Macos 试图访问PCI内存映射寄存器时OS X内核死机

Macos 试图访问PCI内存映射寄存器时OS X内核死机,macos,kernel,iokit,pci,kernel-extension,Macos,Kernel,Iokit,Pci,Kernel Extension,我指的代码是 当我为pcidevice创建内存映射时,我总是得到与getPhysicalAddress和getVirtualAddress相同的值: e、 g 事实上,我对此并不感到惊讶,因为我认为这就是“DMA”的意义所在 如果我们在驱动程序中有某种映射,那么我们只需要一个。 也就是说,physicaladdress是虚拟地址,因为它是我们进行“内存到内存”(cpu数据存储到PCI声卡)的唯一位置 这种理解正确吗 现在来看主要问题:我正在经历由DeviceRegister成员的任何访

我指的代码是

当我为pcidevice创建内存映射时,我总是得到与
getPhysicalAddress
getVirtualAddress
相同的值: e、 g

事实上,我对此并不感到惊讶,因为我认为这就是“DMA”的意义所在

  • 如果我们在驱动程序中有某种映射,那么我们只需要一个。
    • 也就是说,physicaladdress是虚拟地址,因为它是我们进行“内存到内存”(cpu数据存储到PCI声卡)的唯一位置
这种理解正确吗

现在来看主要问题:我正在经历由DeviceRegister成员的任何访问或分配引起的内核恐慌,例如:

kprintf("Xonar Vendor ID:0x%04x, Device ID:0x%04x, SubDevice ID:0x%04x, Physical Address:%lu\n",
       vendor_id, dev_id, subdev_id, deviceRegisters->addr);
这告诉我,我在分配方面做错了什么,因为访问这个结构的成员不应该引起恐慌

但是,如果您在这里查看清单3-2:

这正是应该怎么做的

一位智者(pmj)建议我必须使用ioRead/Write函数来分配/访问这些值,但这与苹果公司提供的(公认的旧)框架代码并不完全一致。什么可能导致对该内存映射的访问问题?当然,必须执行指针算法来分配/读取值(虽然可能是正确的),这不是本设计的目的吗

当我为pcidevice创建内存映射时,我总是得到GetPhysicaAddress和getVirtualAddress的相同值:例如

这些值是否在
0x0..0xffff
范围内

我强烈怀疑这是一个,而不是一个内存映射范围

在代码中检查这一点的方法是:

if (0 != (kIOPCIIOSpace & pciDevice->configRead32(kIOPCIConfigBaseAddress0))
{
    // port mapped range
}
else
{
    // memory mapped range
}
另见:

事实上,我对此并不感到惊讶,因为我认为这就是“DMA”的意义所在

不,端口映射I/O与DMA几乎相反。如果您的设备恰好是这样运行的,您当然可以使用端口映射I/O来启动DMA传输,所以最好将其表述为与DMA正交

DMA是关于直接访问系统内存的设备。PCI条是关于CPU访问设备寄存器或内存的

如果我们在驱动程序中有某种映射,那么我们只需要一个。 也就是说,physicaladdress是虚拟地址,因为它是我们进行“内存到内存”(cpu数据存储到PCI声卡)的唯一位置 这种理解正确吗

不,至少在x86上,I/O端口地址空间与物理内存地址空间完全分离,因此也无法映射到虚拟地址空间,因为MMU在虚拟内存空间和物理内存空间之间转换。在x86上,有专门的机器指令,
in
out
,用于从I/O端口读写。然而,在大多数体系结构上(对于OSX尤其是PPC,但我认为ARM也是如此),存在某种形式的内存映射。我不知道它在这些体系结构上是如何工作的,但就本问题而言,您不需要关心:

在macOS kext中对端口映射范围执行I/O的独立于体系结构的方法是在
IOPCDevice
上使用
ioread*
iowrite*
方法,其中
*
可以是
8
16
32
,用于PCI标准允许的3种不同的I/O字大小

现在来看主要问题:我正在经历由DeviceRegister成员的任何访问或分配引起的内核恐慌,例如:

kprintf("Xonar Vendor ID:0x%04x, Device ID:0x%04x, SubDevice ID:0x%04x, Physical Address:%lu\n",
       vendor_id, dev_id, subdev_id, deviceRegisters->addr);
假设您实际上正在处理设备中的端口映射I/O范围,那么这就解释了您的内核恐慌。使用
pciDevice->ioread16(寄存器偏移,设备映射)
或类似工具

一位智者(pmj)建议我必须使用ioRead/Write函数来分配/访问这些值,但这与苹果公司提供的(公认的旧)框架代码并不完全一致

您链接到的文档假定设备栏所指的是内存映射范围,而不是端口映射的I/O范围