StarFive StarLink PMU 性能监测指南RISC-V 未核UncoreL3 缓存事件计数实战【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读本文面向在 StarFive JH8100 等 RISC-V 平台上的内核开发者与性能工程师系统讲解 Linux 内核中 StarFive StarLink Performance Monitor UnitPMU驱动的架构、sysfs 暴露接口与 perf 使用方法。StarLink PMU 位于连接多个 CPU 簇与 L3 内存系统的 StarLink 一致性片上网络CNoC中属于典型的 uncore PMU——它通过 MMIO 访问、计数 L3 缓存读写命中/缺失等全局事件而不依赖任何单一 CPU 核心。读完本文你将掌握如何查看 StarLink 事件列表、读取 PMU 的 cpumask 与 format 信息、使用perf stat进行系统级计数并理解事件 ID 编码、计数器分配、溢出中断与 CPU 热插拔迁移等底层实现细节。一、StarLink PMU 是什么StarFive StarLink Performance Monitor UnitPMU存在于 StarLink 一致性片上网络Coherent Network on ChipCNoC内部该网络将多个 CPU 簇与一个 L3 内存系统连接在一起官方内核文档。从驱动源码中的设备树匹配表看该 PMU 对应 StarFive JH8100 平台static const struct of_device_id starlink_pmu_of_match[] { { .compatible starfive,jh8100-starlink-pmu }, {} };设备树绑定文档 starfive,jh8100-starlink-pmu.yaml 给出了完整描述StarFives JH8100 StarLink PMU integrates one or more CPU cores with a shared L3 memory system. The PMU support overflow interrupt, up to 16 programmable 64bit event counters, and an independent 64bit cycle counter. StarFives JH8100 StarLink PMU is accessed via MMIO.即该 PMU 将若干个 CPU 核心与共享的 L3 内存系统集成在一起这也解释了为何它监测的都是 L3 缓存层面的事件而非单核内部事件。1.1 硬件能力概览特性说明位置StarLink CNoC 内连接 CPU 簇与 L3 内存系统访问方式仅支持 Memory Mapped I/OMMIO不支持指令访问事件计数器最多 16 个可编程 64 位事件计数器周期计数器1 个独立的 64 位 cycle counter中断支持溢出中断overflow interrupt作用域连接到同一 PMU 的所有核心共享common to the cores平台StarFive JH8100compatible starfive,jh8100-starlink-pmu由于计数器对所有共享该 PMU 的核心通用因此它天然属于 uncore 事件——任何单核视角都无法代表全局的 L3 缓存行为。1.2 内核配置要启用该驱动需要在内核配置中开启drivers/perf/Kconfigconfig STARFIVE_STARLINK_PMU depends on ARCH_STARFIVE || COMPILE_TEST depends on 64BIT bool StarFive StarLink PMU help Provide support for StarLink Performance Monitor Unit. StarLink Performance Monitor Unit integrates one or more cores with an L3 memory system. The L3 cache events are added into perf event subsystem, allowing monitoring of various L3 cache perf events.关键约束依赖ARCH_STARFIVE或COMPILE_TEST依赖64BIT——这与硬件仅支持 64 位寄存器、驱动使用writeq/readq访问寄存器一致编译单元由 drivers/perf/Makefile 中的obj-$(CONFIG_STARFIVE_STARLINK_PMU) starfive_starlink_pmu.o生成。配置开启后设备树中需按绑定文档声明节点例如摘自绑定文档示例pmu12900000 { compatible starfive,jh8100-starlink-pmu; reg 0x0 0x12900000 0x0 0x10000; interrupts 34; };compatible、reg、interrupts三个属性均为必填项。二、sysfs 接口事件、cpumask 与 format驱动注册后perf 子系统会以平台设备名starfive_starlink_pmu暴露一个 PMU 设备对应的 sysfs 路径为/sys/bus/event_source/devices/starfive_starlink_pmu/其下包含三个属性组starlink_pmu_attr_groups定义于 starfive_starlink_pmu.c。2.1 events 目录受支持的事件列表/sys/bus/event_source/devices/starfive_starlink_pmu/events/驱动通过PMU_EVENT_ATTR_ID宏将 9 个事件暴露为 sysfs 属性starfive_starlink_pmu.c事件名事件 ID源码定义含义cycles0x058STARLINK_CYCLES周期计数独立计数器read_request0x04000701读请求write_request0x03000001写请求release_request0x0003e001释放请求read_hit0x00901202读命中read_miss0x04008002读缺失write_hit0x006c0002写命中write_miss0x03000002写缺失writeback0x00000403写回sysfs 中每个事件属性文件的内容由starlink_pmu_sysfs_event_show生成格式为event0x...starfive_starlink_pmu.cstatic ssize_t starlink_pmu_sysfs_event_show(struct device *dev, struct device_attribute *attr, char *buf) { ... return sysfs_emit(buf, event0x%02llx\n, eattr-id); }例如read_hit文件内容为event0x901202实际输出按%02llx格式化为最小两位十六进制。这些 ID 正是 perf 内部传递给驱动、写入事件选择寄存器STARLINK_PMU_EVENT_SELECT的原始编码。2.2 cpumask 目录处理 PMU 事件的 CPU/sys/bus/event_source/devices/starfive_starlink_pmu/cpumask/由于 uncore 计数器对所有核心共享perf 需要指定一个代理 CPU 来处理事件。cpumask属性文件cpumask_showstarfive_starlink_pmu.c以%*pbl位图打印格式输出当前被选中的 CPU 集合通常只包含一个 CPUreturn sysfs_emit(buf, %*pbl\n, cpumask_pr_args(starlink_pmu-cpumask));该 cpumask 的维护由 CPU 热插拔回调完成CPU 上线时若 cpumask 为空则将该 CPU 加入并设置中断亲和性starlink_pmu_online_cpustarfive_starlink_pmu.cCPU 下线时通过perf_pmu_migrate_context将 PMU 事件迁移到另一个在线 CPU并把中断亲和性一并迁移过去starlink_pmu_offline_cpustarfive_starlink_pmu.c。这也意味着当你在 perf 命令中省略 CPU 指定时事件会被绑定到 cpumask 中的这个 CPU 上执行见下文starlink_pmu_event_init。2.3 format 目录config 字段格式/sys/bus/event_source/devices/starfive_starlink_pmu/format/format 属性组描述了事件配置寄存器config的位域格式starfive_starlink_pmu.cstatic struct attribute *starlink_pmu_format_attrs[] { STARLINK_FORMAT_ATTR(event, config:0-31), NULL };即事件 ID 占用 config 字段的 bit 0–31共 32 位。这解释了为何上表事件 ID 都是 32 位以内的数值。使用 perf 时可以直接用event0x...指定任意合法 ID而不仅限于 sysfs events 中预置的 9 个。三、perf 使用示例3.1 查看事件列表$ perf list输出中可看到以下 Kernel PMU 事件starfive_starlink_pmu/cycles/ [Kernel PMU event] starfive_starlink_pmu/read_hit/ [Kernel PMU event] starfive_starlink_pmu/read_miss/ [Kernel PMU event] starfive_starlink_pmu/read_request/ [Kernel PMU event] starfive_starlink_pmu/release_request/ [Kernel PMU event] starfive_starlink_pmu/write_hit/ [Kernel PMU event] starfive_starlink_pmu/write_miss/ [Kernel PMU event] starfive_starlink_pmu/write_request/ [Kernel PMU event] starfive_starlink_pmu/writeback/ [Kernel PMU event]这些事件名与starlink_pmu_event_attrs中注册的属性一一对应starfive_starlink_pmu.c。3.2 系统级计数$ perf stat -a -e /starfive_starlink_pmu/cycles/ sleep 1该命令在系统范围-a内对 StarLink PMU 的cycles事件计数 1 秒。也可以同时监测多个事件例如$ perf stat -a -e /starfive_starlink_pmu/read_hit/,/starfive_starlink_pmu/read_miss/ sleep 13.3 使用原始事件 ID由于 format 定义了config:0-31还可以跳过 sysfs 命名事件直接用原始编码$ perf stat -a -e /starfive_starlink_pmu/event0x901202/ sleep 1这与read_hit是等效的read_hit的事件 ID 即0x00901202。3.4 使用限制必须了解从文档与驱动双重确认StarLink PMU 存在两项硬性限制不支持采样Samplingperf record不可用。驱动在starlink_pmu_event_init中直接拒绝带采样周期的事件starfive_starlink_pmu.c/* * Sampling is not supported, as counters are shared * by all CPU. */ if (hwc-sample_period) return -EOPNOTSUPP;不支持绑定任务per-task只能做系统级计数。驱动同样在starlink_pmu_event_init中拒绝event-cpu 0未指定 CPU或带有PERF_ATTACH_TASK标志的事件starfive_starlink_pmu.c/* * Per-task and attach to a task are not supported, * as uncore events are not specific to any CPU. */ if (event-cpu 0 || event-attach_state PERF_ATTACH_TASK) return -EOPNOTSUPP;其根因正如注释所写计数器为所有 CPU 共享事件不属于任何特定 CPU 或任务。因此使用时必须像上文示例那样加-a或显式-C cpu否则事件初始化会失败。四、源码级原理解析4.1 寄存器布局驱动定义的核心寄存器偏移starfive_starlink_pmu.c寄存器偏移作用STARLINK_PMU_CONTROL0x040全局控制bit 0 为全局使能STARLINK_PMU_GLOBAL_ENABLESTARLINK_PMU_COUNTER_OVERFLOW_STATUS0x048计数器溢出状态STARLINK_PMU_INTERRUPT_ENABLE0x050计数器溢出中断使能STARLINK_PMU_CYCLE_COUNTER0x058独立周期计数器64 位STARLINK_PMU_EVENT_SELECT0x060事件选择寄存器每个计数器占 8 字节STARLINK_PMU_EVENT_COUNTER0x160事件计数器阵列每个计数器占 8 字节关键常量#define STARLINK_PMU_MAX_COUNTERS 64 #define STARLINK_PMU_NUM_COUNTERS 16 #define STARLINK_PMU_IDX_CYCLE_COUNTER 63 #define STARLINK_PMU_CYCLE_OVERFLOW_MASK BIT_ULL(63)4.2 计数器索引与中断位映射驱动为事件分配索引starlink_pmu_addstarfive_starlink_pmu.ccycles事件固定使用索引63STARLINK_PMU_IDX_CYCLE_COUNTER因为它有专用寄存器不占用 16 个可编程计数器其他事件通过find_first_zero_bit从 16 个计数器used_mask中分配空闲索引计数器用完则拒绝新增事件。中断使能/溢出状态寄存器中每一位与计数器的映射关系代码注释原文event counter 0 - Bit [0] event counter 1 - Bit [1] ... cycle counter - Bit [63]即中断寄存器 bit 0–15 对应 16 个事件计数器bit 63 对应周期计数器。这也是为什么STARLINK_PMU_MAX_COUNTERS取 64、STARLINK_PMU_CYCLE_OVERFLOW_MASK是BIT_ULL(63)。4.3 启动/停止与周期编程计数器启动流程starlink_pmu_counter_startstarfive_starlink_pmu.c读回中断使能寄存器若为cycles事件仅置位 cycle 溢出中断位bit 63周期计数器在GLOBAL_ENABLE置位后立即开始计数否则把事件 ID 写入事件选择寄存器EVENT_SELECT idx * 8并置位对应计数器的溢出中断位最后写入STARLINK_PMU_GLOBAL_ENABLEbit 0到控制寄存器全局启动计数。停止流程starlink_pmu_counter_stopstarfive_starlink_pmu.c则反向操作先清GLOBAL_ENABLE再清除对应中断使能位。值得注意的细节是starlink_pmu_set_event_periodstarfive_starlink_pmu.c计数器初始值被编程为64 位最大值的一半STARLINK_PMU_COUNTER_MASK 1注释说明这是为了处理极端中断延迟extreme interrupt latency场景——计数从半程开始即使中断响应有较大延迟也不容易漏计溢出。每次中断处理后starlink_pmu_handle_irq都会重新写入该半程初值。4.4 读取与差值计算starlink_pmu_updatestarfive_starlink_pmu.c使用local64_cmpxchg进行无锁的读-改-写循环读取当前计数器原始值并与上次记录值求差按 64 位掩码取模累加到 perf 事件计数中。这与标准的 perf uncore 驱动模式一致保证并发中断/读取场景下计数不丢失。4.5 溢出中断处理中断处理函数starlink_pmu_handle_irqstarfive_starlink_pmu.c遍历 64 个计数器槽位跳过未使用的槽位读取COUNTER_OVERFLOW_STATUS检查当前索引对应位若溢出写回该位以清中断调用starlink_pmu_update累加计数再调用starlink_pmu_set_event_period重新装载半程初值。中断通过starlink_setup_irqs从设备树interrupts属性获取platform_get_irq(pdev, 0)并注册starfive_starlink_pmu.c。4.6 电源管理CPU_PM 通知驱动在CONFIG_CPU_PM使能时注册电源管理通知器starlink_pmu_pm_notifystarfive_starlink_pmu.cCPU_PM_ENTER停止并更新所有在用计数器CPU_PM_EXIT/CPU_PM_ENTER_FAILED恢复并重新启动计数器。这确保 CPU 进入低功耗状态时 PMU 计数不会丢失退出后能无缝恢复。4.7 事件分组校验starlink_pmu_validate_event_groupstarfive_starlink_pmu.c保证同组硬件事件都在 StarLink PMU 上软件事件除外且组内事件总数不超过 16 个可编程计数器。若超限starlink_pmu_event_init返回-EINVALperf 会尝试拆分事件组。五、与其他文档与资源的关联如果你想进一步了解 StarLink 的 L3 缓存硬件本身可以参考设备树缓存绑定文档 starfive,jh8100-starlink-cache.yaml其 compatible 为starfive,jh8100-starlink-cache基址位于0x15000000与 PMU 的0x12900000不同。而本 PMU 驱动的完整实现集中在 drivers/perf/starfive_starlink_pmu.c主线 perf 子系统的通用机制可参考 include/linux/perf_event.h 与 kernel/events 目录下的核心代码。六、小结StarFive StarLink PMU 是一个典型的 uncore PMU通过 MMIO 访问、共享于所有核心、支持溢出中断、拥有 16 个 64 位可编程事件计数器与 1 个独立的 64 位周期计数器。在软件层面sysfs 三件套events/9 个预置 L3 缓存事件、cpumask/代理 CPU、format/config:0-31perf 用法perf list查看事件perf stat -a -e /starfive_starlink_pmu/event/做系统级计数也可用event0x...指定原始 ID两大限制不支持采样不能用perf record不支持 per-task必须系统级计数底层机制事件 ID 写入事件选择寄存器、计数器索引与中断位一一对应、半程初值装载抗中断延迟、CPU 热插拔时自动迁移中断与事件上下文、CPU_PM 电源状态切换时保存恢复计数。掌握这些内容后你就可以在 JH8100 平台上对 L3 缓存行为读/写命中率、缺失率、写回频率等进行可靠的系统级性能观测为缓存调优、内存带宽分析与应用性能评估提供数据支撑。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
