windows - PCI BAR0 指向哪里?
问题描述
我有一个 PCI 设备,它在 BAR0 中有一些内存地址。我想这个内存地址只是操作系统虚拟地址,它指向设备的一些物理内存。问题是它指向哪里?阅读设备文档和固件源代码后,我注意到该设备有一些寄存器负责设置所谓的内存窗口。我希望 BAR0 会准确地指向它们,但事实并非如此,看起来像这样:
BAR0 地址 -> 一些未知内存 -> + 0x80000 我的内存窗口
那么为什么我的内存窗口从 BAR0 指向的位置偏移了 0x80000,这个 BAR0 指向我们在哪里 + 它是如何由谁设置的?
谢谢
解决方案
不,BAR 中的地址是 BAR 开头的物理地址。这就是设备如何知道何时以及如何响应内存读取或写入请求的方式。例如,假设 BAR (BAR0) 的长度为 128K,基地址为0xb840 0000
,那么设备将响应对这些地址中的任何一个的内存读取或写入:
0xb840 0000
0xb840 0080
0xb840 1184
0xb841 fffc
但不是这些地址中的任何一个:
0x5844 0000 (Below BAR)
0xb83f 0000 (Below)
0xb83f fffc (Below)
0xb842 0000 (Above BAR)
0xe022 0000 (Above)
这在原始 PCI 中更为重要,其中总线实际上是共享介质,设备可能会看到对属于其他设备的地址的请求。使用 PCI-Express 的点对点架构,只有 PCI“桥”会看到对它们不拥有的内存地址的请求。但它仍然以完全相同的方式发挥作用。并且地址空间的低位仍然允许设备为空间的不同部分指定不同的功能/操作(如在您的设备中,创建您尝试访问的单独内存窗口)。
现在,作为程序员,您如何访问 BAR 内存空间是一个不同的问题。对于几乎所有现代系统,程序进行的所有内存访问都是对虚拟地址的。因此,为了让您的内存访问到达设备,必须有一个从虚拟地址到物理地址的映射。这通常是通过页表完成的(尽管某些体系结构,如 MIPS,有一个虚拟地址空间的专用区域,该区域永久映射到物理地址空间的一部分)。
分配虚拟地址空间以及设置页表以从该空间映射到 BAR 物理地址空间的确切机制取决于处理器和操作系统。因此,您需要分配一些虚拟地址空间,然后创建从分配空间开始到的页表映射,(BAR0) + 0x80000
以便使用您的窗口。(我将其描述为两个步骤,但您的操作系统可能提供了一个函数调用来分配虚拟地址空间并将其映射到一个物理范围。)
现在,为设备分配物理地址空间的过程(即实际上将地址粘贴到BAR 中)通常在系统初始化的早期由系统 BIOS 或类似的早期启动机制完成,同时它正在枚举所有 PCI 设备安装在系统中。所需的地址空间大小通过查询设备来确定,然后将足够大的物理地址区域的基地址写入 BAR。
最后一个问题:为什么您的内存窗口在设备地址空间内的偏移量为 0x80000 完全是特定于设备的,无法更普遍地回答。
推荐阅读
- sonarqube - 为什么我们必须在 Azure DevOps 中执行 SonarQube 代码分析之前先构建项目?
- ios - 在collectionView.deleteItems 之后没有调用cellForItemAt
- javascript - 对通过函数传递的对象使用@param
- python-3.x - “模块”对象不可调用,模块“sklearn.linear_model”没有属性“适合”错误
- geolocation - 如何计算给定中心和方位角的扇区点的地理坐标
- javascript - 如何将 socket.io 实例传递给 typegraphql 解析器?
- android - Android Studio 应用程序中的 MQTT 连接错误
- firebase - 如何在颤动中滚动时修复小部件的位置不移动
- node.js - 为什么 gitup-pages 没有为我的项目加载我的所有文件?
- java - Apache Ant java 目标中的 maxmemory 标志究竟是做什么的?