via*_*lly 9 c++ macos iokit macos-system-extension driverkit
如何将 PCI 基地址寄存器 (BAR) 从 PCIDriverKit 驱动程序 (DEXT) 内存映射到用户空间应用程序?
从驱动程序扩展到应用程序的内存映射可以通过在用户客户端子类(在驱动程序端)中实现IOUserClient::CopyClientMemoryForType然后调用IOConnectMapMemory64(从用户空间应用程序端)来完成。这在相关的答案中已经得到了非常好的和彻底的解释。
唯一缺少的一点是获取与所需 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;
}
Run Code Online (Sandbox Code Playgroud)
前面的代码ivars->pciDevice中指的是一个现成的IOPCIDevice(例如:它已经根据最新的最佳实践成功匹配、打开和配置)。
这意味着已经可以使用各种配置和内存读/写方法来访问所需 PCI BAR 内存的显式偏移量。缺少(或不清楚)的是如何使用这些 API(或等效 API)将与 PCI BAR 对应的整个缓冲区映射到用户空间应用程序。
此答案来自相关问题:How to allocate memory in a DriverKit system extension and map it to another process? 包含以下引用:
[...] 返回的内存描述符不必是我在示例中使用的 IOBufferMemoryDescriptor,它也可以是 PCI BAR 或其他任何东西。
这正是我想做的,所以至少听起来应该是可能的。唯一剩下的问题是如何实施它。
苹果论坛上也发布了类似的问题,尽管尚未收到任何答案(截至撰写本文时),但它确实包含一些有用的提示。
看起来 PCIDriverKit 中有一个私有函数,其签名如下:
virtual kern_return_t IOPCIDevice::_CopyDeviceMemoryWithIndex(uint64_t memoryIndex, IOMemoryDescriptor** memory, IOService* forClient)
Run Code Online (Sandbox Code Playgroud)
很难说出它到底应该做什么(因为它没有记录),但签名似乎确实与我正在寻找的函数匹配。但是,尝试使用它总是会导致错误代码(类似于原始论坛帖子中报告的错误代码)。错误代码似乎有所不同,具体取决于作为IOService *forClient) 传递的参数。
这篇文章的另一个优点是,有一个可用于内核扩展(KEXT)的getDeviceMemoryWithIndex,它可以用来完成我们需要的事情(如果驱动程序是作为 PCI 内核扩展实现的,现在似乎已弃用)。
但是,此功能似乎不适用于驱动程序扩展(DEXT)。因此,构建这个问题的另一个问题可能是:getDeviceMemoryWithIndexPCIDriverKit 驱动程序扩展的等效项是什么?
事实证明IOPCIDevice::_CopyDeviceMemoryWithIndex确实是实现这个所需的函数(但事实上它是私有的仍然是一个不方便的地方)。
下面是一些示例代码,展示了如何实现这一点(该代码用于MyDriver驱动程序类名称和MyDriverUserClient用户客户端)。
实施的相关部分MyDriver.cpp:
struct MyDriver_IVars {
IOPCIDevice* pciDevice = nullptr;
};
// MyDriver::init/free/Start/Stop/NewUserClient implementation ommited for brevity
IOMemoryDescriptor* MyDriver::copyBarMemory(uint8_t barIndex)
{
IOMemoryDescriptor* memory;
uint8_t barMemoryIndex, barMemoryType;
uint64_t barMemorySize;
// Warning: error handling is omitted for brevity
ivars->pciDevice->GetBARInfo(barIndex, &barMemoryIndex, &barMemorySize, &barMemoryType);
ivars->pciDevice->_CopyDeviceMemoryWithIndex(barMemoryIndex, &memory, this);
return memory;
}
Run Code Online (Sandbox Code Playgroud)
实施的相关部分MyDriverUserClient.cpp:
struct MyDriverUserClient_IVars {
MyDriver* myDriver = nullptr;
};
// MyDriverUserClient::init/free/Start/Stop implementation ommited for brevity
kern_return_t
IMPL(MyDriverUserClient, CopyClientMemoryForType) //(uint64_t type, uint64_t *options, IOMemoryDescriptor **memory)
{
*memory = ivars->myDriver->copyBARMemory(kPCIMemoryRangeBAR0);
return kIOReturnSuccess;
}
Run Code Online (Sandbox Code Playgroud)
使用此模式的完整实现可以在ivshmem.dext项目(它实现了IVSHMEM的 macOS 驱动程序)中找到。
| 归档时间: |
|
| 查看次数: |
903 次 |
| 最近记录: |