1

我有一个 Windows VM 驱动程序,它允许用户空间应用程序通过 IOCTL 进行通信。我需要向主机公开一个结构(使用 virtio),并且在using函数virtqueue_add_buf中初始化 virt 设备后尝试使用。调用时出现致命错误。EvtDevicePrepareHardwareVirtIODeviceInitializevirtqueue_add_buf

下面是一段代码

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);
}

我得到的错误是致命系统错误:0x000000d1(0x0000000000000014,0x0000000000000002,0x0000000000000000,0xFFFFF80109FC0637)

中断指令异常 - 代码 80000003(第一次机会)

然后windbg 无法加载符号和崩溃使我的调试会话无用。有什么想法可以调试这个或我可能缺少什么吗?

4

1 回答 1

2

0x000000d1 是 DRIVER_IRQL_NOT_LESS_OR_EQUAL 这几乎总是意味着在 DPC IRQL 或更高版本中引用了无效地址或寻址分页内存。

0x0000000000000000 是从 IRQL 2 (DPC) 对无效地址 (0x0000000000000014) 的读取访问。

我没有初始化队列。感谢 Redhat 的 Vadim RozenFeld 指出我的错误和他的准确解释。

我检查了使用以下函数初始化 virtio 队列的气球 virtio 驱动程序。

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;
}
于 2016-04-26T15:15:46.950 回答