我有一个Windows VM驱动程序,允许用户空间应用程序通过IOCTL进行通信。我需要向主机公开一个结构(使用virtio),并且在使用virtqueue_add_buf
函数初始化EvtDevicePrepareHardware
中的virt设备后,我尝试使用VirtIODeviceInitialize
。在致电virtqueue_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无法加载符号和崩溃,使我的调试会话无用。我有什么想法可以调试这个或者我可能缺少什么?
答案 0 :(得分:1)
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;
}