iPXE
Defines | Functions
xenbus.c File Reference

Xen device bus. More...

#include <stdio.h>
#include <errno.h>
#include <ipxe/malloc.h>
#include <ipxe/device.h>
#include <ipxe/timer.h>
#include <ipxe/nap.h>
#include <ipxe/xen.h>
#include <ipxe/xenstore.h>
#include <ipxe/xenbus.h>

Go to the source code of this file.

Defines

#define ETIMEDOUT_UNKNOWN   __einfo_error ( EINFO_ETIMEDOUT_UNKNOWN )
#define EINFO_ETIMEDOUT_UNKNOWN
#define ETIMEDOUT_INITIALISING   __einfo_error ( EINFO_ETIMEDOUT_INITIALISING )
#define EINFO_ETIMEDOUT_INITIALISING
#define ETIMEDOUT_INITWAIT   __einfo_error ( EINFO_ETIMEDOUT_INITWAIT )
#define EINFO_ETIMEDOUT_INITWAIT
#define ETIMEDOUT_INITIALISED   __einfo_error ( EINFO_ETIMEDOUT_INITIALISED )
#define EINFO_ETIMEDOUT_INITIALISED
#define ETIMEDOUT_CONNECTED   __einfo_error ( EINFO_ETIMEDOUT_CONNECTED )
#define EINFO_ETIMEDOUT_CONNECTED
#define ETIMEDOUT_CLOSING   __einfo_error ( EINFO_ETIMEDOUT_CLOSING )
#define EINFO_ETIMEDOUT_CLOSING
#define ETIMEDOUT_CLOSED   __einfo_error ( EINFO_ETIMEDOUT_CLOSED )
#define EINFO_ETIMEDOUT_CLOSED
#define ETIMEDOUT_RECONFIGURING   __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURING )
#define EINFO_ETIMEDOUT_RECONFIGURING
#define ETIMEDOUT_RECONFIGURED   __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURED )
#define EINFO_ETIMEDOUT_RECONFIGURED
#define ETIMEDOUT_STATE(state)
#define XENBUS_BACKEND_TIMEOUT   ( 5 * TICKS_PER_SEC )
 Maximum time to wait for backend to reach a given state, in ticks.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int xenbus_set_state (struct xen_device *xendev, int state)
 Set device state.
int xenbus_backend_state (struct xen_device *xendev)
 Get backend state.
int xenbus_backend_wait (struct xen_device *xendev, int state)
 Wait for backend to reach a given state.
static struct xen_driverxenbus_find_driver (const char *type)
 Find driver for Xen device.
static int xenbus_probe_device (struct xen_hypervisor *xen, struct device *parent, const char *instance, struct xen_driver *driver)
 Probe Xen device.
static void xenbus_remove_device (struct xen_device *xendev)
 Remove Xen device.
static int xenbus_probe_type (struct xen_hypervisor *xen, struct device *parent, const char *type)
 Probe Xen devices of a given type.
int xenbus_probe (struct xen_hypervisor *xen, struct device *parent)
 Probe Xen bus.
void xenbus_remove (struct xen_hypervisor *xen __unused, struct device *parent)
 Remove Xen bus.

Detailed Description

Xen device bus.

Definition in file xenbus.c.


Define Documentation

Definition at line 43 of file xenbus.c.

Value:

Definition at line 45 of file xenbus.c.

Definition at line 48 of file xenbus.c.

Value:

Definition at line 50 of file xenbus.c.

Definition at line 53 of file xenbus.c.

Value:

Definition at line 55 of file xenbus.c.

Definition at line 58 of file xenbus.c.

Value:

Definition at line 60 of file xenbus.c.

Definition at line 63 of file xenbus.c.

Value:

Definition at line 65 of file xenbus.c.

Definition at line 68 of file xenbus.c.

Value:

Definition at line 70 of file xenbus.c.

Definition at line 73 of file xenbus.c.

Value:

Definition at line 75 of file xenbus.c.

