Skip to content

feat(starry): ARM PMUv3 hardware-PMU perf support (perf stat / record / report)#1395

Merged
ZR233 merged 14 commits into
rcore-os:devfrom
oscomp-posad:feat/perf-pmuv3-hw
Jun 29, 2026
Merged

feat(starry): ARM PMUv3 hardware-PMU perf support (perf stat / record / report)#1395
ZR233 merged 14 commits into
rcore-os:devfrom
oscomp-posad:feat/perf-pmuv3-hw

Conversation

@JosephJoshua

@JosephJoshua JosephJoshua commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

StarryOS 已实现 perf_event_open(2),但仅覆盖软件 / 追踪事件(kprobe / uprobe / tracepoint / eBPF software);硬件 PMU 路径完全缺失:PERF_TYPE_HARDWARE/HW_CACHE/RAWread(perf_fd)、采样 + mmap 环形缓冲、rdpmc 均返回 Unsupported。本 PR 补齐硬件 PMU 路径,使真实上游 perf 工具(stat / record / report)能在 ARMv8 PMUv3(如 RK3588)上运行。改动纯增量(39 文件,+8009 / −29),原追踪 perf 路径不受影响、无回归。

实现内容

硬件寄存器层components/axcpu/src/aarch64/pmu.rs,新增)
ARM PMUv3 完整封装:PMCR / PMCCNTR / PMEVCNTRn / PMEVTYPERn / PMCNTENSET·CLR / PMINTENSET·CLR / PMOVSCLR / PMCEID / PMUSERENR / MIDR —— 覆盖计数、采样溢出、EL0 直读所需全部原语。

perf stat(计数)
PERF_TYPE_HARDWARE(cycles 走专用周期计数器,instructions / cache / branch 走可编程计数器)+ PERF_TYPE_RAW;多计数器并行;read_format(value / time_enabled / time_running / id)。

perf record(采样)
PMUv3 溢出 IRQ(PPI 7 / INTID 23,每-CPU 寄存器表)→ 按 sample_type 写多字段 PERF_RECORD_SAMPLE 进 mmap 环;IRQ 安全的环写入 + 严格拆除顺序避免 UAF。

PMU 枚举(sysfs / procfs)
/sys/bus/event_source/devices/armv8_pmuv3_0/{type,cpus,format,events}/proc/sys/kernel/perf_event_*、MIDR 解码的 /proc/cpuinfo —— 真实 perf 据此发现并打开 PMU。

