windows kdmf driver virtio calling virtqueue_add_buf causes system fatal error

1

I have a driver for Windows VM that allows user space apps to communicate via IOCTL. I need to expose a structure to the host (using virtio) and I have tried using virtqueue_add_buf after initializing the virt device in the EvtDevicePrepareHardware using VirtIODeviceInitialize function. I am getting a fatal error when calling virtqueue_add_buf.

Below is a snippet of code

int TellHost(WDFOBJECT WdfDevice, VirtioQArg *virtioArg)
{
    VIO_SG              sg;
    PDEVICE_CONTEXT     context = GetDeviceContext(WdfDevice);
    sg.physAddr = MmGetPhysicalAddress(virtioArg);
    sg.length = sizeof(VirtioQCArg);

    WdfSpinLockAcquire(context->VirtQueueLock);
    error = virtqueue_add_buf(context->VirtQueue, &sg, 1, 0, virtioArg, NULL, 0);
    // more code ....
    WdfSpinLockRelease(context->VirtQueueLock);
}

The error I get is Fatal System Error: 0x000000d1 (0x0000000000000014,0x0000000000000002,0x0000000000000000,0xFFFFF80109FC0637)

Break instruction exception - code 80000003 (first chance)

and then windbg is unable to load symbols and crashes making my debugging session useless. Any ideas how I can debug this or what I might be missing?

windbg
drivers
kmdf
asked on Stack Overflow Apr 25, 2016 by Luis

1 Answer

2

0x000000d1 is DRIVER_IRQL_NOT_LESS_OR_EQUAL which almost always means invalid address is being referenced or addressing paged memory at DPC IRQL or higher.

0x0000000000000000 is a read access to invalid address (0x0000000000000014) from IRQL 2 (DPC).

I had not initialized the queue. Thanks to Vadim RozenFeld from Redhat for pointing out my mistake and his precise explanation.

I checked the balloon virtio driver which uses the following function for initialization of virtio queue.

PVIOQUEUE FindVirtualQueue(VIODEVICE *dev, ULONG index)
{
    PVIOQUEUE  pq = NULL;
    PVOID p;
    ULONG size, allocSize;
    VirtIODeviceQueryQueueAllocation(dev, index, &size, &allocSize);
    if (allocSize)
    {
        PHYSICAL_ADDRESS HighestAcceptable;
        HighestAcceptable.QuadPart = 0xFFFFFFFFFF;
        p = MmAllocateContiguousMemory(allocSize, HighestAcceptable);
        if (p)
        {
            pq = VirtIODevicePrepareQueue(dev, index, MmGetPhysicalAddress(p), p, allocSize, p, FALSE);
        }
    }
    return pq;
}
answered on Stack Overflow Apr 26, 2016 by Luis

User contributions licensed under CC BY-SA 3.0