ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SSD 的 MSI / MSI-X 中断机制解析

SSD 的 MSI / MSI-X 中断机制解析 本文主要针对PCIe NVMe SSD。SATA/AHCI SSD 也可能使用 MSI/MSI-X但其命令完成模型是 AHCI/NCQ不完全适用 NVMe 的 SQ/CQ、Completion Queue Interrupt Vector 等概念。目录1. 先给结论2. INTx、MSI、MSI-X 的区别2.1 Legacy INTx2.2 MSIMSI 的关键特点2.3 MSI-XMSI-X 的优势2.4 对比表3. MSI/MSI-X 中的几个“编号”不要混淆3.1 NVMe Completion Queue ID3.2 MSI-X Vector Index3.3 Linux IRQ Number3.4 CPU Interrupt Vector4. NVMe 中的队列和中断关系4.1 Submission Queue 和 Completion Queue4.2 Completion Queue 的 Interrupt Vector5. NVMe MSI-X 的完整工作流程5.1 PCIe 枚举阶段5.2 MSI-X Table 初始化5.3 NVMe 控制器初始化5.4 主机提交 I/O5.5 SSD 写入 Completion Queue5.6 CPU 处理中断6. 为什么有时“完成了但没有中断”6.1 处于轮询模式6.2 中断被 Mask6.3 中断聚合7. 常见应用场景7.1 一队列一个 MSI-X 向量7.2 多个 CQ 共享一个 MSI-X 向量7.3 降级到单 MSI7.4 轮询模式7.5 虚拟化和 SR-IOV8. Linux 下的检查方法8.1 查看 MSI/MSI-X 是否启用8.2 查看实际中断计数8.3 查看 PCI 设备的 MSI IRQ 列表8.4 查看 IRQ CPU 亲和性8.5 查看内核日志8.6 查看 PCIe 链路和 AER 状态9. 常见故障现象和排查思路9.1 现象一I/O 超时/proc/interrupts 不增长优先检查常见原因9.2 现象二IRQ 计数增长但 I/O 仍然超时9.3 现象三中断风暴9.4 现象四只有一个 CPU 有中断其他 CPU 没有9.5 现象五性能低、CPU 中断占用高9.6 现象六系统重置或热复位后中断失效10. MSI-X 硬件或 FPGA SSD 的调试重点10.1 MSI-X Capability 描述错误10.2 没有使用主机写入的地址和数据10.3 CQE 和 MSI-X 消息的顺序错误10.4 Vector Index 和 CQ 配置不一致10.5 Mask 和 Pending 处理错误11. 建议的系统化排查流程第一步确认是否真的需要中断第二步确认 PCIe 中断模式第三步确认实际 IRQ第四步确认控制器和队列状态第五步确认所有 Mask 层第六步确认 PCIe、IOMMU 和中断路由第七步确认 CPU 和 NUMA12. 需要特别记住的几个结论1. 先给结论NVMe SSD 的一次典型 I/O 完成过程可以概括为主机提交 SQ Entry │ ▼ SSD 控制器 DMA 读取 SQ │ ▼ SSD 执行命令 │ ▼ SSD DMA 写入 CQE │ ▼ SSD 发送 MSI/MSI-X 消息 │ ▼ Root Complex / IOMMU / APIC 或 GIC │ ▼ CPU 进入 NVMe 中断处理函数 │ ▼ 驱动读取 CQE、完成请求、更新 CQ Head Doorbell最重要的一点MSI/MSI-X 只是“通知主机有完成事件”中断消息本身不携带 NVMe Completion Entry。真正的完成信息已经由 SSD 通过 DMA 写入主机内存中的 Completion Queue。2. INTx、MSI、MSI-X 的区别2.1 Legacy INTx传统 PCI 中断通常使用 INTx 引脚设备拉低中断线 │ ▼ 主机响应中断 │ ▼ 驱动读取设备状态并清除中断特点物理或逻辑中断线多个 PCI 设备可能共享同一条中断线属于电平触发方式需要设备和驱动显式清除中断状态扩展性差容易产生共享中断和中断抖动。在现代 NVMe SSD 中INTx 通常只是兼容性兜底方式。2.2 MSIMSI即 Message Signaled Interrupt。它不是通过独立的中断引脚而是设备发起一个 PCIe Memory Write TLP写入由操作系统配置好的中断消息地址和数据SSD │ │ PCIe Memory Write TLP ▼ MSI 地址 / 数据 │ ▼ Root Complex │ ▼ APIC / GIC / Interrupt Remapping │ ▼ CPU IRQMSI 的关键特点不使用共享中断线中断通过 PCIe 总线事务传递一般支持 1、2、4、8、16、32 个消息多 MSI 数量通常要求是 2 的幂所有 MSI 消息通常使用相同的 Message Address仅 Message Data 有区别每个 MSI 向量的独立性不如 MSI-X支持能力受设备、操作系统和平台限制。PCI MSI Capability 中通常包括MSI EnableMultiple Message CapableMultiple Message Enable32 位或 64 位 Message AddressMessage Data可选的 Per-Vector Mask 和 Pending Bits。2.3 MSI-XMSI-X 是为大量独立中断向量设计的扩展机制。MSI-X 一般最多支持 2048 个向量而且每个向量都有独立的Message Address Message Data Vector Mask典型结构如下MSI-X Table ┌────────────────────────────┐ │ Entry 0: Addr/Data/Mask │ │ Entry 1: Addr/Data/Mask │ │ Entry 2: Addr/Data/Mask │ │ ... │ │ Entry N: Addr/Data/Mask │ └────────────────────────────┘ PBA: Pending Bit ArrayMSI-X Table 和 Pending Bit Array 通常位于设备 BAR 指定的位置。每个 MSI-X Table Entry 通常包含Message Address Low Message Address High Message Data Vector Control其中 Vector Control 中通常有 Mask 位。MSI-X 的优势每个队列可以使用独立向量每个向量可以绑定到不同 CPU适合 NVMe 多队列、高 IOPS 场景支持任意数量的向量不要求 2 的幂向量间隔离性更好可以将不同队列分散到不同 NUMA 节点和 CPU。2.4 对比表特性INTxMSIMSI-X传递方式中断线PCIe Memory WritePCIe Memory Write是否共享经常共享通常不共享通常不共享向量数量少通常最多 32最多 2048向量数量要求无通常为 2 的幂可任意分配每向量独立地址无有限有每向量独立 Mask无可选支持适合 NVMe 多队列较差一般最适合典型使用兼容性回退低队列或降级场景高性能默认方案3. MSI/MSI-X 中的几个“编号”不要混淆NVMe 调试中经常把以下几个概念混为一谈。3.1 NVMe Completion Queue ID例如CQ1、CQ2、CQ3这是 NVMe 协议中的队列编号。3.2 MSI-X Vector Index例如MSI-X vector 0、vector 1、vector 2这是 MSI-X Table 的索引也是 NVMe Create I/O Completion Queue 命令中 IV 字段所引用的向量编号。3.3 Linux IRQ Number例如IRQ 123 IRQ 124这是 Linux 内核分配给设备中断的 IRQ 号。3.4 CPU Interrupt Vector这是 CPU/APIC 层面的硬件中断向量例如某个内部向量号。它们之间并不一定相等NVMe IV 3 │ ▼ MSI-X Table Entry 3 │ ▼ Linux IRQ 157 │ ▼ CPU APIC Vector 0xE1因此NVMe 的 Interrupt Vector、MSI-X Table Index、Linux IRQ 号不是同一个概念。4. NVMe 中的队列和中断关系4.1 Submission Queue 和 Completion QueueNVMe 使用成对或多对队列Submission QueueSQ主机提交命令 Completion QueueCQSSD 返回完成结果典型关系SQ1 ───────┐ ├── CQ1 ── MSI-X Vector 1 SQ2 ───────┘ SQ3 ───────┐ ├── CQ2 ── MSI-X Vector 2 SQ4 ───────┘多个 Submission Queue 可以关联到同一个 Completion Queue。真正决定中断向量的是Completion Queue而不是 Submission Queue。4.2 Completion Queue 的 Interrupt Vector创建 I/O Completion Queue 时主机通常会指定Completion Queue ID队列深度队列物理地址Interrupt Enable通常称为IENInterrupt Vector通常称为IV。概念上相当于Create CQ1: IEN 1 IV 1 Create CQ2: IEN 1 IV 2于是CQ1 的完成事件 - MSI-X Vector 1 CQ2 的完成事件 - MSI-X Vector 2Admin Completion Queue 在规范和常见驱动实现中通常使用 vector 0但具体仍以驱动和控制器实现为准。5. NVMe MSI-X 的完整工作流程5.1 PCIe 枚举阶段系统启动时PCIe Root Complex 枚举 SSD读取 PCI Configuration Space检查 MSI Capability检查 MSI-X Capability读取 MSI-X Table Size读取 MSI-X Table 的 BAR、偏移读取 PBA 的 BAR、偏移分配 PCI 资源建立中断路由。Linux 中驱动通常会通过类似以下机制申请中断向量pci_alloc_irq_vectors(...) pci_irq_vector(...) request_irq(...)实际函数和参数会随内核版本变化。一般选择顺序是MSI-X ↓ 失败 MSI ↓ 失败 Legacy INTx不过具体行为依赖驱动和操作系统。5.2 MSI-X Table 初始化操作系统或 PCI 子系统会为每个 MSI-X Table Entry 写入Message Address Message Data Vector Mask例如MSI-X Entry 0 - Linux IRQ 100 MSI-X Entry 1 - Linux IRQ 101 MSI-X Entry 2 - Linux IRQ 102注意Table 中的 Message Address 不是固定值不能把 x86 上常见的0xFEE...地址硬编码到设备中在 IOMMU、Interrupt Remapping、虚拟化或 ARM GIC ITS 环境下地址和数据可能完全不同设备必须使用主机写入的地址和数据。5.3 NVMe 控制器初始化驱动随后初始化 NVMe 控制器创建 Admin Submission Queue创建 Admin Completion Queue使能控制器查询或设置 I/O Queue 数量创建 I/O Completion Queues为每个 CQ 指定IV创建与 CQ 关联的 Submission Queue开启相关中断绑定 IRQ affinity。一个常见布局可能是MSI-X Vector 0 - Admin CQ MSI-X Vector 1 - I/O CQ 1 MSI-X Vector 2 - I/O CQ 2 MSI-X Vector 3 - I/O CQ 3 ...但如果向量不够也可能是MSI-X Vector 1 - CQ1、CQ5 MSI-X Vector 2 - CQ2、CQ6 MSI-X Vector 3 - CQ3、CQ75.4 主机提交 I/O主机驱动完成以下动作在 SQ 中填写 NVMe Command更新本地 SQ Tail通过 MMIO 写 SQ Tail DoorbellSSD 看到 Doorbell 变化SSD DMA 读取 SQ Entry。5.5 SSD 写入 Completion Queue命令完成后SSD执行存储操作生成 Completion Entry通过 DMA 将 CQE 写入主机内存更新 CQ Entry 中的 Phase Bit根据中断聚合和 Mask 状态决定是否发送中断找到对应的 Interrupt Vector读取 MSI-X Table Entry生成 MSI-X PCIe Memory Write。CQE 中通常包含Command IdentifierCIDSubmission Queue HeadSubmission Queue IdentifierStatusPhase Bit其他状态信息。5.6 CPU 处理中断CPU 收到 MSI-X 后进入类似以下逻辑nvme_irq(vector) ├── 找到该 vector 关联的 CQ ├── 检查 CQ 中是否有新的 CQE ├── 检查 Phase Bit ├── 读取 CID 和 Status ├── 完成对应 Block Layer Request ├── 推进本地 CQ Head └── 写 CQ Head Doorbell注意在 MSI-X 中设备没有像 INTx 那样的“拉线保持”和明确的硬件 ACK 概念。主机真正解除设备侧待处理状态的关键动作是消费 CQE 并更新 CQ Head Doorbell。CPU 的 APIC EOI 仍由操作系统中断子系统处理。6. 为什么有时“完成了但没有中断”以下情况都可能导致 CQE 已经写入但暂时没有看到中断6.1 处于轮询模式某些 NVMe 驱动、SPDK、DPDK 或高性能应用会使用 polling主机主动轮询 CQ 而不是等待 MSI-X这种情况下I/O 可以正常完成/proc/interrupts中断计数可能不增长没有中断并不代表异常。Linux 也可能配置部分 polling queues。6.2 中断被 Mask可能存在多层 MaskMSI-X Table Entry 的 Vector MaskMSI-X Function MaskNVMeINTMS寄存器CQ 创建时IEN 0Linux IRQ 被禁用设备处于复位或电源管理状态。这些 Mask 并不等价需要逐层确认。6.3 中断聚合NVMe 支持 Interrupt Coalescing。控制器可能不会在每个 CQE 写入后都立刻中断而是满足以下条件之一后再中断累计完成数达到阈值等待时间达到定时器值控制器内部触发强制刷新。好处减少中断次数降低 CPU 消耗提高高 IOPS 场景的吞吐。代价增加单个 I/O 的完成延迟参数不合理时表现为“中断很少”或“延迟突然升高”。NVMe 中通常有Interrupt Coalescing FeatureInterrupt Vector Configuration Feature。工具支持时可以查看类似nvme get-feature /dev/nvme0 -f 0x08不同工具版本和控制器支持情况可能不同。7. 常见应用场景7.1 一队列一个 MSI-X 向量CQ1 - Vector 1 - CPU 1 CQ2 - Vector 2 - CPU 2 CQ3 - Vector 3 - CPU 3适合高并发随机 I/O多核系统高端 PCIe SSD每 CPU 或每 NUMA 节点绑定一个队列。优点低共享中断处理并行便于 CPU affinity适合高 IOPS。缺点占用更多向量每个队列都可能产生中断中断频率过高时 CPU 消耗增加。7.2 多个 CQ 共享一个 MSI-X 向量CQ1 ─┐ CQ5 ─┴── Vector 1 CQ2 ─┐ CQ6 ─┴── Vector 2适合MSI-X 向量数量不足虚拟机或 SR-IOV VF低端控制器系统限制了最大 IRQ 数量。中断处理函数通常需要扫描该 vector 关联的多个 CQ。缺点共享 vector 的队列相互影响扫描队列增加处理开销可能导致某些队列延迟增加。7.3 降级到单 MSI所有 CQ - MSI Vector 0常见原因MSI-X 分配失败平台不支持 MSI-X虚拟化环境限制驱动参数或内核策略控制器 MSI-X Capability 描述错误。这种模式下 I/O 仍然可能正常但所有队列共享一个 IRQ中断处理集中到一个 CPU高 IOPS 场景吞吐和延迟可能明显变差。7.4 轮询模式应用或驱动主动读取 CQ适合极低延迟场景用户态 NVMeSPDK高速存储测试CPU 资源充足的环境。优点避免中断切换延迟更稳定高 IOPS 下性能好。缺点消耗 CPU空闲时效率低通用块设备场景不一定适合。7.5 虚拟化和 SR-IOV在虚拟化环境中MSI-X 可能经过Guest MSI-X ↓ 虚拟机监控器 ↓ 物理 MSI-X / Posted Interrupt / vIOMMU ↓ 物理 CPU可能遇到VF 的 MSI-X 向量数较少Guest 中看到的向量数与 PF 不同中断经过虚拟化转发虚拟机迁移或 reset 后向量重新分配IOMMU/Interrupt Remapping 配置导致消息地址不同。8. Linux 下的检查方法8.1 查看 MSI/MSI-X 是否启用lspci -vv -s 0000:xx:yy.z重点观察类似信息MSI: Enable Count1/1 MSI-X: Enable Count64 Masked-含义Enable该模式当前启用Count64设备最多提供或报告 64 个 MSI-X 表项不代表操作系统实际创建了 64 个 I/O 队列Masked-通常表示没有被整体 Mask但仍不能替代对 NVMe 和驱动状态的检查。注意MSI-X Capability 中的 Count 通常是最大能力不一定等于实际分配的 IRQ 数量。8.2 查看实际中断计数grep -i nvme /proc/interrupts可能看到120: 10023 0 0 0 IR-PCI-MSI nvme0q0 121: 0 9821 0 0 IR-PCI-MSI nvme0q1 122: 0 0 9934 0 IR-PCI-MSI nvme0q2可以观察是否存在多个nvme0qX每个 IRQ 是否都在增长是否只有一个 IRQ 增长是否只有 CPU0 处理IRQ 是否极度集中。注意没有 I/O 时计数不增长是正常的polling 模式下计数不增长也可能正常中断计数增长不代表 CQE 一定被正确处理。8.3 查看 PCI 设备的 MSI IRQ 列表BDF0000:xx:yy.z ls /sys/bus/pci/devices/$BDF/msi_irqs/ cat /sys/bus/pci/devices/$BDF/irq不同内核版本中 sysfs 内容可能略有不同。8.4 查看 IRQ CPU 亲和性IRQ120 cat /proc/irq/$IRQ/smp_affinity_list cat /proc/irq/$IRQ/effective_affinity_list还可以查看设备 NUMA 节点cat /sys/bus/pci/devices/$BDF/numa_node重点确认IRQ 是否运行在正确 CPUCPU 是否和 SSD 位于同一 NUMA 节点是否被 irqbalance 自动迁移是否所有 IRQ 集中在一个 CPU是否某些 IRQ 被绑定到了不合适的 NUMA 节点。8.5 查看内核日志dmesg -T | grep -iE \ nvme|msi|msix|aer|iommu|dmar|amd-vi|timeout|reset重点关注I/O timeoutreset controllerfailed to allocate IRQMSI-X分配失败AER错误IOMMU DMA faultPCIe link downCompletion Queue overflowcontroller fatal status。8.6 查看 PCIe 链路和 AER 状态lspci -vv -s 0000:xx:yy.z关注LnkStaLink SpeedLink WidthCorrectable ErrorNon-Fatal ErrorFatal ErrorUnsupported RequestCompletion TimeoutReceiver Error。MSI-X 消息本身也是 PCIe 事务。如果 PCIe 链路、Root Port、IOMMU 或 Interrupt Remapping 有问题设备可能已经完成命令但中断消息没有正常抵达 CPU。9. 常见故障现象和排查思路9.1 现象一I/O 超时/proc/interrupts不增长优先检查是否真的产生了 I/O是否启用了 pollinglspci -vv中 MSI-X 是否为Enable实际是否降级到了 MSI 或 INTxNVMe 控制器是否处于CSTS.RDY1NVMeINTMS是否屏蔽MSI-X Table Entry 是否被 MaskCQ 是否创建时IEN1CQ 的 IV 是否指向正确向量设备是否真的写入了 CQE是否存在 IOMMU、AER、PCIe 链路错误。常见原因MSI-X 没有启用MSI-X Table 被错误配置CQ 使用了错误的 Interrupt Vector控制器处于复位状态IRQ 被禁用IOMMU 拒绝了 MSI 或 DMASSD 没有产生 CQE设备写入 CQE 的 DMA 地址错误使用 polling误以为应该有中断。9.2 现象二IRQ 计数增长但 I/O 仍然超时这种情况通常说明中断消息已经到达 CPU但 NVMe 完成处理链路有问题。重点检查中断处理函数是否找到正确的 CQCQE 是否真的写入CQE Phase Bit 是否正确CID 是否能匹配到原始请求CQ Head 是否正确推进CQ Doorbell 是否正确写回DMA 内存是否可见CPU Cache 是否同步内核驱动是否出现锁竞争或异常退出。常见原因CQE DMA 写入错误地址Phase Bit 处理错误CQ Head 没有更新CQE 中 CID 错误设备生成了错误的 MSI-X vectorISR 进入了错误的队列处理路径共享 vector 扫描逻辑存在问题。9.3 现象三中断风暴表现为/proc/interrupts 中某个 nvme IRQ 快速增长 CPU 使用率升高 I/O 性能下降常见原因ISR 没有消费 CQECQ Head Doorbell 没有更新Phase Bit 判断错误设备不断认为 CQ 中存在未处理 CQEMSI-X Pending Bit 没有正确清除共享 vector 处理函数没有扫描到真正产生事件的 CQ中断聚合参数不合理AER 或设备错误导致重复中断控制器持续报告异步事件。排查重点是否存在未消费 CQE CQ Head 是否推进 CQ Tail/Phase 是否一致 ISR 退出前是否还有 pending CQE 是否是共享 vector9.4 现象四只有一个 CPU 有中断其他 CPU 没有可能原因只分配了一个 MSI/MSI-X 向量所有 CQ 共享一个 vectorirqbalance 将 IRQ 集中到了一个 CPUIRQ affinity 没有正确配置NVMe 驱动根据 CPU 数量只创建了少量队列虚拟化环境限制了向量数量控制器 NUMA 拓扑和 CPU 绑定不合理。可检查grep -i nvme /proc/interrupts cat /proc/irq/IRQ/effective_affinity_list性能优化方向增加 I/O Queue 数量使用 MSI-X让队列数与 CPU 或工作线程数匹配设置合理 IRQ affinity让 IRQ 与内存、SSD 位于同一 NUMA 节点避免所有队列共享同一个 vector。9.5 现象五性能低、CPU 中断占用高常见原因降级到了单 MSI多个 CQ 共享一个向量I/O 粒度很小没有启用中断聚合中断亲和性配置不合理中断集中在一个 CPU设备队列数少使用了不合适的 NUMA 绑定中断与软中断、块层处理产生竞争。可以从以下角度优化确认 MSI-X 是否启用确认实际分配的 vector 数量检查 CQ 与 vector 的映射调整 CPU affinity检查 NUMA调整 NVMe Interrupt Coalescing对极低延迟业务评估 polling对高 IOPS 业务增加队列并避免过度共享。9.6 现象六系统重置或热复位后中断失效常见原因FLR 后 MSI-X Table 内容被设备清除驱动没有重新写入 MSI-X TableIRQ 已经重新分配但设备仍使用旧的地址/数据CQ 和 SQ 已经被重新创建但 IV 映射未更新控制器尚未重新解除 Maskreset 流程中存在旧请求和新队列并发PCIe Link Recovery 后设备状态与驱动状态不一致。正确的 reset 流程通常需要停止新 I/O 等待或取消旧请求 Mask 中断 停止控制器 重新初始化 MSI/MSI-X 重新创建 Admin Queue 重新创建 I/O CQ/SQ 重新配置 vector 映射 解除 Mask 恢复 I/O10. MSI-X 硬件或 FPGA SSD 的调试重点如果是自研 SSD 控制器、FPGA NVMe Endpoint 或定制 PCIe 设备MSI-X 问题通常集中在以下位置。10.1 MSI-X Capability 描述错误检查Capability 链表是否正确Table Size 是否正确Table BIR 是否指向正确 BARTable Offset 是否正确PBA BIR 是否正确PBA Offset 是否正确Table 是否按规范对齐Table Entry 是否为正确大小BAR 空间是否足够。MSI-X Table Entry 通常为 16 字节。10.2 没有使用主机写入的地址和数据错误做法设备内部硬编码一个 MSI 地址 设备内部硬编码一个中断数据正确做法主机通过 MSI-X Table 写入地址和数据 设备读取或使用对应 Table Entry 设备按照该 Entry 生成 MSI-X Message特别是在以下环境中硬编码几乎一定会失败IOMMU 开启Interrupt Remapping 开启ARM GIC ITS虚拟机SR-IOV不同 BIOS 或不同内核多 Socket 系统。10.3 CQE 和 MSI-X 消息的顺序错误设备必须保证先让 CQE 对主机可见 再发送 MSI-X Message错误顺序可能是先发送 MSI-X 后完成 CQE DMA 写入此时 CPU 进入 ISR 后可能读不到有效 CQE表现为中断计数增长驱动找不到完成项I/O 长时间 pending后续可能产生中断风暴。需要关注PCIe TLP 顺序设备内部 DMA 写入完成标志内存屏障DMA 一致性非一致性 ARM 平台上的 Cache SyncCQE 写入和 MSI 写入之间的排序保证。10.4 Vector Index 和 CQ 配置不一致例如主机创建 CQ3指定 IV3 设备实际向 Table Entry 2 发送中断可能导致中断进入错误的 ISRISR 找不到待处理 CQ某个 CQ 一直不处理另一个 CQ 产生大量“伪中断”。测试时建议先只启用一个 CQ只使用 vector 0 或 vector 1确认单队列路径再逐步增加 CQ 和 MSI-X vector最后测试共享 vector。10.5 Mask 和 Pending 处理错误需要同时检查MSI-X Function MaskMSI-X Vector Control MaskPBA Pending BitNVMe INTMSCQ 的 IEN控制器内部中断 pending 状态Reset 后是否清理旧状态。11. 建议的系统化排查流程可以按以下顺序排查。第一步确认是否真的需要中断是否使用 polling 是否有实际 I/O 是否只是空闲状态第二步确认 PCIe 中断模式lspci -vv -s BDF确认MSI-X: Enable如果是MSI-X: Enable- MSI: Enable说明实际使用的是 MSI而不是 MSI-X。第三步确认实际 IRQgrep -i nvme /proc/interrupts ls /sys/bus/pci/devices/BDF/msi_irqs/判断是否只有一个 IRQ是否有多个 nvme 队列 IRQ是否有 IRQ 计数是否 IRQ 分布在多个 CPU。第四步确认控制器和队列状态关注Controller 是否 ReadyAdmin Queue 是否正常I/O CQ 是否创建成功CQ 的 IV 是否正确CQ 的 IEN 是否打开CQ 是否有有效 CQEPhase Bit 是否变化CQ Head Doorbell 是否推进。第五步确认所有 Mask 层PCI MSI/MSI-X Enable MSI-X Function Mask MSI-X Vector Mask NVMe INTMS CQ IEN Linux IRQ enable 状态第六步确认 PCIe、IOMMU 和中断路由检查dmesg -T | grep -iE aer|iommu|dmar|amd-vi|nvme|pci排除PCIe 链路异常Completion TimeoutIOMMU DMA FaultInterrupt Remapping 异常Root Port 错误虚拟化中断注入异常。第七步确认 CPU 和 NUMA检查cat /proc/irq/IRQ/effective_affinity_list cat /sys/bus/pci/devices/BDF/numa_node避免所有中断集中在 CPU0IRQ 位于远端 NUMA 节点irqbalance 与手工 affinity 冲突I/O 线程、内存和中断位于不同 NUMA 节点。12. 需要特别记住的几个结论MSI/MSI-X 是 PCIe 消息不是传统中断线。MSI/MSI-X 只传递通知不携带 NVMe CQE 内容。CQE 由 SSD DMA 写入主机内存。NVMe 的中断向量绑定在 Completion Queue 上。Submission Queue 不直接决定中断向量。MSI-X Count 是设备最大能力不等于实际使用的 IRQ 数量。NVMe IV、MSI-X Table Index、Linux IRQ、CPU Vector 不是同一个编号。MSI-X Enable 不代表一定已经有中断产生。中断不增长可能是 polling也可能是 Mask、路由、设备或 DMA 故障。中断增长但 I/O 不完成问题可能在 CQE、Phase、CID、Doorbell 或 DMA而不一定在 MSI-X。高性能 NVMe 通常优先使用 MSI-X多队列和 CPU affinity 是性能关键。自研硬件不能硬编码 MSI 地址和数据必须使用主机配置到 MSI-X Table 的内容。整体上可以把 NVMe MSI-X 理解为Completion Queue │ │ 通过 IV 指定 ▼ MSI-X Vector │ │ 通过 Table Entry 指定地址和数据 ▼ PCIe MSI-X Message │ ▼ Linux IRQ / CPU │ ▼ 驱动消费 CQE而排查问题时最有效的思路是把链路拆成四段SSD 是否写入 CQE ↓ SSD 是否生成 MSI/MSI-X ↓ PCIe/平台是否把 MSI 送到 CPU ↓ 驱动是否正确消费 CQE这四段分别对应设备数据通路、设备中断生成、PCIe/平台中断路由、操作系统驱动处理。只要逐段确认绝大多数“NVMe 中断不工作、IRQ 风暴、I/O 超时或 MSI-X 性能异常”都可以定位。
返回列表