尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Linux 内核 GICv3+ITS 翻译表完整指南:MSI 中断如何变成 LPI 并路由到目标 CPU

Linux 内核 GICv3+ITS 翻译表完整指南:MSI 中断如何变成 LPI 并路由到目标 CPU Linux 内核 GICv3ITS 翻译表完整指南MSI 中断如何变成 LPI 并路由到目标 CPU【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux设备越加越多可用的 SPI 中断号却只有 1020 个绑核还改不动。Linux 内核 GICv3 里的 ITS 翻译表解决的就是这个痛点把设备发来的 MSI 中断消息现场翻译成 LPI 中断号再路由到目标 CPU。本文讲清它怎么工作设备树配置 ITS 怎么写驱动建表流程长什么样。一、先看清楚问题SPI 路由的两个死穴SPI 这条路走到后期会卡住卡在两件事上中断号不够用和中断绑死了地方动不了。第一中断号耗尽。GICv3 的 SPI 编号范围是 32 到 1023一共 1020 个全系统共享。今天插一块网卡、明天加两块 NVMe、后天再上 RAID 卡每块设备想独占一路 SPI 就得占一个号号池见底只是时间问题。第二绑核僵化。SPI 是电平/边沿触发的硬件线路中断号和产生它的那块外设是物理上焊死的。你想把某个外设的中断从 CPU2 挪到 CPU5 做负载均衡可以改亲和性但你没法凭空多造一个某外设的 SPI也没法让同一个外设的不同队列各占一路线——线路就是那么多。而 PCIe 设备的 MSI 消息天然不同它走的是 TLP 包用消息里的地址加数据字段编码我是谁、哪个事件。消息数量基本不受硬件线数限制。缺的不是中断是把消息和中断号对上号的机制。二、一个类比讲透 ITS中断号码的转接台把 ITS 想象成总机转接台设备打来的每个 MSI 消息都是一次来电ITS 查表把哪个设备、哪个事件翻译成内部工单号LPI再按分机规则拨给对应 CPU。ITS 维护三张表恰好对应转接台里的三样东西。Device Table 是登记簿以 DeviceID 为索引记下该设备那张翻译表的基地址。来电先报分机号转接台先翻登记簿。Interrupt Translation TableITT是分机对照表以 EventID 为索引查到对应的 LPI 中断号INTID。报出事件转接台翻出工单号。Collection Table 是值班表LPI 该叫醒哪些 CPU 由它决定这也是运行时改亲和性的落点。整条链路一句话串起来外设发 MSI 消息 → ITS 从地址里拆出 DeviceID 和 EventID → Device Table 找到该设备的 ITT → ITT 把 EventID 换成 LPI 号 → Collection 决定发给哪个 CPU → 目标 CPU 执行中断处理程序。上面这张图把整条链路画全了上半部分是数据面消息怎么变中断下半部分提示这些表其实是内核通过命令队列预建好的。三、内核视角三步走探测、建表、注册 MSI domain驱动干三件事找到硬件并打开它把内存里的表建好然后把自己挂成 MSI domain 供上层申请中断。第一步探测irq-gic-v3-its.c 按设备树里compatible arm,gic-v3-its的节点逐个 ITS 初始化。第二步建表为每个 ITS 分配命令队列4K 到 64K 的页再分配 Device Table 和各 Collection表内容通过 ITS 命令队列写入命令顺序是 MAPD绑设备→ MAPC绑 collection→ MAPIEventID 映射 INTID→ MOV设亲和→ SYNC刷缓存使其生效。第三步注册its_init_domain()把 ITS 注册成 MSI domain此后 PCIe 设备用标准 MSI 接口申请中断内核自动翻译成走 ITS 的 LPI。驱动的关键路径可以精简成这样/* 每个 ITS 实例的初始化主干精简自 its_probe_one */ page its_alloc_pages(...); /* 分配命令队列内存内核往这里写命令 */ its-cmd_base (void *)page_address(page); err its_alloc_tables(its); /* 建 Device Table登记设备入口 */ if (err) goto out_free_cmd; err its_alloc_collections(its); /* 建 Collection决定 LPI 发给谁 */ if (err) goto out_free_tables; gits_write_cbaser(baser, its-base GITS_CBASER); /* 告诉 ITS 命令队列在哪 */ ctlr | GITS_CTLR_ENABLE; /* 打开 ITS 硬件 */ writel_relaxed(ctlr, its-base GITS_CTLR); err its_init_domain(its); /* 注册 MSI domain设备从此能申请 MSI */这段在做什么先给转接台拨号命令队列再摆好三张表的架子最后挂牌营业。真正的设备绑定和事件映射不是这里硬编码的而是之后经 MSI domain 回调触发its_alloc_device登记设备、its_map_irq建 EventID 到 LPI 的映射、its_set_affinity改目标 CPU全部翻译成命令队列里的 MAPD / MAPI / MOV 命令执行。四、动手配置一份能用的 GICv3ITS 设备树设备树里 ITS 就是一个带msi-controller标签的节点写对四个属性就够compatible、reg、msi-parent、#msi-cells。/* GIC 分发器 重分布器 */ gic: interrupt-controller2c000000 { compatible arm,gic-v3; #interrupt-cells 3; /* 类型、编号、触发方式 */ #address-cells 2; #size-cells 2; ranges 0x0 0x2c000000 0x0 0x10000; /* GICD 寄存器 */ #redistributor-regions 1; redistribitor2c010000 { reg 0x0 0x2c010000 0x0 0x200000; /* 每 CPU 一个 GICR */ }; }; /* ITS 翻译服务节点 */ its: msi-controller2c100000 { compatible arm,gic-v3-its; reg 0x0 0x2c100000 0x0 0x20000; /* ITS 寄存器空间 */ msi-parent gic; /* LPI 由 GIC 分发 */ #msi-cells 1; /* MSI 消息只带一个数据字段 */ };属性说明#msi-cells 1表示设备发出的 MSI 消息只有一个 32 位数据字段PCIe 标准格式若你的平台用地址低位携带 DeviceID 信息按绑定文档可写2。外设侧不用写特殊内容驱动通过of_msi_remap或标准 MSI 接口申请即可内核会自动把它挂到 ITS domain 上走 LPI。GICv3 与 ITS 节点各属性的完整定义见 arm,gic-v3.yaml。五、调优三板斧亲和性、优先级、多 ITS翻译表建好只是起点性能好不好看这三件事。中断亲和性设置/proc/irq调优命令。LPI 的亲和性最终落在 Collection Table 里所以内核改亲和性是真在改硬件表不是软件把戏# 把中断 8123 绑到 CPU0 和 CPU1掩码 0x3 echo 3 /proc/irq/8123/smp_affinity # 查看当前绑定的 CPU 列表 cat /proc/irq/8123/smp_affinity_list多队列网卡或 NVMe 场景下把各队列的中断均匀撒到各核比全挤在一颗核上跑得快得多。优先级设置。GICv3 的优先级是 8 位共 256 级0xff 最低0x00 最高通过 GICD 的 PRIORITY 寄存器调整LPI 的优先级由内核管理你更常操作的是 SPI 的优先级和抢占关系。设备树里中断单元格的第三个字段是触发方式IRQ_TYPE_*不是优先级别写混。多 ITS 实例分担。大系统里多个 ITS 实例并行工作内核按设备的 MPIDR 归属把设备分给不同 ITS天然做了分片。设备树里给每个 ITS 各写一个节点同第四节的写法、不同 reg驱动会全部探测注册翻译负载随之分摊。六、收尾关键概念对照表概念一句话定位容易混的点SPI外设直连的固定中断线路32~1023 共 1020 个全系统共享池用完就没了LPIMSI 消息经 ITS 翻译出来的中断INTID 可达 2^31不是线路是翻译产物天然支持动态路由PPI / SGI每核私有中断 / CPU 间软件中断和 MSI 路由无关走传统路径Device Table按 DeviceID 找设备翻译表基址一级入口对应 MAPD 命令ITT按 EventID 查 LPI 中断号真正的号码对照表对应 MAI 命令Collection Table按 INTID 决定 LPI 发给哪些 CPU亲和性的硬件落点对应 MOV 命令MSI domain内核里 ITS 对外的服务接口设备驱动不感知 ITS 细节只调标准 MSI 接口想继续往下读从这三个地方入手GICv3 驱动主体drivers/irqchip/irq-gic-v3.cITS 驱动全部实现约 5900 行drivers/irqchip/irq-gic-v3-its.c设备树绑定定义Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yamlITS 把中断号从稀缺的硬件资源变成了内存里的表项代价是三张表加一条命令队列的复杂度。理解了这张转接台GICv4 的虚拟 LPI、虚拟化中断直通也就有了着落点。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表