Macos 试图访问PCI内存映射寄存器时OS X内核死机
我指的代码是 当我为pcidevice创建内存映射时,我总是得到与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成员的任何访
getPhysicalAddress
和getVirtualAddress
相同的值:
e、 g
事实上,我对此并不感到惊讶,因为我认为这就是“DMA”的意义所在
- 如果我们在驱动程序中有某种映射,那么我们只需要一个。
- 也就是说,physicaladdress是虚拟地址,因为它是我们进行“内存到内存”(cpu数据存储到PCI声卡)的唯一位置
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范围