我已经设法创建了一个虚拟的IOPCIDevice,它附加到IOResources并且基本上什么都不做。我能够让现有的驱动程序注册并匹配它。
但是当谈到IO处理时,我遇到了一些麻烦。 IOPCIDevice类中描述的函数(例如configRead,ioRead,configWrite,ioWrite)的IO访问可以由我自己的代码处理。但是使用内存映射和IODMACommand的驱动程序是个问题。
我需要管理两件事:IODeviceMemory(在IOPCIDevice中描述)和DMA传输。
我怎么能创建一个最终指向内存/ RAM的IODeviceMemory,这样当驱动程序尝试与PCI设备通信时,它最终什么也不做,或者只是将数据移动到RAM,所以我的用户空间客户端可以处理这些数据并充当模拟PCI设备?
然后DMA命令也可以定向到我的用户空间客户端,而不会干扰使用IODMACommand的现有驱动程序的源代码。
谢谢!
捕获内存访问
所以从理论上讲,要实现你想要的,你需要分配一个内存区域,将其保护位设置为只读(如果你正在模拟的设备中的读取有副作用,则可能既不读也不写),以及然后将任何写入捕获到您自己的处理函数中,然后您将模拟设备寄存器写入。
据我所知,您可以使用Mach异常处理在macOS用户空间中执行此类操作。您需要设置从您正在控制的进程发送到您控制的Mach端口的页面保护错误异常。在该端口的消息处理程序中,您将:
正如我所说,我相信这可以在用户空间流程中完成。这并不容易,你可以通过网络上的各种晦涩的例子来拼凑你需要使用的马赫调用。我有类似的工作曾经,但似乎无法找到那个代码,对不起。
......在内核中
现在,另一个问题是你在内核中尝试这样做。我不知道有任何公开的KPI可以让你做任何像我上面所述的事情。你可以在以下地方寻找黑客:
IOMemoryDescriptor
s支持系统内存。不要担心IODeviceMemory
术语:这些只是IOMemoryDescriptor
对象; the IODeviceMemory
class is a lie。陷阱访问完全是另一回事。原则上,您可以使用createMappingInTask()
函数的“reference”标志找出特定MD存在的虚拟内存映射,然后使用redirect()
支持内存参数在返回的IOMemoryMap
上调用NULL
方法。不幸的是,这只会暂停尝试访问映射的任何线程。发生这种情况时,您不会收到回调。osfmk/vm/
目录中。也许有一种方法可以为那里的VM区域设置自定义故障处理程序。但是,您可能不得不使用私有内核API。为什么?
最后,你为什么要这样做?退后一步:你最终试图用它做什么?看起来以这种方式模拟PCI设备本身并不是一个目的,所以这真的是实现你最终要实现的更大目标的唯一方法吗? See: XY problem