如何访问 PCIe 配置空间?(ECAM)



为了访问PCI配置空间,I/O端口地址0xCF8,根据各种文章使用0xCFC。

mov eax, dword 0x80000000
mov dx, word 0x0CF8
out dx, eax
mov dx, word 0x0CFC
in eax, dx

上面代码中 eax 的值是0x12378086,表示vendor ID = 0x8086device ID = 0x1237

问题来了。

问题 1.我已经看到此方法仅适用于PCI配置空间。那么,访问 PCIe 配置空间的另一种方法是什么?

"无法使用旧版 PCI方法(通过端口 0xCF8 和 0xCFC)访问此扩展配置空间">

https://wiki.osdev.org/PCI_Express

但其他一些文章说这种传统方法也与 PCIe 配置空间兼容。

这是令人困惑的。

问题 2.如果遗留0xCF8,0xCFC也适用于 PCIe 配置空间,那么 NASM 汇编源代码的详细信息(不是关于 linux)将不胜感激,因为我看过很多 ECAM(增强型配置访问机制)文章,但它们都是关于概念内容的。

硬件规格:

Motherboard : P775TM1
Processor : Intel i7 8700K

Q1。我已经看到此方法仅适用于PCI配置空间。那么,访问 PCIe 配置空间的另一种方法是什么?

对于 80x86 PC,实际上有 3 种机制可以访问 PCI 配置空间。您提到的传统机制(使用 IO 端口 0x0CF8 和 0x0xCFC)是"机制 #1"。还有另一种称为"机制#2"的遗留机制,它也使用了0x0CF8和0x0xCFC;但它并没有被许多芯片组使用,并且(对于现代计算机)可以被认为是过时的。

最初,每个PCI"功能"的PCI配置空间大小为256字节;对于这两种传统机制,您只能访问256字节。当他们发明PCI-E时,他们添加了第三种机制(内存映射ECAM),并且还将每个PCI-E"功能"的PCI配置空间增加到4096字节。传统的"机制#1"仍然有效,但仍然只能访问前256字节(在PCI-E"功能"可以具有的4096字节中)。幸运的是,硬件制造商足够聪明,可以确保旧操作系统需要访问的内容在前 256 字节内,因此不支持 PCI-E 的旧操作系统仍然可以工作(使用"机制 #1"),其余的 4096 字节(没有 ECAM 就无法访问)主要用于 PCI-E 扩展功能等。

注意:可以有一个"PCI-E 到 PCI 常规"桥接器,桥后面是 PCI 传统设备。在这种情况下,PCI 常规设备/功能将仅提供 256 字节的 PCI 配置空间,即使它仍在使用 ECAM。

若要使用 ECAM;需要使用 ACPI 的"表索引"(RSDT 或 XSDT)来查找名为"MCFG"的表。可悲的是(除非自从我上次查看以来它发生了变化)此表未在其所属的 ACPI 规范中描述;而是在锁定在"恶意昂贵"PCI SIG 付费墙后面的 PCI 规范中描述。希望您可以在某处找到可靠的第三方描述。

通常,MCFG 表由描述用于总线号范围的地址范围的条目组成;对于多个单独的总线号范围,可能有多个不同的地址范围。这个想法是使用设备的总线号来查找正确区域的地址;然后组合"address_of_area + ((bus - first_bus_for_area) << 20) | (device << 15) | (function << 12)"以查找函数PCI配置空间开始的地址。找到后,您可以在该物理页面中读取/写入偏移量,以访问函数的 PCI 配置空间中的相应偏移量。

你读了这句话

无法使用传统 PCI 方法(通过端口 0xCF8 和 0xCFC)访问此扩展配置空间

断章取义.
这是上下文中的引用(强调我的):

PCI Express 总线将配置空间从 256 字节扩展到 4096 字节无法使用旧版 PCI 方法(通过端口 0xCF8 和 0xCFC)访问此扩展配置空间。

作者说的是 PCIe 配置空间中从 0x100 开始的部分

