x86 机器上的不同 CPU 可以有不同的本地 APIC 寄存器 MMIO 基地址吗?

Can different CPUs on an x86 machine can have different local APIC register MMIO base addresses?

Intel手册说本地APIC寄存器内存映射到一个4KB的区域,默认地址是FEE00000H。这个地址可以使用IA32_APIC_BASE MSR.

修改

引用 SDM 第 3 卷第 10.4.5 节

The Pentium 4, Intel Xeon, and P6 family processors permit the starting address of the APIC registers to be relocated from FEE00000H to another physical address by modifying the value in the 24-bit base address field of the IA32_APIC_BASE MSR. This extension of the APIC architecture is provided to help resolve conflicts with memory maps of existing systems and to allow individual processors in an MP system to map their APIC registers to different locations in physical memory.

  1. 是否有可能同时在同一台机器上的不同 CPUs 可以有不同的本地 APIC 基地址?比如说,CPU 0 决定留在 FEE00000H,但是 CPU1 移动到 FEF00000H

  2. 如果以上为真,PCI MSI 中断如何工作?如果不同的CPUs可以有不同的本地APIC地址,那么MSI消息地址对于不同的CPUs意味着不同的。

是的,它们可以不同。

MSI 地址,即使它与默认 APIC 地址相同,也没有绑定到它。 APIC基地址改变,MSI地址不变。

  1. 是的,正如您引用的那样,这是英特尔手册明确允许的。 然而,由于 P6 架构,APIC 访问由处理器在内部处理,没有可见的外部总线周期。

    For P6 family, Pentium 4, and Intel Xeon processors, the APIC handles all memory accesses to addresses within the 4-KByte APIC register space internally and no external bus cycles are produced.

    所以重新映射只是为了避免与旧设备发生冲突。
    今天,这是一种罕见的情况,因为从 4 GiB - 18 MiB 到 4GiB - 17 MiB(开放式)的区域是为 MSI 保留的。

  2. 从 PCI 的角度来看,MSI 非常简单:将值写入地址。
    地址和值都通过MSI or MSI-x capability structures(值分别为05h和11h)配置在设备的PCI地址space中。
    只有 MSI-x 允许 32 位数据。

    PCI 规范是有意通用的,地址和数据对形成唯一的 "interrupt vector",即标识中断的值。
    第一个设备实际上对 MESSAGE_DATA 字段的扩展非常有限,只有几个较低的位 writable.
    然而,在 x86 体系结构中,地址和数据采用特定形式。
    这些在 Intel 手册 3A 的第 10.11 节中有描述。

    Address format
    
    31   20  19            12  11         4   3    2  0
    0FEEH    Destination ID    Reserved   RH  DM   XX
    
    Data format
    
    63     16   15   14   13     11  10          8  7   0
    Reserved    TM   LM   Reserved   Delivery mode  Vector
    

    我们可以看到这些格式与 MSI 和 MSI-x 都兼容,但更重要的是地址的前缀为 0feeh,使其至少为 0fee00000h,即 4 GiB - 18 MiB。
    该区域用于通过 Host-to-PCI 路由 MSI,即 Root Complex(在 CPU 芯片或 PCH 中)或 MCH(对于旧平台)。
    该地址决定了哪一组处理器将处理 MSI(确切的规则可以在 Intel 的手册中找到)。

    即使所有本地APIC都映射到同一个地址,选择一组处理器的也是目的地址的格式,x86的MSI的设计是为了允许 OS 将中断定向到特定处理器。
    所以,不,MSI 地址对每个 CPU 意味着相同的事情,因为它不是 CPU 处理 PCI 写入,而是主机到 PCI 桥接,并且该芯片是系统范围的。


Host-to-PCI 如何知道将 MSI 发送到哪里?

该地址有一个目标 ID(英特尔术语中的 MDA - 消息目标地址),连同一些元信息,足以在 "APIC bus" 中路由消息 - 一个逻辑结构,实现定义(可能是带有一些 QPI/UPI/DMI 段的环形总线),它连接 APIC 和 APIC 集群。
与网络数据包的路由方式非常相似。

MSI 范围和默认本地 APIC 范围是否重叠?

是的,但是这些范围存在于两个不同的 "address space" 中:本地 APIC 范围存在于每个内核中或最多存在于非内核中(但不在系统代理中)MSI 范围存在于主机中-转PCI芯片。
从针对 MSI 范围的 PCI 总线写入永远不会离开主机到 PCI 桥,而对本地 APIC 范围的访问永远不会离开内核。
这两个域之间的通信是通过 APIC 总线进行的。


附录

评论中出现了一个问题:在启用了 VT-d 的系统(本质上是 IOMMU)中,为什么需要中断重映射 (IR) 机制?为什么 DMA 重映射不够用?

由于 MSI(-X) 是从设备发起的内存写入,因此 DMA 重新映射应该足以重新映射中断。

DMA 重新映射转换 地址,而 MSI(-X) 由目标地址(传达中断的目的地)和数据(指定类型中断传送)。
为了让软件完全控制要传送的中断,VT-d 规范为 MSI(-X) 引入了一种新格式:可重映射格式
这个想法类似于 CPU 使用的标准内存转换:MSI(-X) 仅具有必要的信息来索引具有中断目标和类型的完整定义的 table。

新格式为:

基本上有三个字段:

  • HandleSub handle 字段
    它们被 添加 在一起以获得 IR Table (IRT) 中的索引。它们已被分开,因为 Sub handleData 寄存器中(而 Handle 在地址寄存器中),这允许使用单个配置设备地址和多个数据值(显然这是必要的要求)。
  • SHV字段判断Sub handle字段是否有效,否则使用零代替。

请注意,索引是一个 16 位值。

找到索引后,它用于检索 IRT 条目 (IRTE),其中包含传递中断的所有信息 - 包括一些字段以验证中断源。

请注意,旧版(兼容格式)MSI(-X) 从未 重新映射,它们要么通过,要么被阻止(取决于软件如何配置转换器).