我正在基于英特尔 vt-x 技术开发自己的裸机管理程序。
我的目标是以任何方式使我在我的管理程序上运行的操作系统无法访问它,因此我配置了一个 EPT 表以防止内存访问。我相信现在我缺少对具有 DMA 访问权限的设备的保护。
我想知道如何防止所有 PCI 设备访问我的管理程序内存区域?代码示例对我来说是完美的。
顺便说一句:如果可能会影响答案,我会使用 QEMU 环境测试我的项目。
我正在基于英特尔 vt-x 技术开发自己的裸机管理程序。
我的目标是以任何方式使我在我的管理程序上运行的操作系统无法访问它,因此我配置了一个 EPT 表以防止内存访问。我相信现在我缺少对具有 DMA 访问权限的设备的保护。
我想知道如何防止所有 PCI 设备访问我的管理程序内存区域?代码示例对我来说是完美的。
顺便说一句:如果可能会影响答案,我会使用 QEMU 环境测试我的项目。
我相信现在我缺少对具有 DMA 访问权限的设备的保护。
我不确定您是否缺少保护。任何一个:
a) 您允许访客直接访问 PCI 设备(例如,通过让访客访问设备的 PCI 配置空间、内存映射 IO 区域、IO 端口和/或 IRQ);因此还需要担心客人要求设备执行总线主控或 DMA。
b) 您不允许客人直接访问 PCI 设备(例如,仅提供对模拟设备的访问,可能通过某种“virt IO”接口);因此客人不能首先要求真实设备执行总线主控或DMA。
我想知道如何防止所有 PCI 设备访问我的管理程序内存区域?
它不是那样工作的。
一般来说,我发现将它(总线等)想象成网络要容易得多,所有东西(设备、IOMMU、CPU、内存控制器)都在其中发送和接收数据包。例如,设备发送一个数据包说“为我从这个地址读取 N 个字节”并等待一个包含回复(请求的字节)的数据包,或者一个设备发送一个数据包说“为我将这 N 个字节写入这个地址”。IOMMU 拦截这些数据包。它只知道数据包的内容(发送它的内容、是否读/写、地址等),不知道设备是为主机工作还是为客人工作。如果您阻止所有 PCI 设备访问您的管理程序内存区域,那么您也会阻止您的管理程序使用所有设备。
反而; IOMMU 使用“哪个设备(或哪组设备)”作为其决策的基础。几乎就像每个设备(或设备组)都有一组页表来将“来自设备的地址”转换为“到主机的地址”。例如,IOMMU 从一个设备接收到一个数据包,说“为我从这个地址读取 N 个字节”,而 IOMMU 说“嘿,对于那个设备,我需要使用这些表来转换地址”,最终可能会发送一个“读取 N 个字节”从另一个完全不同的地址”到内存控制器。
换句话说; 如果您允许访客直接访问设备(并允许访客要求设备进行总线主控或 DMA);那么主机(您的管理程序)根本不应该尝试访问该设备,并且需要设置 IOMMU 以将“来自设备的访客物理地址”转换为“主机物理地址”(这就像CPU 用来将客户物理地址转换为主机物理地址的 EPT)。
当然它比这更复杂 - 你还必须关心从设备发送的 IRQ 之类的事情(并模拟 PCI 配置空间)。
关于如何配置 IOMMU,这里就不多说了。您想从名为“面向定向 I/O 架构规范的英特尔虚拟化技术”的文档开始(通过网络搜索应该很容易找到)。