/** * Create event channel * * @v netfront Netfront device * @ret rc Return status code */ static int netfront_create_event ( struct netfront_nic *netfront ) { struct xen_device *xendev = netfront->xendev; struct xen_hypervisor *xen = xendev->xen; struct evtchn_alloc_unbound alloc_unbound; struct evtchn_close close; int xenrc; int rc; /* Allocate event */ alloc_unbound.dom = DOMID_SELF; alloc_unbound.remote_dom = xendev->backend_id; if ( ( xenrc = xenevent_alloc_unbound ( xen, &alloc_unbound ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( netfront, "NETFRONT %s could not allocate event: %s\n", xendev->key, strerror ( rc ) ); goto err_alloc_unbound; } netfront->event.port = alloc_unbound.port; /* Publish event channel */ if ( ( rc = netfront_write_num ( netfront, "event-channel", netfront->event.port ) ) != 0 ) goto err_write_num; DBGC ( netfront, "NETFRONT %s event-channel=\"%d\"\n", xendev->key, netfront->event.port ); return 0; netfront_rm ( netfront, "event-channel" ); err_write_num: close.port = netfront->event.port; xenevent_close ( xen, &close ); err_alloc_unbound: return rc; }
/** * Send XenStore request * * @v xen Xen hypervisor * @v type Message type * @v req_id Request ID * @v value Value, or NULL to omit * @v key Key path components * @ret rc Return status code */ static int xenstore_request ( struct xen_hypervisor *xen, enum xsd_sockmsg_type type, uint32_t req_id, const char *value, va_list key ) { struct xsd_sockmsg msg; struct evtchn_send event; const char *string; va_list tmp; int xenrc; int rc; /* Construct message header */ msg.type = type; msg.req_id = req_id; msg.tx_id = 0; msg.len = 0; DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type ); /* Calculate total length */ va_copy ( tmp, key ); while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) { DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string ); msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ ); } va_end ( tmp ); if ( value ) { DBGC2 ( xen, " = \"%s\"", value ); msg.len += strlen ( value ); } DBGC2 ( xen, "\n" ); /* Send message */ xenstore_send ( xen, &msg, sizeof ( msg ) ); string = va_arg ( key, const char * ); assert ( string != NULL ); xenstore_send_string ( xen, string ); while ( ( string = va_arg ( key, const char * ) ) != NULL ) { xenstore_send_string ( xen, "/" ); xenstore_send_string ( xen, string ); } xenstore_send ( xen, "", 1 ); /* Separating NUL */ if ( value ) xenstore_send_string ( xen, value ); /* Notify the back end */ event.port = xen->store.port; if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( xen, "XENSTORE could not notify back end: %s\n", strerror ( rc ) ); return rc; } return 0; }
/** * Send event * * @v netfront Netfront device * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int netfront_send_event ( struct netfront_nic *netfront ) { struct xen_device *xendev = netfront->xendev; struct xen_hypervisor *xen = xendev->xen; int xenrc; int rc; /* Send event */ if ( ( xenrc = xenevent_send ( xen, &netfront->event ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( netfront, "NETFRONT %s could not send event: %s\n", xendev->key, strerror ( rc ) ); return rc; } return 0; }
/** * Initialise grant table * * @v xen Xen hypervisor * @ret rc Return status code */ int xengrant_init ( struct xen_hypervisor *xen ) { struct gnttab_query_size size; struct gnttab_set_version set_version; struct gnttab_get_version get_version; struct grant_entry_v1 *v1; union grant_entry_v2 *v2; unsigned int version; int xenrc; int rc; /* Get grant table size */ size.dom = DOMID_SELF; if ( ( xenrc = xengrant_query_size ( xen, &size ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( xen, "XENGRANT could not get table size: %s\n", strerror ( rc ) ); return rc; } xen->grant.len = ( size.nr_frames * PAGE_SIZE ); /* Set grant table version, if applicable */ set_version.version = XENGRANT_TRY_VERSION; if ( ( xenrc = xengrant_set_version ( xen, &set_version ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( xen, "XENGRANT could not set version %d: %s\n", XENGRANT_TRY_VERSION, strerror ( rc ) ); /* Continue; use whatever version is current */ } /* Get grant table version */ get_version.dom = DOMID_SELF; get_version.pad = 0; if ( ( xenrc = xengrant_get_version ( xen, &get_version ) ) == 0 ) { version = get_version.version; switch ( version ) { case 0: /* Version not yet specified: will be version 1 */ version = 1; break; case 1 : /* Version 1 table: nothing special to do */ break; case 2: /* Version 2 table: configure shift appropriately */ xen->grant.shift = ( fls ( sizeof ( *v2 ) / sizeof ( *v1 ) ) - 1 ); break; default: /* Unsupported version */ DBGC ( xen, "XENGRANT detected unsupported version " "%d\n", version ); return -ENOTSUP; } } else { rc = -EXEN ( xenrc ); DBGC ( xen, "XENGRANT could not get version (assuming v1): " "%s\n", strerror ( rc ) ); version = 1; } DBGC ( xen, "XENGRANT using v%d table with %d entries\n", version, xengrant_entries ( xen ) ); return 0; }