【发布时间】:2021-11-12 17:29:58
【问题描述】:
如何将 PCI 基地址寄存器 (BAR) 从 PCIDriverKit 驱动程序 (DEXT) 内存映射到用户空间应用程序?
从驱动程序扩展到应用程序的内存映射可以通过在用户客户端子类(在驱动程序端)中实现IOUserClient::CopyClientMemoryForType,然后调用IOConnectMapMemory64(从用户空间应用程序端)。这在this related answer 中得到了非常好的和彻底的解释。
唯一缺少的位是获取与所需 PCI BAR 相对应的 IOMemoryDescriptor,以便从 CopyClientMemoryForType 实现中返回它。
示例代码
换一种方式问,给定下面的简化代码,imaginaryFunctionWhichReturnsTheBARBuffer的实现会是什么?
kern_return_t IMPL(MyUserClient, CopyClientMemoryForType) //(uint64_t type, uint64_t *options, IOMemoryDescriptor **memory)
{
IOMemoryDescriptor* buffer = nullptr;
imaginaryFunctionWhichReturnsTheBARBuffer(ivars->pciDevice /* IOPCIDevice */, kPCIMemoryRangeBAR0, &buffer);
*memory = buffer;
return kIOReturnSuccess;
}
在前面的代码中ivars->pciDevice指的是一个现成的IOPCIDevice(如:已成功匹配,根据latest best practices打开配置)。
这意味着已经可以使用各种configuration 和memory 读/写方法来访问所需PCI BAR 内存的显式偏移量。缺少(或不清楚)的是如何使用这些 API(或等效的 API)将对应于 PCI BAR 的整个缓冲区映射到用户空间应用程序。
可能相关或不相关的随机注释
-
This answer 来自相关问题:How to allocate memory in a DriverKit system extension and map it to another process? 包含以下引用:
[...] 返回的内存描述符不必是我在示例中使用的 IOBufferMemoryDescriptor,它也可以是 PCI BAR 或其他。
这正是我想做的,所以至少听起来应该是可能的。剩下的唯一问题是如何实现它。
-
A similar question 已发布在 Apple 论坛上,尽管尚未收到任何答复(截至撰写本文时),但它确实包含一些有用的提示。
在 PCIDriverKit 中似乎有一个 private 函数,其签名如下:
virtual kern_return_t IOPCIDevice::_CopyDeviceMemoryWithIndex(uint64_t memoryIndex, IOMemoryDescriptor** memory, IOService* forClient)很难说出它应该做什么(因为它没有记录),但签名似乎与我正在寻找的功能相匹配。但是,尝试使用它总是会导致错误代码(类似于原始论坛帖子中报告的错误代码)。错误代码似乎有所不同,具体取决于作为
IOService *forClient传递的参数。该帖子的另一个好处是,有一个可用于内核扩展 (KEXT) 的 getDeviceMemoryWithIndex 可用于完成我们需要的工作(如果驱动程序是作为 PCI 内核实现的现在似乎已弃用的扩展名)。
但是,此功能似乎不适用于驱动程序扩展 (DEXT)。因此,构建这个问题的另一个问题可能是:PCIDriverKit 驱动程序扩展的等效
getDeviceMemoryWithIndex是什么?
【问题讨论】:
标签: c++ macos iokit driverkit macos-system-extension