Definition at line 78 of file xenbus.c.

Value:

Definition at line 80 of file xenbus.c.

Definition at line 83 of file xenbus.c.

Value:

Definition at line 85 of file xenbus.c.

#define ETIMEDOUT_STATE (   state)
#define XENBUS_BACKEND_TIMEOUT   ( 5 * TICKS_PER_SEC )

Maximum time to wait for backend to reach a given state, in ticks.

Definition at line 96 of file xenbus.c.

Referenced by xenbus_backend_wait().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int xenbus_set_state ( struct xen_device xendev,
int  state 
)

Set device state.

Parameters:
xendevXen device
stateNew state
Return values:
rcReturn status code

Definition at line 105 of file xenbus.c.

References DBGC, xen_device::key, NULL, rc, strerror(), xen_device::xen, and xenstore_write_num().

Referenced by netfront_open(), and netfront_reset().

                                                              {
        int rc;

        /* Attempt to set state */
        if ( ( rc = xenstore_write_num ( xendev->xen, state, xendev->key,
                                         "state", NULL ) ) != 0 ) {
                DBGC ( xendev, "XENBUS %s could not set state=\"%d\": %s\n",
                       xendev->key, state, strerror ( rc ) );
                return rc;
        }

        return 0;
}
int xenbus_backend_state ( struct xen_device xendev)

Get backend state.

Parameters:
xendevXen device
Return values:
stateBackend state, or negative error

Definition at line 125 of file xenbus.c.

References xen_device::backend, DBGC, xen_device::key, NULL, rc, state, strerror(), xen_device::xen, and xenstore_read_num().

Referenced by netfront_reset(), and xenbus_backend_wait().

                                                       {
        unsigned long state;
        int rc;

        /* Attempt to get backend state */
        if ( ( rc = xenstore_read_num ( xendev->xen, &state, xendev->backend,
                                        "state", NULL ) ) != 0 ) {
                DBGC ( xendev, "XENBUS %s could not read %s/state: %s\n",
                       xendev->key, xendev->backend, strerror ( rc ) );
                return rc;
        }

        return state;
}
int xenbus_backend_wait ( struct xen_device xendev,
int  state 
)

Wait for backend to reach a given state.

Parameters:
xendevXen device
stateDesired backend state
Return values:
rcReturn status code

Definition at line 147 of file xenbus.c.

References xen_device::backend, cpu_nap(), currticks(), DBGC, ETIMEDOUT_STATE, xen_device::key, rc, started, strerror(), xenbus_backend_state(), and XENBUS_BACKEND_TIMEOUT.

Referenced by netfront_open(), and netfront_reset().

                                                                 {
        unsigned long started = currticks();
        unsigned long elapsed;
        unsigned int attempts = 0;
        int current_state;
        int rc;

        /* Wait for backend to reach this state */
        do {

                /* Get current backend state */
                current_state = xenbus_backend_state ( xendev );
                if ( current_state < 0 ) {
                        rc = current_state;
                        return rc;
                }
                if ( current_state == state )
                        return 0;

                /* Allow time for backend to react */
                cpu_nap();

                /* XenStore is a very slow interface; any fixed delay
                 * time would be dwarfed by the XenStore access time.
                 * We therefore use wall clock to time out this
                 * operation.
                 */
                elapsed = ( currticks() - started );
                attempts++;

        } while ( elapsed < XENBUS_BACKEND_TIMEOUT );

        /* Construct status code from current backend state */
        rc = -ETIMEDOUT_STATE ( current_state );
        DBGC ( xendev, "XENBUS %s timed out after %d attempts waiting for "
               "%s/state=\"%d\": %s\n", xendev->key, attempts, xendev->backend,
               state, strerror ( rc ) );

        return rc;
}
static struct xen_driver* xenbus_find_driver ( const char *  type) [static, read]

Find driver for Xen device.

Parameters:
typeDevice type
Return values:
driverDriver, or NULL

Definition at line 194 of file xenbus.c.

