SMP 关联路由不适用于 ARM 上的 GICv2

SMP affinity routing doesn't work with GICv2 on ARM

我的 Raspberry Pi 上有 4 个 CPU 内核和一个以太网卡。
我需要将来自 NIC 的中断路由到所有 4 CPU 个内核。
我将 /proc/irq/24/smp_affinity 设置为 0xF (1111),但这没有用。
/proc/interrupts 的第六列中,我没有看到 IO-APIC (绝对支持*亲和路由)但是 GICv2 代替。仍然找不到关于 GICv2 和 smp_affinity.

的任何有用信息

GICv2 是否支持 SMP 关联路由?

*更新:
来自 that post

The only reason to look at this value is that SMP affinity will only work for IO-APIC enabled device drivers.

TL;DR - /proc/irq/24/smp_affinity 的存在表明您的 Linux SMP 系统支持关联。文本 IO-APIC 是中断控制器的类型(典型的 PC),它确实 NOT 表示系统可以处理关联。在 ARM 系统上,GIC 通常是中断控制器,尽管一些中断可以路由到 'sub-controller'.


至少主线是supporting some affinities as per Kconfig。但是,我不确定您要做什么。中断只能 运行 在一个 CPU 上,因为只有一个 CPU 可以从 NIC 中取出数据。如果一个特定的 CPU 是 运行ning 网络代码而其余的用于其他目的,则亲和力有意义。

该核心上的数据可能不会在缓存中,因为 NIC 缓冲区可能是 DMA 且不可缓存。所以,我不太确定你会实现什么,或者你会如何期望在所有四个 CPU 上中断到 运行?如果您有四个 NIC 接口,则可以将每个接口挂接到一个 CPU。这可能对功耗问题有好处。

具体来说,对于四个 CPU 的情况,0xf 的关联掩码将禁用任何关联,这是默认情况。您可以 cat /proc/irq/24/smp_affinity 查看亲和力设置。此外,此文件的存在表明您的 Linux SMP 系统支持关联性。文本 IO-APIC 是中断控制器的类型(典型的 PC),它 NOT 表示系统可以处理关联。

另请参阅:


注意这部分是推测性的,不是我所知道的任何卡片的工作方式。

你想要的主要部分一般是不可能的。 NIC 寄存器是单一资源。有多个寄存器,它们具有读取和写入寄存器以执行操作的一般顺序。如果两个CPU同时在写入(甚至读取)寄存器,那么它会严重混淆网卡。通常 CPU 与中断无关,只有一些 DMA 引擎需要被告知中断中的下一个缓冲区。

为了实现您想要的有用功能,您需要一个带有多个寄存器 'banks' 且可以独立使用的网卡。例如,仅 READ/WRITE 个数据包库很容易理解。然而,可能有几家银行写入不同的数据包,然后卡必须管理如何序列化它们。此外,该卡可以进行一些数据包检查并根据固定数据包值中断不同的 CPUs。即,端口和IP。这种数据包匹配会产生不同的中断源,不同的 CPU 可以处理不同的匹配。

这将允许您使用单个 NIC 将不同的套接字流量路由到特定的 CPU。

问题是与现有卡相比,在硬件上制作这张卡会非常复杂。它会更昂贵并且需要更多的电力来运行。

如果是标准的网卡硬件,如果原来的CPU不忙,旋转CPUs是没有增益的。如果存在非网络 activity,最好单独保留其他 CPU,以便缓存可用于不同的工作负载 (code/data)。所以在大多数情况下,最好只将中断保持在固定的 CPU 上,除非它很忙,然后它可能会在几个 CPU 之间来回切换。 运行 所有 CPU 的中断几乎永远不会有益。

我不相信 GICv2 支持 IRQ 平衡。中断将始终由相同的 CPU 处理。至少当我最后查看 5.1 内核时就是这种情况。当时的讨论是不支持这个,因为这不是一个好主意。

你会看到中断总是由 CPU 0 处理。使用类似 ftrace 或 LTTng 的东西来观察 CPU 正在做什么。

我认为通过关联设置,您可以通过将该位设置为零来防止 运行ning 在 CPU 上的中断。但这并不能平衡允许它的所有 CPUs 的 IRQ。它仍将始终转到相同的 CPU。但是你可以让这个 CPU 1 而不是 0.

所以您可以做的是在不同的 CPU 上设置某些中断。这将允许诸如 SDIO 和网络之类的东西在它们的中断处理程序中不与 CPU 0 争夺 CPU 时间。也可以设置用户空间进程的关联性,使其不会 运行 在处理中断的同一个 CPU 上,从而减少用户空间进程被中断的时间。

那我们为什么不做 IRQ 平衡呢?它最终没有用。

请记住,这里的中断处理程序只是 "hard" IRQ 处理程序。这通常不会做很多工作。它通过硬件确认中断,然后触发后端处理程序,如工作队列、IRQ 线程、软中断或 tasklet。这些在 IRQ 上下文中不 运行,并且可以并且将根据当前工作负载安排到不同的 CPU 或 CPU。

因此,即使网络中断总是路由到同一个 CPU,网络堆栈也是多线程的,并且 运行 在所有 CPU 上。它的主要工作不是在一个 CPU 上 运行 的硬 IRQ 处理程序中完成的。同样,使用 ftrace 或 LTTng 来查看。

如果硬 IRQ 做的很少,最重要的是减少延迟,最好通过 运行ning 在相同的 CPU 上完成,以提高缓存效率。将其分散可能会导致延迟和处理 IRQ 的总成本更糟。

硬 IRQ 处理程序一次只能 运行 一个实例。所以即使它是平衡的,它也可以在任何时候只使用一个CPU。如果不是这种情况,则几乎不可能在没有竞争条件的情况下编写处理程序。如果你想同时使用多个 CPUs,那么不要在硬 IRQ 处理程序中完成工作,在像工作队列这样的结构中完成。这就是网络堆栈的工作原理。和块设备层。

IRQ 不平衡,因为它通常不是答案。答案是不要在 IRQ 上下文中进行工作。