我有一个PCI设备,其BAR0内有一些内存地址。我想这个内存地址只是OS虚拟地址,它指向设备的某些物理内存。问题是它指向哪里?阅读设备文档以及固件源代码后,我注意到该设备有一些寄存器负责设置所谓的内存窗口。我希望BAR0会准确指向他们,但事实并非如此,看起来像这样:
BAR0地址->一些未知的内存-> + 0x80000我的内存窗口
那为什么我的内存窗口从BAR0指向的位置偏移0x80000,这个BAR0指向我们的位置+它是由谁设置的?
谢谢
答案 0 :(得分:0)
不。 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中,总线实际上是共享介质,并且设备可能会看到对属于其他设备的地址的请求。使用PCI-Express的点对点架构,只有PCI“网桥”才能看到对他们不拥有的内存地址的请求。但是它的功能仍然完全相同。而且地址空间的低位仍然允许设备为空间的不同部分指定不同的功能/操作(就像在设备中一样,创建要访问的单独的内存窗口)。
现在,作为程序员的您如何访问BAR存储空间是另一个问题。对于几乎所有现代系统而言,程序对 all 进行的所有内存访问都是针对虚拟地址的。因此,为了使您的内存访问到达设备,必须存在从虚拟地址到物理地址的映射。通常,这是通过页表完成的(尽管某些体系结构(例如MIPS)具有虚拟地址空间的专用区域,该区域永久映射到物理地址空间的一部分)。
分配虚拟地址空间以及设置页面表以从该空间映射到BAR物理地址空间的确切机制取决于处理器和OS。因此,您将需要分配一些虚拟地址空间,然后创建从分配的空间开始到(BAR0) + 0x80000
的页表映射,以便使用您的窗口。 (我将其描述为两个步骤,但是您的操作系统可能只提供了一个函数调用,即可分配虚拟地址空间并将其映射到一个物理范围内。)
现在,为设备分配物理地址空间的过程(即实际上将地址粘贴到 BAR中)通常在系统初始化的早期就完成了系统BIOS或类似的早期启动机制,同时枚举系统中安装的所有PCI设备。通过查询设备确定所需的地址空间大小,然后将足够大的物理地址区域的基地址写入BAR。
最后一个问题:为什么您的内存窗口在设备地址空间内的偏移量为0x80000完全是特定于设备的,因此无法更普遍地回答。