per-task(pid > 0
事件随被监控线程上下文切换布防 / 撤防(复用既有 TaskExt 调度钩子,不改 axtask);enable_on_exec;per-task 采样。

真实 perf record 端到端
PERF_EVENT_IOC_ID + PERF_EVENT_IOC_SET_OUTPUTperf_event_mmap_page.version=1;cpuid sysfs 节点。

常用能力
频率模式(-F,Linux perf_adjust_period 自适应);多事件共享环(-e a,b,SET_OUTPUT 重定向 + per-event id 区分);rdpmc / EL0 直读(PMUSERENR + mmap_page index / pmc_width / cap_user_rdpmc)。

side-band 记录(perf report 符号化)
PERF_RECORD_COMM + MMAP2(exec 镜像 / 动态库真实路径);PERF_RECORD_FORK + EXIT(进程树)。

事件继承(attr.inherit
被监控任务 fork 子任务时事件随之克隆、写入同一环 —— perf record 默认的"跟随子进程"。

设计要点

  • 路由规则pid > 0 → per-task;pid ≤ 0(self / -a)→ 系统级。硬件类型判断置于原追踪 perf 调度之前,完全保留原路径,无回归
  • per-task 状态挂在 Thread.perf_counters,由既有调度钩子驱动,不触碰 axtask。
  • ABI 结构体复用 kbpf-basic 0.6。

测试

12 个自包含 QEMU 用例(不依赖 perf 二进制,CI 可跑,全部 1/1 通过):
perf-hw-{cycles, stat, sample, pmu-sysfs, sample-task, record-ioctl, freq, rdpmc, ring-merge, sideband, fork-exit, inherit}

真实上游 perf 6.6.0(QEMU):perf stat 命名事件(经 sysfs 枚举)、perf record 采集 724 样本。

真实硬件(OrangePi-5-Plus / RK3588,单核):perf stat真实 PMU 值 —— 32,354,872 cycles、97,608,453 instructions、cycles + instructions 同时计数 IPC 0.89。

clippy(starry-kernel + ax-cpu)45/45、nightly fmt、aarch64 build、riscv64 交叉编译(cfg 门控)全部通过。

范围与限制

  • 仅 aarch64 / ARM PMUv3;其它架构经 #[cfg] 门控,不受影响。
  • 单核;多核(每-CPU 资源)+ big.LITTLE 异构 PMU 为后续工作。
  • attr.inherit 每个被监控任务占一个硬件可编程计数器槽(暂不时分复用);后续工作。
  • perf record 的 mmap 修复已在 QEMU 验证,硬件上尚未在修复后复测。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 审核总结

变更概述

本 PR 为 StarryOS 补齐 ARM PMUv3 硬件 PMU perf 路径,使上游 perf 工具(stat / record / report)能在 aarch64 上运行。改动纯增量(39 文件,+8085/−29),原追踪 perf 路径不受影响。

实现逻辑

实现架构分层清晰:

  1. 硬件寄存器层axcpu/src/aarch64/pmu.rs):ARM PMUv3 完整封装,包含 PMCR/PMCCNTR/PMEVCNTRn/PMEVTYPERn 等全部原语,使用命名系统寄存器直接访问(不走 PMSELR 间接寻址),避免 IRQ 处理器竞争。
  2. hw.rs:counting(M1, perf stat)和 sampling(M2, perf record)事件,计数器分配器(HwAlloc)跟踪专用周期计数器与可编程计数器的使用状态。
  3. sampling.rs:PMU 溢出 IRQ 处理器,每 CPU 注册表 [Option<SampleSlot>; 32]NoPreemptIrqSave 下读写,频率模式自适应控制(next_freq_period)使用 1/8 阻尼。ring_write 在写入 data_head 前使用 Release 屏障。
  4. task.rs:per-task 事件通过 PerTaskCounter 挂载在 Thread.perf_counters,由 perf_sched_in/perf_sched_out 调度钩子驱动,热路径仅依赖原子操作和 sysreg 写入。
  5. sideband.rsPERF_RECORD_COMM/MMAP2/FORK/EXIT 从进程上下文写入环,通过 ring_write_process(mask 本地 IRQ)与溢出处理序列化。
  6. sysfs/procfs:PMU 设备枚举(/sys/bus/event_source/devices/armv8_pmuv3_0/)、MIDR 解码的 /proc/cpuinfo、perf knobs。

安全性分析

  • IRQ 上下文纪律:溢出处理器不分配内存,不持锁,先读取中断上下文(ELR_EL1/SPSR_EL1),符合硬中断要求。
  • 拆除顺序:mask IRQ → stop counter → unregister slot → drop Arc,防止 UAF。Drop 实现与 disable 共享 teardown_sampling_irq(幂等)。
  • 原始指针音效性SampleSlot::notify*const IrqNotify,仅在注册的 slot 存活期间被解引用(unregisterArc<IrqNotify> drop 之前执行),模块级文档明确论证了这一点。
  • RAII 页面固定:ring 页面通过 Arc<GlobalPage> 固定在 VMA retainer 中,Weak 避免事件持有强引用导致的生命周期延长。
  • [patch.crates-io]:未引入任何 crates.io patch。

测试覆盖

12 个自包含 QEMU C 用例位于 test-suit/starryos/qemu-smp1/system/perf-hw-*/,覆盖:

  • 计数(cycles、stat)、采样(sample、sample-task)、PMU sysfs 枚举
  • ioctl 行为(record-ioctl)、频率模式(freq)、EL0 直读(rdpmc)
  • 多事件环合并(ring-merge)、side-band 记录(sideband)
  • fork/exit 生命周期(fork-exit)、事件继承(inherit)

测试不依赖 perf 二进制,可独立运行,打印 STARRY_PERF_HW_OK 成功哨兵。用例放置在正确的 test-suit 路径下。

CI 状态

CI 检查全部为 skipped(来自 fork PR 的典型行为,非 PR 引起的失败)。cargo fmt --check 本地通过。作者报告 clippy 45/45、aarch64 build、riscv64 交叉编译、nightly fmt 全部通过。

重复/重叠分析

检查了当前所有 open PR,无其他 PR 涉及 PMU/硬件 perf 功能。base 分支现有 perf 仅覆盖软件/追踪事件,本 PR 补齐硬件路径,纯增量无冲突。

已知限制(非 blocking)

  • 仅单核;多核 + big.LITTLE 异构 PMU 为后续工作
  • attr.inherit 每任务占一个可编程计数器槽(暂不时分复用)
  • 仅 aarch64;其他架构通过 #[cfg] 门控不受影响

结论

实现质量高、文档详尽、安全论证完整、测试覆盖全面。无阻塞性问题。

Powered by mimo-v2.5-pro

@mai-team-app
mai-team-app Bot requested review from ZCShou and luodeb June 26, 2026 17:22

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 审核总结

变更概述

本 PR 为 StarryOS 补齐 ARM PMUv3 硬件 PMU perf 路径,使上游 perf 工具(stat / record / report)能在 aarch64 上运行。改动纯增量(39 文件,+8093/−29),原追踪 perf 路径不受影响。

实现逻辑

实现架构分层清晰,各模块职责明确:

  1. 硬件寄存器层axcpu/src/aarch64/pmu.rs,621 行新增):ARM PMUv3 完整封装——PMCR/PMCCNTR/PMEVCNTRn/PMEVTYPERn/PMCNTENSET·CLR/PMINTENSET·CLR/PMOVSCLR/PMCEID/PMUSERENR/MIDR。使用命名系统寄存器直接访问(mrs/msr),避免 PMSELR 间接寻址的竞态,设计合理。

  2. hw.rs(1195 行):counting(perf stat)和 sampling(perf record)事件的统一入口。HwAlloc 计数器分配器跟踪专用周期计数器与可编程计数器的使用状态。RingState 使用 Weak<GlobalPage> 避免事件持有强引用导致页面生命周期过长。

  3. sampling.rs(725 行):PMU 溢出 IRQ 处理器。每 CPU 固定 [Option<SampleSlot>; 32]NoPreemptIrqSave 下读写。频率模式自适应控制(next_freq_period)使用 1/8 阻尼,与 Linux perf_adjust_period 一致。ring_write 在写入 data_head 前使用 Release 屏障,保证用户态观察到新 data_head 时也观察到记录内容。

  4. task.rs(1300+ 行):per-task 事件通过 PerTaskCounter 挂载在 Thread.perf_counters,由既有 perf_sched_in/perf_sched_out 调度钩子驱动。热路径仅依赖原子操作和 sysreg 写入,PERF_TASK_ACTIVE 计数器为 0 时 early-return,空闲系统开销仅为一次 relaxed 原子读。

  5. sideband.rsPERF_RECORD_COMM/MMAP2/FORK/EXIT 记录从进程上下文写入环,通过 ring_write_process(mask 本地 IRQ)与溢出处理序列化。

  6. sysfs/procfs:PMU 设备枚举(/sys/bus/event_source/devices/armv8_pmuv3_0/)、MIDR 解码的 /proc/cpuinfoperf_event_* knobs。真实 perf 工具据此发现并打开 PMU。