一开始,每个 PCI 设备功能都有一个 256 字节的配置空间.
这个空间是在端口 0xcf8 和0xcfc使用 PCI 遗留机制(我们可以忽略有两种机制的事实)访问的。

PCIe 将此空间从 256 字节扩展到 4KiB,并引入了一种访问配置空间(全部)的新机制。

所以,回顾一下:

  • 有一个 4KiB 的 PCI 配置空间。它分为PCI 3.0 兼容区域(从 0x000 到 0x0ff)和 PCIe 扩展配置区域(从 0x100 到 0xfff)。
  • 有两种机制可以访问 PCI 配置空间。一个是 0xcf8/0xcfc 的遗留机制,另一个是内存映射区域。
  • 旧版机制只能访问兼容区域(前 256 个字节)。
  • ECAM 可以访问所有空间。

引用 PCIe 规范:

PCI Express 将配置空间扩展到每个功能 4096 字节,而 PCI 本地总线规范允许的配置空间为 256 字节。

PCI Express 配置空间分为 PCI 3.0 兼容区域(由函数配置空间的前 256 个字节组成)和 PCI Express 扩展配置空间(由剩余的配置空间组成)(请参阅图 7-3)。

可以使用 PCI 本地总线规范[NdR:旧版配置机制] 中定义的机制或本节后面所述的 PCI Express 增强型配置访问机制 (ECAM) 访问与 PCI 3.0 兼容的配置空间。

使用任一访问机制进行的访问是等效的。PCI Express 扩展配置空间只能使用 ECAM 访问。


英特尔的CPU 很可能在未来许多年内支持传统的 PCI 配置机制。
在内部,生成 PCI 配置事务的非内核部分(即系统代理/UBox)已经仅使用 PCIe 配置事务(即由 ECAM 生成的相同 MMCFG 类型),但旧版软件接口未被删除。

由于 PCIe 根复合体位于 CPU 内,因此在涉及传统 PCI软件兼容性时,CPU 是唯一关注的问题(传统 PCI 需要 PCIe 到 PCI 桥接器,这可能会暴露配置机制)。

简而言之,您可以安全地使用传统 PCI 机制访问 PCIe 配置空间的前 256 字节(每个功能)。
实际上,除非英特尔找到配置非内核设备的新方法,否则传统机制永远不会消失,因为它需要配置 ECAM 本身。


旧机制易于使用,您已经发布了一些使用它的代码。我不确定还需要什么。

你可以像这样使用它:

%define CFG(bus, dev, fun, reg) (0x80000000 | (bus << 16) | (dev << 11) | (fun << 8) | reg)
%macro cfg_arm 4
mov dx, 0cf8h
mov eax, CFG(%1, %2, %3, %4)
out dx, eax
%endmacro
%macro cfg_read 4
cfg_arm %1, %2, %3, %4
mov dx, 0cfch
in eax, dx
%endmacro
%macro cfg_write 5
cfg_arm %1, %2, %3, %4
mov dx, 0cfch
mov eax, %5
out dx, eax
%endmacro
cfg_read 0, 0, 0, 0   ;eax <- VID:DID of dev 0, fun 0 on bus 0

此代码未经测试

如果您指的是配置空间的内容(即要设置的内容),那就太宽泛了。
您可以阅读相关设备的数据表,它们通常甚至记录 PCI 规范中定义的标准寄存器。
或者,您可以阅读 PCI 规范本身。

如果你问如何使用 ECAM,请阅读 Brendan 的回答.
我唯一能补充的是,对于您的 CPU,您可以通过从 CPU 的 iMC 的(遗留)PCI 配置空间(总线 0、dev 0、fun 0)读取寄存器 PCIEXBAR(偏移量 60h)来找到 ECAM 的基础><。

cfg_read 0, 0, 0, 60h       ;Low 32-bit
mov ebx, eax                
cfg_read 0, 0, 0, 64h       ;high 32-bit
shl rax, 32
or rax, rbx                 ;RAX = ptr to ECAM area 

固件已将所有内容配置为正确使用此区域。

最新更新