static VOID NTAPI V4vDehibernateWorkItem(PDEVICE_OBJECT fdo, PVOID ctx) { PIO_WORKITEM wi = (PIO_WORKITEM)ctx; if (xenbus_await_initialisation()) { (VOID)V4vInitializeEventChannel(fdo); TraceNotice(("dehibrination work item initialized VIRQ.\n")); } else { TraceError(("wait for XENBUS initialization failed, cannot connect VIRQ.\n")); } IoFreeWorkItem(wi); }
BOOLEAN XenLowerInit( PXEN_LOWER XenLower, PVOID XenUpper, PDEVICE_OBJECT Pdo) { PCHAR path; NTSTATUS status; XenLower->XenUpper = XenUpper; XenLower->Pdo = Pdo; // // Wait for xenbus to come up. SMP guests sometimes try and // initialise xennet and xenvbd in parallel when they come back // from hibernation, and that causes problems. // if (!xenbus_await_initialisation()) { TraceError((__FUNCTION__ ": xenbus_await_initialisation() failed?\n")); return FALSE; } path = xenbus_find_frontend(Pdo); if (path == NULL) { TraceError((__FUNCTION__ ": xenbus_find_frontend() failed to return the front end path, fatal.\n")); return FALSE; } status = RtlStringCchCopyA(XenLower->FrontendPath, sizeof(XenLower->FrontendPath), path); XmFreeMemory(path); if (status != STATUS_SUCCESS) { XenLower->FrontendPath[0] = 0; TraceError((__FUNCTION__ ": Failed to copy front end path - status: 0x%x\n", status)); return FALSE; } return TRUE; }
NDIS_STATUS MiniportInitialize ( IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE MiniportDriverContext, IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters ) { PADAPTER adapter = NULL; NDIS_STATUS ndisStatus; PCHAR path; PDEVICE_OBJECT pdo; PCHAR xenbusPath = NULL; int i; UNREFERENCED_PARAMETER(MiniportDriverContext); UNREFERENCED_PARAMETER(MiniportInitParameters); TraceVerbose(("====> '%s'.\n", __FUNCTION__)); // // Wait for xenbus to come up. SMP guests sometimes try and // initialise xennet and xenvbd in parallel when they come back // from hibernation, and that causes problems. // if (!xenbus_await_initialisation()) { ndisStatus = NDIS_STATUS_DEVICE_FAILED; goto exit; } // // 8021P support is disabled by default. // It can be turned on by specifying the appropriate PV boot option. // if (XenPVFeatureEnabled(DEBUG_NIC_8021_P)) { XennetMacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY; } xenbus_write(XBT_NIL, "drivers/xenwnet", XENNET_VERSION); NdisMGetDeviceProperty(MiniportAdapterHandle, &pdo, NULL, NULL, NULL, NULL); xenbusPath = xenbus_find_frontend(pdo); if (!xenbusPath) { ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND; goto exit; } TraceNotice(("Found '%s' frontend.\n", xenbusPath)); adapter = XmAllocateZeroedMemory(sizeof(ADAPTER)); if (adapter == NULL) { ndisStatus = NDIS_STATUS_RESOURCES; goto exit; } path = xenbusPath; xenbusPath = NULL; i = 0; do { ndisStatus = AdapterInitialize(adapter, MiniportAdapterHandle, path); if (ndisStatus != NDIS_STATUS_SUCCESS) { TraceWarning (("Waiting for backend...\n")); NdisMSleep (1000000); // 1 sec } } while ((ndisStatus != NDIS_STATUS_SUCCESS) && (++i < 30)); if (ndisStatus != NDIS_STATUS_SUCCESS) { goto exit; } exit: if (ndisStatus != NDIS_STATUS_SUCCESS) { if (adapter) { XmFreeMemory(adapter->BackendPath); adapter->BackendPath = NULL; AdapterDelete(&adapter); } if (xenbusPath) { XmFreeMemory(xenbusPath); } } TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return ndisStatus; }
NTSTATUS v2v_listen(const char *xenbus_prefix, struct v2v_channel **channel, unsigned prod_ring_page_order, unsigned cons_ring_page_order, struct v2v_async *async_values) { NTSTATUS status = STATUS_SUCCESS; unsigned prod_ring_size = PAGE_SIZE << prod_ring_page_order; unsigned cons_ring_size = PAGE_SIZE << cons_ring_page_order; struct v2v_channel *chan; xenbus_transaction_t xbt = {0}; BOOLEAN xbt_pending = FALSE; PHYSICAL_ADDRESS pa; unsigned x; unsigned xen_receive_port, xen_send_port; uint32_t xen_gref; XM_ASSERT(channel != NULL); XM_ASSERT(xenbus_prefix != NULL); if (prod_ring_page_order > MAX_RING_PAGE_ORDER || cons_ring_page_order > MAX_RING_PAGE_ORDER) return STATUS_INVALID_PARAMETER; if (async_values && (!async_values->receive_dpc || !async_values->send_dpc)) return STATUS_INVALID_PARAMETER; *channel = NULL; if (!xenbus_await_initialisation()) return STATUS_NO_SUCH_DEVICE; chan = v2v_make_channel(xenbus_prefix, async_values); if (!chan) return STATUS_NO_MEMORY; chan->is_temple = TRUE; chan->prod_sring = ExAllocatePoolWithTag(NonPagedPool, prod_ring_size, V2V_TAG); chan->cons_sring = ExAllocatePoolWithTag(NonPagedPool, cons_ring_size, V2V_TAG); chan->control = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, V2V_TAG); if (!chan->prod_sring || !chan->cons_sring || !chan->control) goto err_nomem; RtlZeroMemory(chan->prod_sring, prod_ring_size); RtlZeroMemory((void *)chan->cons_sring, cons_ring_size); RtlZeroMemory(chan->control, PAGE_SIZE); chan->nr_prod_ring_pages = 1 << prod_ring_page_order; chan->nr_cons_ring_pages = 1 << cons_ring_page_order; /* pre-allocate the granf refs we are going to need below in a grant cache */ chan->u.temple.grant_cache = GnttabAllocCache(chan->nr_prod_ring_pages + chan->nr_cons_ring_pages + 1); if (!chan->u.temple.grant_cache) goto err_nomem; v2v_nc2_attach_rings_temple(&chan->nc2_rings, chan->cons_sring, cons_ring_size, chan->prod_sring, prod_ring_size, chan->control); for (;;) { xenbus_transaction_start(&xbt); xbt_pending = TRUE; status = v2v_connect_channel_xenbus(chan, xbt); if (!NT_SUCCESS(status)) goto err; for (x = 0; x < 1u << prod_ring_page_order; x++) { pa = MmGetPhysicalAddress((void *)((ULONG_PTR)chan->prod_sring + x * PAGE_SIZE)); chan->u.temple.prod_grefs[x] = GnttabGrantForeignAccessCache(chan->peer_domid, PHYS_TO_PFN(pa), GRANT_MODE_RO, chan->u.temple.grant_cache); XM_ASSERT(!is_null_GRANT_REF(chan->u.temple.prod_grefs[x])); status = v2v_write_grantref(chan, xbt, x, TRUE); if (!NT_SUCCESS(status)) goto err; } for (x = 0; x < 1u << cons_ring_page_order; x++) { pa = MmGetPhysicalAddress((void *)((ULONG_PTR)chan->cons_sring + x * PAGE_SIZE)); chan->u.temple.cons_grefs[x] = GnttabGrantForeignAccessCache(chan->peer_domid, PHYS_TO_PFN(pa), GRANT_MODE_RW, chan->u.temple.grant_cache); XM_ASSERT(!is_null_GRANT_REF(chan->u.temple.cons_grefs[x])); status = v2v_write_grantref(chan, xbt, x, FALSE); if (!NT_SUCCESS(status)) goto err; } pa = MmGetPhysicalAddress((void *)((ULONG_PTR)chan->control)); chan->u.temple.control_gref = GnttabGrantForeignAccessCache(chan->peer_domid, PHYS_TO_PFN(pa), GRANT_MODE_RW, chan->u.temple.grant_cache); XM_ASSERT(!is_null_GRANT_REF(chan->u.temple.control_gref)); chan->receive_evtchn_port = EvtchnAllocUnboundDpc(chan->peer_domid, (chan->is_sync ? v2v_dpc : async_values->receive_dpc), (chan->is_sync ? &chan->s.sync.receive_event : async_values->receive_ctx)); if (is_null_EVTCHN_PORT(chan->receive_evtchn_port)) { status = STATUS_INSUFFICIENT_RESOURCES; goto err; } xen_receive_port = xen_EVTCHN_PORT(chan->receive_evtchn_port); chan->send_evtchn_port = EvtchnAllocUnboundDpc(chan->peer_domid, (chan->is_sync ? v2v_dpc : async_values->send_dpc), (chan->is_sync ? &chan->s.sync.send_event : async_values->send_ctx)); if (is_null_EVTCHN_PORT(chan->send_evtchn_port)) { status = STATUS_INSUFFICIENT_RESOURCES; goto err; } xen_send_port = xen_EVTCHN_PORT(chan->send_evtchn_port); xen_gref = xen_GRANT_REF(chan->u.temple.control_gref); status = v2v_xenstore_scatter(xbt, chan->local_prefix, "prod-order", xenstore_scatter_type_int, prod_ring_page_order, "cons-order", xenstore_scatter_type_int, cons_ring_page_order, "control-gref", xenstore_scatter_type_grant_ref, xen_gref, "prod-evtchn",xenstore_scatter_type_evtchn_port, xen_send_port, "cons-evtchn",xenstore_scatter_type_evtchn_port, xen_receive_port, NULL); if (!NT_SUCCESS(status)) goto err; status = v2v_change_local_state(chan, xbt, v2v_state_listening); if (!NT_SUCCESS(status)) goto err; status = xenbus_transaction_end(xbt, 0); xbt_pending = FALSE; if (NT_SUCCESS(status)) break; if (status != STATUS_RETRY) goto err; /* cleanup for retry */ for (x = 0; x < 1u << prod_ring_page_order; x++) { GnttabEndForeignAccessCache(chan->u.temple.prod_grefs[x], chan->u.temple.grant_cache); } RtlZeroMemory(chan->u.temple.prod_grefs, sizeof(chan->u.temple.prod_grefs)); for (x = 0; x < 1u << cons_ring_page_order; x++) { GnttabEndForeignAccessCache(chan->u.temple.cons_grefs[x], chan->u.temple.grant_cache); } RtlZeroMemory(chan->u.temple.cons_grefs, sizeof(chan->u.temple.cons_grefs)); GnttabEndForeignAccessCache(chan->u.temple.control_gref, chan->u.temple.grant_cache); chan->u.temple.control_gref = null_GRANT_REF(); EvtchnClose(chan->receive_evtchn_port); chan->receive_evtchn_port = null_EVTCHN_PORT(); EvtchnClose(chan->send_evtchn_port); chan->send_evtchn_port = null_EVTCHN_PORT(); xenbus_unregister_watch(chan->remote_state_watch); chan->remote_state_watch = NULL; ExFreePoolWithTag(chan->remote_prefix, V2V_TAG); chan->remote_prefix = NULL; } *channel = chan; return STATUS_SUCCESS; err_nomem: status = STATUS_NO_MEMORY; err: if (xbt_pending) xenbus_transaction_end(xbt, 1); /* since the channel has never been connected here, it is safe to free any temple resources that may have been allocated in this routine */ v2v_destroy_channel(chan, TRUE); return status; }