安全性分析

  • IRQ 上下文纪律:溢出处理器不分配内存、不持锁,先读取中断上下文(ELR_EL1/SPSR_EL1)再操作 PMU,符合硬中断要求。
  • 拆除顺序disable counter → disable_irqunregister slot → drop Arc,严格保证 IRQ 处理器不会访问已释放资源。Drop 实现与 disable 共享 teardown_sampling_irq(幂等)。
  • 原始指针有效性SampleSlot::notify*const IrqNotify,仅在注册的 slot 存活期间被解引用(unregisterArc<IrqNotify> drop 之前执行),模块级文档明确论证了这一点。
  • RAII 页面固定:ring 页面通过 Arc<GlobalPage> 固定在 VMA retainer 中,Weak 避免事件持有强引用导致生命周期延长。
  • [patch.crates-io]:未引入任何 crates.io patch,ABI 结构体复用 kbpf-basic 0.6。

测试覆盖

12 个自包含 QEMU C 用例位于 test-suit/starryos/qemu-smp1/system/perf-hw-*/

  • 计数(cycles、stat)、采样(sample、sample-task)
  • PMU sysfs 枚举(pmu-sysfs)
  • ioctl 行为(record-ioctl)、频率模式(freq)、EL0 直读(rdpmc)
  • 多事件环合并(ring-merge)、side-band 记录(sideband)
  • fork/exit 生命周期(fork-exit)、事件继承(inherit)

测试不依赖 perf 二进制,可独立运行。PR 作者还报告了真实上游 perf 6.6.0 的 QEMU 端到端验证和 OrangePi-5-Plus/RK3588 硬件验证结果。

CI 状态

  • formatting: ✅ 通过
  • clippy: ✅ 通过
  • starry aarch64/x86_64/riscv64/loongarch64 qemu: ✅ 全部通过
  • arceos aarch64/x86_64/riscv64/loongarch64 qemu: ✅ 全部通过
  • axvisor aarch64/riscv64/loongarch64 qemu + x86_64 self-hosted: ✅ 全部通过
  • board tests (orangepi-5-plus, visionfive2, roc-rk3568-pc, phytiumpi): ✅ 全部通过
  • 唯一失败: Test starry self-hosted board licheerv-nano-sg2002 / run_host — 板端网络 PHY 自协商超时(U-Boot DHCP 阶段未进入内核),已有跟踪 issue #1382,与本 PR 无关(本 PR 仅触及 aarch64 PMUv3 代码)。

