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

9njqaruj  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(109)

为了访问PCI配置空间,根据各种文章使用I/O端口地址0xCF 8、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
问题来了

Q1,我见过这种方法只对PCI配置空间有效。那么,访问PCIe配置空间的另一种方法是什么?

“此扩展配置空间 * 无法 * 使用传统PCI方法(通过端口0xCF 8和0xCFC)访问”
https://wiki.osdev.org/PCI_Express
但是其他一些文章说这种传统方法也与PCIe配置空间兼容。
这太令人困惑了

Q2.如果旧版0xCF 8、0xCFC也能与PCIe配置空间一起工作,那么详细的NASM汇编源代码(而不是关于Linux的)将受到真正的赞赏,因为我已经看到了大量的ECAM(增强型配置访问机制)文章,但所有这些都是关于概念内容的。
硬件规格:

Motherboard : P775TM1
Processor : Intel i7 8700K

syqv5f0l

syqv5f0l1#

我发现这个方法只适用于PCI配置空间。那么,访问PCIe配置空间的另一种方法是什么?
对于80 x86 PC,实际上有3种机制可以访问PCI配置空间。您提到的遗留机制(使用IO端口0x 0 CF 8和0x 0xCFC)是“机制#1”。还有另一种称为“机制#2”的遗留机制,它也使用了0x 0 CF 8和0x 0xCFC;但它并没有被许多芯片组使用,(对于现代计算机)可以被认为是过时的。
最初,每个PCI“功能”的PCI配置空间的大小是256字节;并且对于这两种传统机制,您只能访问256字节。当他们发明PCI-E时,他们添加了第三种机制(内存MapECAM),并且他们还将每个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规范中描述,该规范被锁定在“恶意昂贵”的PCI SIG付费墙之后。希望你能在某个地方找到可靠的第三方描述。
通常,MCFG表由描述用于总线号范围的地址范围的条目组成;并且对于多个单独的总线号范围可以有多个不同的地址范围。这个想法将是使用设备的总线号来找到正确区域的地址;然后合并“address_of_area + ((bus - first_bus_for_area) << 20) | (device << 15) | (function << 12)”找到函数的PCI配置空间的起始地址。一旦找到了,你就可以读/写该物理页面中的偏移量,以访问函数的PCI配置空间中相应的偏移量。

icnyk63a

icnyk63a2#

你读了那句话
无法使用传统PCI方法(通过端口0xCF 8和0xCFC)访问此扩展配置空间
断章取义。
下面是上下文中的引用(强调我的):

PCI Express总线将配置空间从256字节扩展到4096字节。使用传统PCI方法(通过端口0xCF 8和0xCFC)* 不能 * 访问此扩展配置空间。

作者讨论的是PCIe配置空间的 * 部分 ,从0x 100开始。
在开始时,对于每个PCI设备功能,存在256字节的配置空间。
在端口0xcf 8和0xcfc使用PCI传统机制(我们可以忽略存在两种机制的事实)访问该空间。
PCIe将此空间从256字节扩展到4KiB,并引入了一种新的机制来访问配置空间(
全部 *)。
所以,总结一下:

  • 单个PCI配置空间为4KiB。它分为 *PCI 3.0兼容区域 *(从0x 000到0x 0 ff)和PCIe扩展配置区域(从0x 100到0xfff)。
  • 有两种访问PCI配置空间的机制。一个是0xcf 8/0xcfc处的传统机制,另一个是内存Map区域。
  • Legacy机制只能访问兼容区域(前256个字节)。
  • ECAM可以访问所有的空间。

引用PCIe规范:
与PCI局部总线规范所允许的256字节相比,PCI Express将配置空间扩展到每个功能4096字节。
PCI Express配置空间分为PCI 3.0兼容区和PCI Express扩展配置空间,前者由功能配置空间的前256个字节组成,后者由剩余配置空间组成(参见图7-3)。
PCI 3.0兼容配置空间可以使用PCI本地总线规范**[NdR:传统配置机制]**或PCI Express增强型配置访问机制(ECAM),将在本节后面介绍。

使用任一访问机制进行的访问是等效的。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

字符串

此代码未经测试

如果您指的是配置空间的 content(即设定什么),那就太宽泛了。
您可以阅读相关器件的数据手册,它们通常甚至记录了PCI规范中定义的标准寄存器。
或者,您也可以阅读PCI规格本身。
如果你问如何使用ECAM,阅读Brendan的回答。
我唯一要补充的是,对于您的CPU,您可以通过从CPU(总线0、设备0、功能0)的iMC的(传统)PCI配置空间阅读寄存器PCIEXBAR(偏移量60 h)来找到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


固件已经配置了正确使用此区域的所有内容。

相关问题