内容提要
PMU(性能监控单元)通过计数器记录CPU周期、指令数、分支预测错误等硬件事件,计数器溢出时触发PMU中断通知软件。在Armv8 Linux内核中,需先注销内置arm-pmu处理程序,再用request_irq()注册自定义处理函数,并设置IRQF_SHARED等标志。也可在固件EL3中处理,或直接用perf工具监控。
延伸解读
PMU 中断的触发机制与软件控制
PMU 计数器溢出时才会触发中断,而非每次事件递增。计数器是可读写的 32 位寄存器,软件可通过写入初值控制中断时机。例如,每次中断后将寄存器重置为最大值,可实现每次事件都触发中断;也可动态调整初值,在性能与准确性之间权衡。这种灵活性让开发者能根据需求定制监控粒度。
内核中自定义 PMU 中断处理的步骤
在 Armv8 Linux 中,内置的 arm-pmu 处理程序已占用中断。要注册自定义处理函数,需先注销内置处理程序,或修改内核源码为其添加 IRQF_SHARED 标志,使中断可共享。然后通过 request_irq() 注册,传入逻辑中断 ID 和 IRQF_PERCPU 等标志。注意逻辑中断 ID 与硬件中断 ID 的映射关系,可通过 /proc/interrupts 查看。
固件层处理 PMU 中断的适用场景
对于不想侵入操作系统的跟踪器,可在固件中处理 PMU 中断。需配置 GIC 将中断路由到最高安全级别 EL3,并在 ATF 中注册处理程序;也可重新路由到 Secure-EL1,在自有的 TEE-OS 中处理。这种方式适合安全敏感或与 OS 隔离的监控需求,但实现复杂度较高。
使用 perf 工具简化 PMU 监控
若不想自行处理中断,可直接使用 perf 工具。perf 依赖 Linux 内置的 PMU 中断处理程序,能监控多种硬件事件,无需编写内核模块。对于大多数性能分析场景,perf 提供了简单高效的途径,避免了自定义中断处理的复杂性和潜在风险。
Q&A
PMU是什么?它有什么作用?
PMU是性能监控单元(Performance Monitor Unit)的缩写,它是一组可以计数核心中任何可用事件的计数器,用于监控CPU周期、指令数、分支预测错误等硬件事件,帮助软件了解程序在硬件上的执行情况。
PMU中断什么时候触发?它的目的是什么?
PMU中断仅在PMU计数器溢出时生成。其目的是通知软件计数器将重置为零,软件不应信任结束值减去开始值的结果。
如何在Linux内核中注册自定义的PMU中断处理程序?
首先需要注销内置的arm-pmu处理程序,然后使用request_irq()注册自定义处理函数,并设置IRQF_SHARED等标志。例如:request_irq(irq_id, pmu_irq_handler, IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED, "pmi_handler", (void*)pmu_irq_handler);
为什么需要注销内置的arm-pmu处理程序?
因为通常一个中断只能有一个处理程序,而Linux已经内置了arm-pmu处理程序。为了注册自定义处理程序,必须先注销它,或者修改内置处理程序添加IRQF_SHARED标志使其可共享。
除了在内核中处理PMU中断,还有哪些方式?
还可以在固件EL3中处理PMU中断,需要配置GIC将中断路由到EL3,并在ATF中注册处理程序;或者使用perf工具,这是最简单的方式,无需自己处理中断。
perf工具与PMU有什么关系?
perf是使用PMU的最简单方式,它利用PMU监控硬件事件,并且Linux内置的PMU中断处理程序正是为perf服务的。