[尝试访问PCI内存映射的寄存器时,OS X内核出现紧急情况

问题描述 投票:0回答:1

我指的是here

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

pciDevice = OSDynamicCast(IOPCIDevice, provider);
deviceMap = pciDevice->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0);

deviceRegisters = (struct oxygen *)  deviceMap->getVirtualAddress();
pciDevice->setMemoryEnable(true);
pciDevice->setBusMasterEnable(true);
deviceMap->getPhysicalAddress();

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

  • 如果驱动程序中有某种映射,那么就是我们所需要的。
    • 即物理地址虚拟地址,因为它是我们要做“内存到内存”(cpu数据存储到PCI声卡)的唯一位置]

这种理解正确吗?

现在是主要问题:我正在遇到由deviceRegisters成员的任何访问或分配引起的内核恐慌,例如:

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:https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/WritingAudioDrivers/ImplementDriver/ImplementDriver.html#//apple_ref/doc/uid/TP30000732-DontLinkElementID_15

这正是应该完成的方式。

一个聪明的人(pmj)建议我必须使用ioRead / Write函数来分配/访问这些值,但这与Apple提供的(被认为是很旧的)框架代码并不一致。什么会导致对此内存映射的访问问题?当然必须做指针算术来分配/读取值,尽管可能正确,但这不是设计的目的吗?

c macos kernel pci mach
1个回答
0
投票

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

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

我非常怀疑这是一个port-mapped I/O range in your PCI device,而不是内存映射范围。

在您的代码中检查此方法的方式是:

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

另请参见:https://stackoverflow.com/a/44352611/48660

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

不,端口映射的I / O与DMA相反。如果您的设备恰好可以运行,那么您当然可以使用端口映射的I / O发起DMA传输,因此最好将其表述为与DMA正交。

DMA与设备直接访问系统内存有关。 PCI BAR与CPU访问设备寄存器或内存有关。

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

否,至少在x86上,I / O端口地址空间与物理内存地址空间完全分开,因此,由于MMU在虚拟和物理内存之间进行转换,因此也无法映射到虚拟地址空间。 空格。在x86上,有特殊的机器指令inout,用于从I / O端口读取和写入。但是,在大多数体系结构(对于OS X尤其是PPC)上,存在某种形式的内存映射。

在macOS kext中,与体系结构无关的方法是在ioread*上使用iowrite*IOPCIDevice方法,其中*可以是81632 PCI标准允许的3种不同的I / O字长。

现在是主要问题:我正在遇到由deviceRegisters成员的任何访问或分配引起的内核恐慌,例如:

假设您实际上正在处理设备中的端口映射I / O范围,那么这说明了您的内核崩溃。使用pciDevice->ioread16(register_offset, deviceMap)或类似名称。

一个聪明的人(pmj)建议我必须使用ioRead / Write函数来分配/访问这些值,但这与Apple提供的(被认为是很旧的)框架代码并不一致。

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

© www.soinside.com 2019 - 2024. All rights reserved.