References for_each_table_entry, NULL, strcmp(), xen_driver::type, and XEN_DRIVERS.

Referenced by xenbus_probe_type().

                                                                   {
        struct xen_driver *xendrv;

        for_each_table_entry ( xendrv, XEN_DRIVERS ) {
                if ( strcmp ( xendrv->type, type ) == 0 )
                        return xendrv;
        }
        return NULL;
}
static int xenbus_probe_device ( struct xen_hypervisor xen,
struct device parent,
const char *  instance,
struct xen_driver driver 
) [static]

Probe Xen device.

Parameters:
xenXen hypervisor
parentParent device
instanceDevice instance
driverDevice driver
Return values:
rcReturn status code

Definition at line 213 of file xenbus.c.

References xen_device::backend, xen_device::backend_id, device_description::bus_type, BUS_TYPE_XEN, device::children, DBGC, device::desc, xen_device::dev, xen_device::driver, driver, device::driver_name, ENOMEM, free, INIT_LIST_HEAD, xen_device::key, list_add_tail, list_del, xen_driver::name, device::name, NULL, device::parent, xen_driver::probe, rc, xen_driver::remove, device::siblings, snprintf(), strerror(), strlen(), xen_driver::type, type, xen_device::xen, xenstore_read(), xenstore_read_num(), and zalloc().

