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

时间:2019-08-12 07:40:40

标签: assembly intel pci pci-e base-address

为了访问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

这是问题。

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

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

https://wiki.osdev.org/PCI_Express

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

这令人困惑。

第二季度。如果传统的0xCF8、0xCFC也可以与PCIe配置空间配合使用,那么将不胜枚举NASM汇编源代码(不涉及linux),因为我看过很多ECAM(增强型配置访问机制)文章,但所有这些都是关于概念性内容。

硬件规格:

Motherboard : P775TM1
Processor : Intel i7 8700K

2 个答案:

答案 0 :(得分:5)

  

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传统设备/功能仍在使用ECAM,也只能提供256字节的PCI配置空间。

要使用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配置空间中的相应偏移量。

答案 1 :(得分:5)

您阅读了报价

  

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

脱离上下文。
这是上下文中的引号(强调我的意思):

  

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

作者谈论的是PCIe配置空间的 part ,该空间始于0x100。

一开始,每个PCI设备功能的配置空间为256字节。
在端口0xcf8和0xcfc处使用PCI传统机制(我们可以忽略存在两种机制的事实)来访问此空间。

PCIe将该空间从256字节扩展到4KiB,并引入了一种新的机制来访问配置空间(其中的 all )。

所以,回顾一下:

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

引用PCIe规范:

  

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

     

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

     

可以使用以下任一方法访问兼容PCI 3.0的配置空间:   PCI本地总线规范 [NdR:旧版配置机制] 中定义的机制或PCI Express增强配置   访问机制(ECAM)将在本节后面介绍。

     

使用任一访问权限进行的访问   机制是等效的。只能使用ECAM来访问P​​CI Express扩展配置空间。


非常(非常)可能是英特尔的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配置空间读取寄存器PCIEXBAR(偏移60h)来找到ECAM的基础, ,有趣的0)。
像这样:

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 

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