转自https://zhuanlan.zhihu.com/p/678582090
0. 目录
-
垫话
-
本地中断处理[10.5]
2.1 local vector table[10.5.1]
2.2 合法的中断 vector[10.5.2]
2.3 错误处理[10.5.3]
2.4 APIC Timer[10.5.4]
2.4.1 TSC-Deadline 模式[10.5.4.1]
- 核间中断[10.6]
3.1 Interrupt Command Register(ICR)[10.6.1]
3.2 IPI 目标的决议[10.6.2]
3.2.1 Physical Destination Mode[10.6.2.1]
3.2.2 Logical Destination Mode[10.6.2.2]
3.2.3 Broadcast/Self Delivery Mode[10.6.2.3]
3.2.4 Lowest Priority Delivery Mode[10.6.2.4]
3.3 IPI 的发送与接收[10.6.3]
-
系统总线及 APIC 总线仲裁[10.7]
-
垫话
本文乃 Intel SDM “Chapter 10 Advanced Programmable Interrupt Controller(APIC)” 一章的翻译。
要点概述:
APIC timer 频率与系统总线一致,有 one-shot、periodic、TSC-Deadline 模式(此前被误导,一直以为 TSC-Deadline 是独立于 APIC timer 之外的另一个定时器,要纠正此错误思想)。
TSC-Deadline 工作原理是比较 time-stamp counter 与 IA32_TSC_DEADLINE(per-cpu MSR),到点触发中断。
IPI 的发送通过 ICR 寄存器,目标处理器的指定(destination mode)有 physical 及 logical 两种模式。
三种特殊 delivery mode:广播、self、lowest priority。lowest priority 模式的判定依据,在 Pentium 4 及 Intel Xeon 下基于一个特定总线 cycle,由处理器告知芯片组其 task priority;P6 family 及 Pentium 下基于 APR 判定。
中断的总线仲裁采用基于 APR 寄存器的 “rotating priority” 机制,思想类似 round robin(APR 在每个仲裁 round 结束后都会变化)。lowest priority delivery mode 下,多个 APIC 优先级相等时,通过 Arb ID(值唯一,由 local APIC ID 初始化)寄存器来判定接收者。
2. 本地中断处理[10.5]
下面的章节描述 local APIC 对本地中断的处理。包括:处理器 LINT0 及 LINT1 引脚、APIC timer、performance-monitoring counters、thermal sensor 以及内部 APIC 错误 detector。本地中断处理包括:LVT、error status 寄存器(ESR)、divide configuration 寄存器(DCR),以及 initial count 及 current count 寄存器。
2.1 local vector table[10.5.1]
local vector table(LVT) 允许软件指定本地中断被投递给处理器的方式。其包含如下 32-bit 的 APIC 寄存器(Figure 10-8),每个对应一个本地中断:
LVT CMCI Register(FEE0 02F0H):当一个支持 CMCI(Section 15.5.1, “CMCI Local APIC Interface”)的 machine check bank,其 corrected machine check error 数达到一定阈值时(overflow),会触发中断。此寄存器用于指定此中断的投递。
LVT Timer Register(FEE0 0320H):指定对 APIC timer 中断的投递(Section 10.5.4, “APIC Timer”)。
LVT Thermal Monitor Register(FEE0 0330H):指定 thermal sensor 所产生中断的投递(Section 14.8.2, “Thermal Monitor”)。此 LVT entry 是 implementation specific 的,非 architectural。如果实现了的话,其基地址总是 FEE0 0330H。
LVT Performance Counter Register(FEE0 0340H):指定 performance counter 所产生中断的投递(Section 18.6.3.5.8, “Generating an Interrupt on Overflow”)。此 LVT entry 是 implementation specific 的,非 architectural。如果实现了的话,其基地址总是 FEE0 0340H。
LVT LINT0 Register(FEE0 0350H):指定 LINT0 引脚所发起中断的投递。
LVT LINT1 Register(FEE0 0360H):指定 LINT1 引脚所发起中断的投递。
LVT Error Register(FEE0 0370H):指定 APIC 发现内部错误时所发起中断的投递(Section 10.5.3, “Error Handling”)。
如 Figure 10-8 所示,其中有些 entry 的部分域及 flag 是不可用的(保留的)。
LVT table 中的寄存器包含如下信息:
Vector:中断 vector 号。
Delivery Mode:发送给处理器的中断类型。可选值有 Fixed、SMI、NMI、INIT、ExtINT。
Delivery Status:中断投递状态。可选值有 Idle、Send Pending。
Interrupt Input Pin Polarity:对应中断引脚的极性:(0) 高电平有效, (1) 低电平有效。
Remote IRR Flag(Read Only):对于 fixed mode、电平触发的中断,当 local APIC 接受此中断并准备为其服务时,该 flag 会被置上,当从处理器接收到 EOI 时此 flag 会被清掉。对于边沿触发的中断以及其他投递模式,此 flag 的含义未定义。
Trigger Mode:LINT0、LINT1 引脚的触发模式:(0) 边沿触发,(1) 电平触发。此 flag 只在 fixed 投递模式下使用。NMI、SMI 及 INIT 投递模式下,总是边沿触发。ExtINT 投递模式下,总是电平触发。timer 及错误中断总是边沿触发。当 local APIC 并未与 I/O APIC 组合使用,且在 fixed 投递模式下,即使选择边沿触发,Pentium 4、Intel Xeon 及 P6 family 处理器总是采用电平触发。软件应该总是将 LVT LINT1 寄存器的 trigger mode 设置为 0(边沿触发)。LINT1 不支持电平触发。
Mask:中断掩码:(0) 使能对此中断的接收 (1) 禁止对此中断的接收。APCI 接收到 performance-monitoring counter 的中断时,其会自动设置 LVT performance counter 寄存器中的 mask flag。复位时该 flag 为 1。其只能被软件清零。
Timer Mode:bits 18:17 决定 timer 的模式(Section 10.5.4):(00b) 使用向下计数值的 one-shot 模式。(01b) 自动重新装载向下计数值的 periodic 模式。(10b) 使用 IA32_TSC_DEADLINE MSR(Section 10.5.4.1)中绝对目标值的 TSC-Deadline 模式。(11b) 保留。
2.2 合法的中断 vector[10.5.2]
Intel 64 及 IA-32 架构定义了 256 个 vector 号,从 0 到 255(Section 6.2, “Exception and Interrupt Vectors”)。local 及 I/O APIC 支持了其中的 240 个(16 到 255),当 local APIC 发出或接收到一个在 0 到 15 范围内的中断 vector 时,APIC 会在其 Error Status Register(Section 10.5.3,“Error Handling”)中标记一个非法的 vector。Intel 64 及 IA-32 架构为预定义的中断、异常以及 Inter-reserved 编码保留了 16 到 31 的中断 vector 号,但是 local APIC 并不会将这些 vectors 视为非法。
当向一个 LVT entry 写入一个非法的 vector(0 到 15)号且 delivery mode 为 Fixed(bits 8-11 为 0)时,APIC 将发起一个非法 vector 号错误,且无视该 vector 的 mask bit 是否被置上或者此中断是否被实际投送。
2.3 错误处理[10.5.3]
local APIC 会将在中断处理阶段检测到的错误记录到 error status register(ESR)。ESR 格式如 Figure 10-9:
ESR 是一个可读写寄存器。在尝试对其读之前,软件应当先对其写。(写入的值并不会影响后续读出来的值;x2APIC 模式下只能写 0。)该写操作会清除掉此前的错误记录,并将 ESR 更新为上一次对 ESR 写之后所检测到的错误。该写操作同时会重新启动 APIC 错误中断触发机制。
LVT Error Register(Section 10.5.1) 可以指定当检测到 APIC 错误时,向处理器发送的中断的 vector 号。该寄存器同时提供 mask 掉一个 APIC 错误中断的功能。此 masking 只会阻止 APIC 错误中断的投递;并不影响 APIC 将错误记录到 ESR 中。
2.4 APIC Timer[10.5.4]
local APIC 中包含一个 32 bit 的可编程 timer,软件可以操作此 timer 时间相关的事件及操作。通过对 4 个寄存器的编程来设置此 timer:divide configuration 寄存器(Figure 10-10),initial-count 及 current-count 寄存器(Figure 10-11),以及 LVT timer 寄存器(Figure 10-8)。
如果 CPUID.06H:EAX.ARAT[bit 2] = 1,无论 P-state 如何变化,APIC timer 始终以一个固定的速率运行,在深度 C-state 下也以同样的速率运行。
如果 CPUID.06H:EAX.ARAT[bit 2] = 0,或者 CPUID 06H 未支持,在深度 C-state 下或由 Enhanced Intel SpeedStep Technology 引发的(P-state)变化时,APIC timer 可能会临时停止。
APIC timer 的频率等于处理器总线时钟,或 core 晶振时钟频率(TSC/core 晶振时钟频率通过 CPUID leaf 0x15 来枚举)除以 divide configuration 寄存器所指定的值。
通过 timer LVT entry 来配置 timer 是 one-shot 或 periodic 操作。one-shot 模式下,timer 通过编程其 initial-count 及 current-count 寄存器(Figure 10-11),以及 LVT timer 寄存器(Figure 10-8)来启动。init count 值将被拷贝至 current count 寄存器,并开始向下计数。当 timer (current count 值)为 0 时,会生成一个 timer 中断,并在被重新编程之前保持值为 0。
periodic 模式下,当 count 计数变为 0 并生成 timer 中断后,current-count 寄存器会自动被重新装填为 initial-count 寄存器的值,然后继续向下计数。如果在向下计数过程中,initial-count 寄存器被设置,会使用新的 initial-count 值重新开始计数。initial-count 寄存器是可读写寄存器;current-count 寄存器是只读的。
one-shot 及 periodic 模式下,对 initial-count 寄存器写入 0 会立即停止 local APIC timer。
当 timer 计数为 0 并触发 timer 中断时,投递给处理器的 vector 号由 LVT timer 寄存器决定。LVT timer 寄存器中的 mask flag 可用来掩掉 timer 中断。
2.4.1 TSC-Deadline 模式[10.5.4.1]
local-APIC timer 的模式由 LVT timer 寄存器决定。具体来说:
如果 CPUID.01H:ECX.TSC_Deadline[bit 24] = 0,模式由此寄存器的 bit 17 决定。
如果 CPUID.01H:ECX.TSC_Deadline[bit 24] = 1,模式由此寄存器的 bit 18:17 决定。参考 Figure 10-8。(如果 CPUID.01H:ECX.TSC_Deadline[bit 24] = 0,寄存器的 bit 18 是保留的)
timer 所支持的模式见 Table 10-2。此三者 local APIC timer 模式是互斥的。
TSC-deadline 模式允许软件使用 local APIC timer 在一个绝对时间点上发出一个中断。TSC-deadline 模式下,忽略对 initial-count 寄存器的写入;current-count 寄存器始终为 0。timer 行为由 IA32_TSC_DEADLINE MSR 控制。
IA32_TSC_DEADLINE MSR(MSR 地址 6E0H)是一个 per-逻辑处理器的 MSR,其指定了在何时 timer 将发出一个中断。对 IA32_TSC_DEADLINE 写入一个非 0 的 64 bit 值将启动 timer。当逻辑处理器的 time-stamp counter 等于或超过 IA32_TSC_DEADLINE MSR 中的目标值时,将发出一个中断。当 timer 发出中断后,其将停止自己并清除 IA32_TSC_DEADLINE MSR。因此,每次对 IA32_TSC_DEADLINE MSR 的写入,最多只产生一个 timer 中断。
TSC-deadline 模式下,对 IA32_TSC_DEADLINE MSR 写入 0 会停止 local APIC timer。在 TSC-deadline 模式及其他 timer 模式之间进行切换时也会停止 timer。
硬件会将 IA32_TSC_DEADLINE 重置为 0。其他 timer 模式(LVT bit 18 = 0)下,IA32_TSC_DEADLINE MSR 的读返回 0,写被忽略。
软件可通过如下算法配置 TSC-deadline timer 来发起一个中断:
通过校验 CPUID.1:ECX.24 = 1 来检测对 TSC-deadline 模式的支持。
通过将 LVT timer 寄存器的 bits 18:17 编程为 10b,选中 TSC-deadline 模式。
将 IA32_TSC_DEADLINE MSR 配置为期望 timer 中断触发时间点的目标 TSC 值。这会启动 timer。
当 timer-stamp counter 大于等于 IA32_TSC_DEADLINE 的值时,处理器会产生一个 timer 中断。随后停止 timer 并清除 IA32_TSC_DEADLINE MSR。(time-stamp counter 及 IA32_TSC_DEADLINE MSR 都是 64 bit 无符号整型)。
软件可通过重复第 3 步来重新启动 timer。
原注:如果逻辑处理器在 VMX non-root 模式下,其对 time-stamp counter 的读(使用 RDMSR、RDTSC 或 RDTSCP)不会获取 time-stamp counter 的实际值;参阅 Intel 64 and IA-32 Architectures Software Developer’s Manual,Volume 3C 的 Chapter 27。VMX root 模式下,软件负责对 time-stamp counter 及 IA32_TSC_DEADLINE MSR 的虚拟化。
以下是 TSC-deadline 模式的使用指导:
对 IA32_TSC_DEADLINE MSR 的写入不是 serialized 的。因此,系统软件不应该将对 IA32_TSC_DEADLINE 的 WRMSR 视为 serializing 指令(译者注:意思就是该加内存屏障还得加内存屏障)。对 IA32_TSC_DEADLINE 及其他 MSR 的读写操作按 program order 出现(译者注:意思就是 MSR 的读写不会被重排)。
软件可以随时通过对 IA32_TSC_DEADLINE MSR 写入 0 来停止 timer。
如果 timer 启动了,软件可以通过对 IA32_TSC_DEADLINE MSR 写入新的值来改变 deadline(forward 或 backward)。
如果软件停止 timer 或向后推延 deadline,会导致在伪(spurious)timer 中断的投递中产生竞态条件。软件在检测到伪中断时,可通过校验 time-stamp counter 的当前值来确认中断是否是符合预期的。
在 xAPIC 模式下(此模式下 local APIC 寄存器是 memory-mapped 的),软件必须按序做 LVT entry 的 memory-mapped 写(以使能 TSC-deadline 模式)以及后续对 IA32_TSC_DEADLINE MSR 的 WRMSR 操作。软件可通过在 memory-mapped 写之后、WRMSR 之前插入 MFENCE 指令,来确保正确的内存序。(x2APIC 模式下,使用 WRMSR 指令来对 LVT entry 写入。处理器会确保此写入与后续对 deadline 的 WRMSR 的内存序;无需使用内存屏障。译者注:意思就是处理器不会在 WRMSR 指令之间做重排。)
3. 核间中断[10.6]
local APIC 发起 IPIs 功能主要涉及 interrupt command register(ICR)。ICR 可以:
向其他处理器发送一个中断。
处理器可以将收到但不想服务的中断,转发给其他处理器来服务(interrupt forwarding)。
给自己(处理器)发送中断(发起 self interrupt)
向其他处理器发起一个特定 IPIs,比如 start-up IPI(SIPI)消息。
通过此机制向其他处理器发出的中断会通过系统总线(Pentium 4 及 Intel Xeon 处理器)或 APIC 总线(P6 family 及 Pentium 处理器)投递。处理器发送最低优先级 IPI 的能力是 model specific 的,BIOS 及 OS 软件应该避免使用。
3.1 Interrupt Command Register(ICR)[10.6.1]
interrupt command register(ICR) 是一个 64 bit 的 local APIC 寄存器(Figure 10-12),允许处理器向其他指定处理器发送核间中断。
原注:xAPIC 模式下 ICR 是两个 32 bit 寄存器,ICR_LOW(FFE0 0300H) 及 LCR_HIGH(FEE0 0310H)。x2APIC 模式下,ICR 使用 MSR 830H。
要发送 IPI,软件需要通过设置 ICR 指定要发送的 IPI 消息类型、目标处理器(们)。(除 delivery status 域是只读的之外,ICR 的所有其他域对软件都是可读写的。)对 ICR 的 doubleword 写入会发送 IPI。
ICR 有如下域:
Vector:要发送的中断 vector 号。
Delivery Mode:IPI 的类型。可选值:Fixed、LowestPriority、SMI、NMI、INIT、INITLevelDe-assert、Start-Up。
Destination Mode:(0) physical,(1) logical(Section 10.6.2, “Determining IPI Destination”。译者注:不同模式下 Destination 域的含义不同,physical 模式下,Destination 是一个 CPU 的 APIC ID;logical 模式下,有一套复杂的计算映射方法。)
Delivery Status(只读):IPI 的投递状态,可选值有 Idle、Send Pending。
Level:INIT level de-assert 的 delivery mode 下,此 flag 必须为 0;其他 delivery mode 下,其必须为 1。(Pentium 4 及 Intel Xeon 处理器下,此 flag 无意义,总是为 1。)
Trigger Mode:INIT level de-assert delivery mode 下的触发模式:(0) 边沿触发,(1) 电平触发。
Destination Shorthand:是否对 destination 采用简记。可选值:No Shorthand、Self、All Including Self、All Excluding Self。
Destination:指定目标处理器(们)。此域只在 Destination Shorthand 域为 00B 时才会用到。如果 destination mode 是 physical 的,Pentium 及 P6 family 处理器中,其 bit 56 到 59 包含了目标处理器的 APIC ID,Pentium 4 及 Intel Xeon 处理器中,其 bit 56 到 bit 63 包含了目标处理器的 APIC ID。如果 destination mode 是 logical 的,8 bit 的 destination 域的解析,取决于系统中所有处理器的 local APIC 的 DFR 及 LDR 寄存器(Section 10.6.2, “Determining IPI Destination”)。
3.2 IPI 目标的决议[10.6.2]
IPI 的目标(原文注:x2APIC 模式下 IPI 目标的决议在 Section 10.12.10)可以是一个,也可以是一组处理器。IPI 的发送者通过如下 APIC 寄存器及域来确定目标处理器:
ICR register:ICR 寄存器中的如下域用来确定 IPI 的目标。
— Destination Mode:选择两种目标模式(physical 或 logical)。
— Destination Field:physical 目标模式下,用来指定目标处理器的 APIC ID;logical 目标模式下,用来指定一个 message destination address(MDA),可用来选择指定的处理器。
— Destination Shorthand:快速指定目标的方法(译者注:相当于简写),所有处理器、除去自身的所有处理器、自身为目标。
— Delivery mode, Lowest Priority:架构相关的一个功能,在从一组处理器中选择优先级最低的处理器。处理器发起一个最低优先级 IPI 的能力是 model specific 的,BIOS 及 OS 软件应该避免去使用。
Local destination register(LDR):logical 模式下,其与 MDA 一起决定目标处理器。
Destination format register(DFR):logical模式下,其与 MDA 一起决定目标处理器。
ICR、LDR 及 DFR 如何决定 IPI 目标,取决于 destination mode:physical、logical、broadcast/self 或 lowest-priority delivery mode。具体的 destination mode 在如下章节描述。
3.2.1 Physical Destination Mode[10.6.2.1]
physical destination mode下,目标处理器由 local APIC ID 指定(Section 10.4.6, “Local APIC ID”)。对于 Pentium 4 及 Intel Xeon 处理器,physical destination mode 要么指定某一个目标处理器(local APIC ID 从 00H 到 FEH),要么指定对所有 APIC 的广播(APIC ID 为 FFH)。
physical destination mode 下,不支持广播 IPI(MDA 中 bit 28-31 为全 1),也不支持由 I/O 子系统初始化的、lowest priority delivery mode 中断(译者注:physical destination mode 下,外设不可以发 lowest priority delivery mode 中断),软件也不能做此配置。另外,对于非广播 IPI 或由非 I/O 子系统初始化的、lowest priority delivery mode 中断,软件必须确保中断地址所指向的 APICs 是确实存在的且使能了对中断的接收。
对于 P6 family 及 Pentium 处理器,physical destination mode 下,通过 local APIC ID 0H 到 0EH 来指定一个目标处理器,APIC 总线上最多允许 15 个 local APIC。广播 APIC 为 0FH。
注意:系统总线上可寻址的 local APIC 数是受硬件限制的。
3.2.2 Logical Destination Mode[10.6.2.2]
logical destination mode 下,IPI 目标由 8 bit 的 message destination address(MDA) 指定,其位于 ICR 的 destination field。当收到一个 logical destination mode 的 IPI 消息时,local APIC 会比较该消息中的 MDA 与其 LDR 及 DFR 的值,来决定其是否应该接收并处理此 IPI。logical destination mode 配置下,当为 lowest priority delivery mode 时,软件必须确保 IPI 或 I/O 子系统中断所指定的 local APICs 皆必须存在且使能了对此中断的接收。
Figure 10-13 是 logical destination register(LDR) 的布局。此寄存器中的 8 bit logical APIC ID 域被用作一个 ID,并被与 MDA 做对比。
注意:不要混淆此 local APIC ID,与 local APIC ID 寄存器中的 local APIC ID。
Figure 10-14 是 destination format register(DFR) 的布局。此寄存器中的 4 bit model 域用来在两种模式中做选择(flat 或 cluster),其在 logical destination mode 下可被用来做 MDA 的解析。
二者模式下对 MDA 的解析遵循如下规则。
Flat Model:通过将 DFR bit 28 到 31 编程为 1111 选中此模式。通过在每个 local APIC LDR 的 logical APIC ID 域中设置不同的 bit(最多 8 个local APICs),来为此 APIC 建立一个唯一的 logical APIC ID。通过在 MDA 中设置一到多个 bit,从而选中一组 local APICs。
每个 local APIC 对 MDA 和其 logical APIC ID 做逻辑与。如果是 true(非零),则此 local APIC 接受此 IPI 消息。通过将 MDA 设置为全 1 来发出一个广播中断。
Cluster Model:通过将 DFR bit 28 到 31 编程为 0000 选中此模式。此模式支持两种基本目标范式:flat cluster 及 hierarchical cluster。
flat cluster destination 只在 P6 family 及 Pentium 处理器上支持。使用此模式时,将默认所有 APIC 是通过 APIC 总线互联的。MDA 中 bit 60 到 63 标定了 destination cluster 的地址编码,bit 56 到 59 标定了此 cluster 中的 4 个 local APIC(每个 bit 对应 cluster 中的一个 local APIC,同 flat connection model)。要标识一或多个 local APIC,通过比较 MDA 的 bit 60 到 63 与 LDR 的 bit 28 到 31,来决定某 local APIC 是否是 cluster 的一员。比较 MDA 的 bit 56 到 59 与 LDR 的 bit 24 到 27,来标识 cluster 中的一个 local APIC。
通过将目标 cluster 的对应 bits 写入 MDA 的 bit 60 到 63,将 cluster 中目标成员的对应 bits 写入 MDA 的 bit 56 到 59,来指定一个 cluster 中的一组处理器。此模式下,消息可指定 15 个 cluster(cluster 地址从 0 到 14),一个 cluster 中有 4 个 local APIC。P6 及 Pentium 处理器的 local APIC,APIC arbitration ID 只支持 15 个 APIC agent,故此模式下处理器及其 local APIC 的总数量限制为 15 个。通过将所有目标 bits 置为 1 来发起一个对所有 local APIC 的广播,此确保可以匹配到所有 cluster 并选中每个 cluster 中的所有 local APIC。cluster mode 不支持 lowest delivery mode 下的广播 IPI 以及 I/O 子系统的广播中断,软件也不允许做此配置。
Pentium 4 、Intel Xeon、P6 family 或 Pentium 处理器下,可使用 hierarchical cluster destination mode。通过此模式,可以通过独立系统或 APIC 总线连接不同的 flat cluster 来创建一个分层网络。此范式需要每个 cluster 中有一个 cluster 管理者,其负责在系统或 APIC 总线之间处理消息的传递。每个 cluster 最多包含 4 个 agent。因此 15 个 cluster 管理者,每个有 4 个 agent,可以组成一个最多有 60 个 APIC agent 的网络。注意,分层 APIC 网络需要一个特殊的 cluster 管理设备,其不属于 local 或 I/O APIC。
注意:如果处理器使能了其 APIC(通过伪中断 vector enable/disable bit),则必须也要将其 DFRs(Destination Format Registers)编程为唯一的。DFR 的默认模式是 flat mode。如果你要使用 cluster mode,你必须在使能 APIC 之前正确编程 DFRs。因为有些芯片组无法对 logic mode 正确地建立起系统视图,最好在处理器启动后尽快做 DFRs 的编程。
3.2.3 Broadcast/Self Delivery Mode[10.6.2.3]
ICR 的 destination shorthand 域可以 bypass 掉 delivery mode,从而支持对系统总线上所有处理器的 IPI 广播,和/或对其自身的 IPI【Section 10.6.1, “Interrupt Command Register(ICR)”】。支持三种 destination shorthand:self、all excluding self 以及 all including self。使用 destination shorthand 时会忽略 destination mode。
3.2.4 Lowest Priority Delivery Mode[10.6.2.4]
lowest priority delivery mode 下,通过 logical 或 shorthand destination 机制来选择目标处理器,通过编程 ICR 来对系统总线上的若干处理器发起 IPI。系统总线或 APIC 总线会对所选处理器进行仲裁,最低优先级的处理器将接收此 IPI。
基于 Intel Xeon 处理器的系统,芯片组总线控制器接收来自系统中 I/O APIC agents 的消息,并将中断投递给系统总线上的处理器。通过 lowest priority delivery mode,芯片组在可能的目标组中挑选一个目标处理器来接收此中断。Pentium 4 处理器在系统总线上,通过一个特殊的 bus cycle,来告诉芯片组,系统上各逻辑处理器的当前 task priority 是多少。芯片组存下此信息,当其收到一个中断时,利用此信息来选择最低优先级的处理器。
基于 P6 family 处理器的系统,用于做最低优先级仲裁的处理器优先级,是存在每个 local APIC 的 arbitration priority register(APR) 中的。Figure 10-15 是 APR 的布局。
APR 值的计算如下:
其中,TPR 的值为 TRR(Figure 10-18)中的 task priority 的值,IRRV 的值为 IRR(Figure 10-20)中最高优先级 bit 的 vector 号,当 IRR 中没有 bit 被设置时,其为 00H,ISRV 的值为 ISR(Figure 10-20)中最高优先级 bit 的 vector 号。APR 值最低的处理器处理此 IPI,其他处理器忽略之。
对于这些处理器(P6 family 及 Pentium 处理器),如果存在一个 focus processor,无论其优先级如何,其都可能会接收此中断。当一个处理器正在处理某个中断,或其有一个此中断的 pending 请求时,称该处理器 “focus” 此中断。Intel Xeon 处理器上,不支持 focus 处理器的概念。
对于那些使用了 lowest priority delivery mode,但并不会更新 TPR 的操作系统,芯片组中所保存的 TPR 信息,可能会导致中断总是被投递到同一个处理器。此行为是为了向后兼容 P6 family 处理器,但可能会对性能产生不符合预期的影响。
译者注:lowest priority mode 的思想是,选中所运行 task 优先级最低的处理器来处理中断,也很 make sense,APIC 设计此寄存器的本意,是希望操作系统在做任务切换时可以更新 TPR,但 linux 并未采用此机制。focus processor 的思想是,同一种中断尽量交付给同一个处理器(也就是所谓的 focus processor)来处理,如此可以避免 cache thrashing;但这也可能会导致该处理器上的进程饥饿、系统中断负载不均衡等。
3.3 IPI 的发送与接收[10.6.3]
ICR 的低 double-word 被写入时,local APIC 会向总线上发送一个 IPI 消息,IPI 消息的信息包含在 ICR 中。具体 IPI 的接收与处理,见 Section 10.8,“Handling Interrupts”。
- 系统总线及 APIC 总线仲裁[10.7]
多个 local APIC 及 I/O APIC 在系统总线(或 APIC 总线)上发送 IPI 和 中断消息时,消息被发送及处理的顺序是由总线仲裁决定的。
对于 Pentium 4 及 Intel Xeon 处理器,local 及 I/O APIC 采用为系统总线定义的仲裁机制来决定 IPI 的处理顺序。此机制是非 architectural 的,不可被软件控制。
对于 P6 family 及 Pentium 处理器,local 及 I/O APIC 采用基于 APIC 的仲裁机制来决定 IPI 的处理顺序。local APIC 被赋予一个 0 到 15 的仲裁优先级,其被 I/O APIC 用来决定哪个 local APIC 可以访问 APIC 总线。最高优先级的 local APIC 总是赢得总线。每一轮仲裁后,赢家 local APIC 将其仲裁优先级降为 0,败者 local APIC 将其优先级加 1(译者注:kind of round robin)。
目前一个 local APIC 的仲裁优先级存在一个 4 bit、对软件透明的仲裁 ID(Arb ID)寄存器中。复位后,此寄存器被初始为 APIC ID 的值(存在 local APIC ID 寄存器中)。可通过由 ICR 发起的 INIT level-deassert IPI 来重新同步 local APICs 的仲裁优先级,会将每个 agent 的 Arb ID 寄存器重置为其当前 APIC ID 的值。(Pentium 4 及 Intel Xeon 处理器没有实现 Arb ID 寄存器)。
Section 10.10,“APIC Bus Message Passing Mechanism and Protocol(P6 Family, Pentium Processors)” 描述了 APIC 总线仲裁协议以及总线消息格式,Section 10.6.1,“Interrupt Command Register(ICR)” 描述了 INIT level de-assert IPI 消息。
注意,SIPI IPI【Section 10.6.1, “Interrupt Command Register(ICR)”】除外,所有(在总线竞争中失败而)没有投递给其指定目标处理器(们)的总线消息会被重试。软件应该避免将 IPI 发给被禁能或不存在的 local APIC,因为这将导致消息会被一直重试。另外,目标是(被禁能或不存在的)APIC 的中断源,应该将其 mask 掉,或将其目标改成其他 APIC。