Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}