使用IOKit创建虚拟IOPCIDevice

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

我已经设法创建了一个虚拟的IOPCIDevice,它附加到IOResources并且基本上什么都不做。我能够让现有的驱动程序注册并匹配它。

但是当谈到IO处理时,我遇到了一些麻烦。 IOPCIDevice类中描述的函数(例如configRead,ioRead,configWrite,ioWrite)的IO访问可以由我自己的代码处理。但是使用内存映射和IODMACommand的驱动程序是个问题。

我需要管理两件事:IODeviceMemory(在IOPCIDevice中描述)和DMA传输。

我怎么能创建一个最终指向内存/ RAM的IODeviceMemory,这样当驱动程序尝试与PCI设备通信时,它最终什么也不做,或者只是将数据移动到RAM,所以我的用户空间客户端可以处理这些数据并充当模拟PCI设备?

然后DMA命令也可以定向到我的用户空间客户端,而不会干扰使用IODMACommand的现有驱动程序的源代码。

谢谢!

macos emulation iokit pci pci-e
1个回答
0
投票

捕获内存访问

所以从理论上讲,要实现你想要的,你需要分配一个内存区域,将其保护位设置为只读(如果你正在模拟的设备中的读取有副作用,则可能既不读也不写),以及然后将任何写入捕获到您自己的处理函数中,然后您将模拟设备寄存器写入。

据我所知,您可以使用Mach异常处理在macOS用户空间中执行此类操作。您需要设置从您正在控制的进程发送到您控制的Mach端口的页面保护错误异常。在该端口的消息处理程序中,您将:

  • 检查访问的位置
  • 如果是设备内存,则暂停该进程的所有线程
  • 将写入来自的线程切换为单步,暂时允许写入存储区域
  • 恢复作者线程
  • 捕获单步消息。您的“设备内存”现在包含写入的值。
  • 执行“设备”的副作用。
  • 在编写器线程中关闭单步。
  • 恢复所有线程。

正如我所说,我相信这可以在用户空间流程中完成。这并不容易,你可以通过网络上的各种晦涩的例子来拼凑你需要使用的马赫调用。我有类似的工作曾经,但似乎无法找到那个代码,对不起。

......在内核中

现在,另一个问题是你在内核中尝试这样做。我不知道有任何公开的KPI可以让你做任何像我上面所述的事情。你可以在以下地方寻找黑客:

  • 你可以很容易地使IOMemoryDescriptors支持系统内存。不要担心IODeviceMemory术语:这些只是IOMemoryDescriptor对象; the IODeviceMemory class is a lie。陷阱访问完全是另一回事。原则上,您可以使用createMappingInTask()函数的“reference”标志找出特定MD存在的虚拟内存映射,然后使用redirect()支持内存参数在返回的IOMemoryMap上调用NULL方法。不幸的是,这只会暂停尝试访问映射的任何线程。发生这种情况时,您不会收到回调。
  • 你可以深入研究Mach VM内存子系统的内部,它主要位于xnu源的osfmk/vm/目录中。也许有一种方法可以为那里的VM区域设置自定义故障处理程序。但是,您可能不得不使用私有内核API。

为什么?

最后,你为什么要这样做?退后一步:你最终试图用它做什么?看起来以这种方式模拟PCI设备本身并不是一个目的,所以这真的是实现你最终要实现的更大目标的唯一方法吗? See: XY problem

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