重复/重叠分析

检查了当前所有 open PR(#1394, #1390, #1388, #1380, #1379, #1368 等),无其他 PR 涉及 PMU/硬件 perf 功能。base 分支现有 perf 仅覆盖软件/追踪事件,本 PR 补齐硬件路径,纯增量无冲突。

已有 review 考虑

mai-team-app[bot] 在旧 head(d11d084d8)提交了 APPROVE review。当前 head(f43949f4c)在该 review 之后又有两次 fix commit(修正 cross-arch grouped build 和 side-band 测试 sample period),改善了测试的跨架构兼容性和稳定性。

已知限制(非 blocking)

  • 仅单核;多核 + big.LITTLE 异构 PMU 为后续工作
  • attr.inherit 每任务占一个可编程计数器槽(暂不时分复用)
  • 仅 aarch64;其他架构通过 #[cfg] 门控不受影响
  • PMU IRQ 硬编码为 PPI 7/INTID 23(代码注释标注后续应从 FDT 读取)

结论

实现质量高、文档详尽、安全论证完整、测试覆盖全面。无阻塞性问题。

Powered by mimo-v2.5-pro

@ZR233 ZR233 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本次复审基于 head f43949f4c576018f469d871a9df2be8b031ed190

本地验证:

  • cargo fmt --check 通过
  • cargo xtask clippy --package ax-cpu 28 项目标/feature 组合全部通过
  • cargo xtask clippy --package starry-kernel 17 项 feature 组合全部通过
  • git diff --check origin/dev...HEAD 通过

GitHub 当前检查也已到可合入状态,format/clippy/std、Starry/ArceOS/Axvisor QEMU 与 board 检查均为通过或预期跳过,mergeStateStatus=CLEAN

我重点看了 PMUv3 sysreg 层、sampling ring 写入、PERF_EVENT_IOC_ID/SET_OUTPUT、per-task sched in/out、exec/clone/exit side-band 与新增 test-suit 用例。实现整体分层清楚,ring lifetime 通过 VMA retainer/anchor 固定,IRQ teardown 顺序也避免了 notify/ring UAF;新增 12 个 qemu-smp1/system/perf-hw-* 用例覆盖 counting、sampling、sysfs dynamic PMU type、freq、rdpmc、SET_OUTPUT/ring merge、side-band、fork/exit、inherit 等关键路径。

非阻塞建议:PR 描述里提到 PERF_TYPE_HW_CACHE,但当前实现实际支持的是 PERF_TYPE_HARDWAREPERF_TYPE_RAW 和 sysfs 动态 armv8_pmuv3_0 type;HW_CACHE / BREAKPOINThw.rs 里仍明确返回 unsupported。常用命名事件通过 sysfs 动态 PMU type 暴露已经可以覆盖 cache_misses/cache_references 这类入口,但建议把 PR body 或后续文档里的范围表述收窄,避免给维护者留下 PERF_TYPE_HW_CACHE 静态 ABI 已支持的误解。

未发现阻塞问题,批准合入。

@ZR233
ZR233 merged commit b600bd0 into rcore-os:dev Jun 29, 2026
107 of 108 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 29, 2026
luodeb pushed a commit that referenced this pull request Jun 30, 2026
… / report) (#1395)

* feat(starry): add PERF_TYPE_HARDWARE cpu-cycles via ARM PMUv3 (perf M0)

* feat(starry): perf stat counting via PMUv3 programmable counters (perf M1)

* feat(starry): perf record sampling via PMUv3 overflow IRQ (perf M2)

* feat(starry): expose armv8_pmuv3 PMU via sysfs/procfs for perf (perf M2.5)

* feat(starry): per-task perf counting via enable_on_exec + ctx-switch follow (perf M3-pt)

* feat(starry): per-task perf-record sampling + multi-field PERF_RECORD_SAMPLE (perf M3-pt-rec)

* fix(starry): perf_event_mmap_page version=1 + cpuid sysfs for real perf

* feat(starry): real perf record via PERF_EVENT_IOC_ID + SET_OUTPUT (perf M3-rec-e2e)

* feat(starry): perf frequency mode + multi-event ring-merge + rdpmc

* feat(starry): perf side-band COMM + MMAP2 records for perf report symbolization

* feat(starry): perf side-band FORK + EXIT task-lifetime records (attr.task)

* feat(starry): perf attr.inherit — follow forked children into one ring

* fix(starry): skip perf-hw C tests on non-aarch64 (cross-arch grouped build)

* fix(starry): widen perf-hw side-band test sample period to prevent ring wrap
This was referenced Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants