10. 启动中断¶
- 作者:
Sean V Kelley <sean.v.kelley@linux.intel.com>
10.1. 概述¶
在 PCI Express 上,中断以 MSI 或入站中断消息(Assert_INTx/Deassert_INTx)表示。给定 Core IO 中的集成 IO-APIC 将来自 PCI Express 的传统中断消息转换为 MSI 中断。如果 IO-APIC 被禁用(通过 IO-APIC 表条目中的屏蔽位),则消息将路由到传统的 PCH。这种带内中断机制传统上对于不支持 IO-APIC 的系统以及启动是必需的。英特尔过去使用术语“启动中断”来描述这种机制。此外,PCI Express 协议描述了这种带内传统有线中断 INTx 机制,用于 I/O 设备发出 PCI 样式级别中断信号。后续段落描述了 Core IO 处理 INTx 消息路由到 PCH 的问题,以及 BIOS 和 OS 中的缓解措施。
10.2. 问题¶
当带内传统 INTx 消息转发到 PCH 时,它们会反过来触发一个新的中断,而操作系统可能缺少该中断的处理程序。当一个中断长时间未处理时,Linux 内核会将其跟踪为伪中断。当 IRQ 达到特定计数并显示错误“nobody cared”后,Linux 内核会禁用该 IRQ。此禁用的 IRQ 现在阻止了现有中断的有效使用,而该中断可能恰好共享该 IRQ 行。
irq 19: nobody cared (try booting with the "irqpoll" option)
CPU: 0 PID: 2988 Comm: irq/34-nipalk Tainted: 4.14.87-rt49-02410-g4a640ec-dirty #1
Hardware name: National Instruments NI PXIe-8880/NI PXIe-8880, BIOS 2.1.5f1 01/09/2020
Call Trace:
<IRQ>
? dump_stack+0x46/0x5e
? __report_bad_irq+0x2e/0xb0
? note_interrupt+0x242/0x290
? nNIKAL100_memoryRead16+0x8/0x10 [nikal]
? handle_irq_event_percpu+0x55/0x70
? handle_irq_event+0x4f/0x80
? handle_fasteoi_irq+0x81/0x180
? handle_irq+0x1c/0x30
? do_IRQ+0x41/0xd0
? common_interrupt+0x84/0x84
</IRQ>
handlers:
irq_default_primary_handler threaded usb_hcd_irq
Disabling IRQ #19
10.3. 条件¶
今天触发此问题的最可能条件是使用线程中断。线程中断在 IRQ 处理程序唤醒后可能不会重新启用。这些“一次性”条件意味着线程中断需要保持中断线被屏蔽,直到线程处理程序运行。尤其是在处理高数据速率中断时,线程需要运行完成;否则,一些处理程序最终会发生堆栈溢出,因为发出设备的的中断仍然处于活动状态。
10.4. 受影响的芯片组¶
传统的 中断转发机制现在存在于许多设备中,包括但不限于 AMD/ATI、Broadcom 和 Intel 的芯片组。通过以下缓解措施进行的更改已应用于 drivers/pci/quirks.c
从 ICX 开始,Core IO 的设备中不再有任何 IO-APIC。IO-APIC 仅位于 PCH 中。连接到 Core IO 的 PCIe 根端口的设备将使用本机 MSI/MSI-X 机制。
10.5. 缓解措施¶
缓解措施采用 PCI quirks 的形式。首选方法是首先识别并利用一种禁用路由到 PCH 的方法。在这种情况下,可以添加一个禁用启动中断生成的 quirk。[1]
- Intel® 6300ESB I/O 控制器集线器
- 备用基地址寄存器
BIE:启动中断使能
0
启动中断已启用。
1
启动中断已禁用。
- 基于 Intel® Sandy Bridge 到 Sky Lake 的 Xeon 服务器
- 相干接口协议中断控制
- dis_intx_route2pch/dis_intx_route2ich/dis_intx_route2dmi2
设置此位后。从 Intel® 快速数据 DMA/PCI Express 端口接收的本地 INTx 消息不会路由到传统的 PCH - 它们要么通过集成的 IO-APIC 转换为 MSI(如果 IO-APIC 屏蔽位在相应的条目中是清除的),要么不执行进一步的操作(当设置了屏蔽位时)
在没有直接禁用路由的方法的情况下,另一种方法是使用 PCI 中断引脚到 INTx 路由表,以便默认将中断处理程序重定向到重新路由的中断线。因此,在无法禁用 INTx 路由的芯片组上,Linux 内核会将有效中断重新路由到其传统中断。处理程序的这种重定向将防止出现伪中断检测,否则会由于未处理的计数过多而禁用 IRQ 行。[2]
配置选项 X86_REROUTE_FOR_BROKEN_BOOT_IRQS 用于启用(或禁用)将中断处理程序重定向到 PCH 中断线。该选项可以被 pci=ioapicreroute 或 pci=noioapicreroute 覆盖。[3]
10.6. 更多文档¶
在几个数据表中(下面是 6300ESB 和 6700PXH)概述了传统中断处理。虽然大体上相同,但它提供了对其处理与芯片组的演变的见解。
10.6.1. 禁用启动中断的示例¶
Intel® 6300ESB I/O 控制器集线器(文档 # 300641-004US)5.7.3 启动中断 https://www.intel.com/content/dam/doc/datasheet/6300esb-io-controller-hub-datasheet.pdf
Intel® Xeon® 处理器 E5-1600/2400/2600/4600 v3 产品系列数据表 - 第 2 卷:寄存器(文档 # 330784-003)6.6.41 cipintrc 相干接口协议中断控制 https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-v3-datasheet-vol-2.pdf
10.6.2. 处理程序重新路由的示例¶
Intel® 6700PXH 64 位 PCI 集线器(文档 # 302628)2.15.2 PCI Express 传统 INTx 支持和启动中断 https://www.intel.com/content/dam/doc/datasheet/6700pxh-64-bit-pci-hub-datasheet.pdf
如果您有任何未解答的传统 PCI 中断问题,请给我发送电子邮件。
- 祝您愉快,
Sean V Kelley sean.v.kelley@linux.intel.com