Referenced by xenbus_probe_type().

                                                             {
        const char *type = driver->type;
        struct xen_device *xendev;
        size_t key_len;
        int rc;

        /* Allocate and initialise structure */
        key_len = ( 7 /* "device/" */ + strlen ( type ) + 1 /* "/" */ +
                    strlen ( instance ) + 1 /* NUL */ );
        xendev = zalloc ( sizeof ( *xendev ) + key_len );
        if ( ! xendev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        snprintf ( xendev->dev.name, sizeof ( xendev->dev.name ), "%s/%s",
                   type, instance );
        xendev->dev.desc.bus_type = BUS_TYPE_XEN;
        INIT_LIST_HEAD ( &xendev->dev.children );
        list_add_tail ( &xendev->dev.siblings, &parent->children );
        xendev->dev.parent = parent;
        xendev->xen = xen;
        xendev->key = ( ( void * ) ( xendev + 1 ) );
        snprintf ( xendev->key, key_len, "device/%s/%s", type, instance );
        xendev->driver = driver;
        xendev->dev.driver_name = driver->name;
        DBGC ( xendev, "XENBUS %s has driver \"%s\"\n", xendev->key,
               xendev->driver->name );

        /* Read backend key */
        if ( ( rc = xenstore_read ( xen, &xendev->backend, xendev->key,
                                    "backend", NULL ) ) != 0 ) {
                DBGC ( xendev, "XENBUS %s could not read backend: %s\n",
                       xendev->key, strerror ( rc ) );
                goto err_read_backend;
        }

        /* Read backend domain ID */
        if ( ( rc = xenstore_read_num ( xen, &xendev->backend_id, xendev->key,
                                        "backend-id", NULL ) ) != 0 ) {
                DBGC ( xendev, "XENBUS %s could not read backend-id: %s\n",
                       xendev->key, strerror ( rc ) );
                goto err_read_backend_id;
        }
        DBGC ( xendev, "XENBUS %s backend=\"%s\" in domain %ld\n",
               xendev->key, xendev->backend, xendev->backend_id );

        /* Probe driver */
        if ( ( rc = xendev->driver->probe ( xendev ) ) != 0 ) {
                DBGC ( xendev, "XENBUS could not probe %s: %s\n",
                       xendev->key, strerror ( rc ) );
                goto err_probe;
        }

        return 0;

        xendev->driver->remove ( xendev );
 err_probe:
 err_read_backend_id:
        free ( xendev->backend );
 err_read_backend:
        list_del ( &xendev->dev.siblings );
        free ( xendev );
 err_alloc:
        return rc;
}
static void xenbus_remove_device ( struct xen_device xendev) [static]

Remove Xen device.

Parameters:
xendevXen device

Definition at line 286 of file xenbus.c.

References xen_device::backend, xen_device::dev, xen_device::driver, free, list_del, xen_driver::remove, and device::siblings.

Referenced by xenbus_remove().

                                                               {

        /* Remove device */
        xendev->driver->remove ( xendev );
        free ( xendev->backend );
        list_del ( &xendev->dev.siblings );
        free ( xendev );
}
static int xenbus_probe_type ( struct xen_hypervisor xen,
struct device parent,
const char *  type 
) [static]

Probe Xen devices of a given type.

Parameters:
xenXen hypervisor
parentParent device
typeDevice type
Return values:
rcReturn status code

Definition at line 303 of file xenbus.c.

References children, DBGC, driver, free, len, NULL, rc, strerror(), strlen(), xenbus_find_driver(), xenbus_probe_device(), and xenstore_directory().

Referenced by xenbus_probe().

                                                                         {
        struct xen_driver *driver;
        char *children;
        char *child;
        size_t len;
        int rc;

        /* Look for a driver */
        driver = xenbus_find_driver ( type );
        if ( ! driver ) {
                DBGC ( xen, "XENBUS has no driver for \"%s\" devices\n", type );
                /* Not a fatal error */
                rc = 0;
                goto err_no_driver;
        }

        /* Get children of this key */
        if ( ( rc = xenstore_directory ( xen, &children, &len, "device",
                                         type, NULL ) ) != 0 ) {
                DBGC ( xen, "XENBUS could not list \"%s\" devices: %s\n",
                       type, strerror ( rc ) );
                goto err_directory;
        }

        /* Probe each child */
        for ( child = children ; child < ( children + len ) ;
              child += ( strlen ( child ) + 1 /* NUL */ ) ) {
                if ( ( rc = xenbus_probe_device ( xen, parent, child,
                                                  driver ) ) != 0 )
                        goto err_probe_device;
        }

        free ( children );
        return 0;

 err_probe_device:
        free ( children );
 err_directory:
 err_no_driver:
        return rc;
}
int xenbus_probe ( struct xen_hypervisor xen,
struct device parent 
)

Probe Xen bus.

Parameters:
xenXen hypervisor
parentParent device
Return values:
rcReturn status code

Definition at line 353 of file xenbus.c.

References DBGC, free, len, NULL, rc, strerror(), strlen(), type, xenbus_probe_type(), xenbus_remove(), and xenstore_directory().

Referenced by hvm_probe().

                                                                       {
        char *types;
        char *type;
        size_t len;
        int rc;

        /* Get children of "device" key */
        if ( ( rc = xenstore_directory ( xen, &types, &len, "device",
                                         NULL ) ) != 0 ) {
                DBGC ( xen, "XENBUS could not list device types: %s\n",
                       strerror ( rc ) );
                goto err_directory;
        }

        /* Probe each child type */
        for ( type = types ; type < ( types + len ) ;
              type += ( strlen ( type ) + 1 /* NUL */ ) ) {
                if ( ( rc = xenbus_probe_type ( xen, parent, type ) ) != 0 )
                        goto err_probe_type;
        }

        free ( types );
        return 0;

        xenbus_remove ( xen, parent );
 err_probe_type:
        free ( types );
 err_directory:
        return rc;
}
void xenbus_remove ( struct xen_hypervisor *xen  __unused,
struct device parent 
)

Remove Xen bus.

Parameters:
xenXen hypervisor
parentParent device

Definition at line 390 of file xenbus.c.

References device::children, xen_device::dev, list_for_each_entry_safe, device::siblings, and xenbus_remove_device().

Referenced by hvm_probe(), hvm_remove(), and xenbus_probe().

                                             {
        struct xen_device *xendev;
        struct xen_device *tmp;

        /* Remove devices */
        list_for_each_entry_safe ( xendev, tmp, &parent->children,
                                   dev.siblings ) {
                xenbus_remove_device ( xendev );
        }
}