PCI BAR0 指向哪里?

Where is PCI BAR0 pointing to?

我有一个 PCI 设备,它在 BAR0 中有一些内存地址。我想这个内存地址只是 OS 虚拟地址,它指向设备的一些物理内存。问题是它指向哪里?阅读设备的文档以及固件源代码,我注意到该设备有一些寄存器负责设置所谓的内存 windows。我希望 BAR0 能准确指向它们,但事实并非如此,看起来像这样:

BAR0 地址 -> 一些未知内存 -> + 0x80000 我的内存 window

那么为什么我的记忆 window 从 BAR0 指向的位置偏移了 0x80000,这个 BAR0 指向我们的位置 + 它是由谁设置的?

谢谢

没有。 The address in a BAR is the physical address of the beginning of the BAR. That is how the device knows when and how to respond to a memory read or write request. For example, let's say the BAR (BAR0) is of length 128K and has a base address of 0xb840 0000, then the device will respond to a memory read or write to any of these addresses:

0xb840 0000
0xb840 0080
0xb840 1184
0xb841 fffc

but NOT to any of these addresses:

0x5844 0000              (Below BAR)
0xb83f 0000              (Below)
0xb83f fffc              (Below)
0xb842 0000              (Above BAR)
0xe022 0000              (Above)

This was more significant in the original PCI where the bus was actually a shared medium and devices might see requests for addresses belonging to other devices. With PCI-Express' point to point architecture, only PCI "bridges" will ever see requests for memory addresses they do not own. But it still functions in exactly the same way. And the low bits of the address space still allow the device to designate different functions / operations to different parts of the space (as in your device, creating the separate memory window you're attempting to access).

Now, how you as a programmer access the BAR memory space is a different question. For virtually all modern systems, all memory accesses made by programs are to virtual addresses. So, in order for your memory access to reach a device, there must be a mapping from the virtual address to the physical address. That is generally done through page tables (though some architectures, like MIPS, have a dedicated area of virtual address space that is permanently mapped to part of the physical address space).

The exact mechanism for allocating virtual address space, and setting up the page tables to map from that space to the BAR physical address space is processor- and OS-dependent. So you will need to allocate some virtual address space, then create page tables mapping from the start of the allocated space to (BAR0) + 0x80000 in order to work with your window. (I'm describing this as two steps, but your OS probably provides a single function call to allocate virtual address space and map it to a physical range in one fell swoop.)

Now, the process of assigning physical address space to the device (that is, actually sticking an address into the BAR) is generally done very early in system initialization by the system BIOS or an analogous early-boot mechanism while it's enumerating all the PCI devices installed in the system. The desired address space size is determined by querying the device, then the base address of a large enough physical address region is written into the BAR.

The final question: why your memory window is at an offset of 0x80000 within the device's address space is completely device-specific and cannot be answered more generally.