news 2026/9/10 4:11:59

Linux 内核 HiSilicon SoC Uncore PMU 实战指南:L3C/HHA/DDRC 的 perf 事件采集与过滤配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 内核 HiSilicon SoC Uncore PMU 实战指南:L3C/HHA/DDRC 的 perf 事件采集与过滤配置

Linux 内核 HiSilicon SoC Uncore PMU 实战指南:L3C/HHA/DDRC 的 perf 事件采集与过滤配置

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

HiSilicon SoC 内部的 L3 缓存(L3C)、Hydra Home Agent(HHA)与 DDR 控制器(DDRC)等系统级设备各自内置独立的 uncore 性能监控单元(PMU)。本文基于内核文档 Documentation/admin-guide/perf/hisi-pmu.rst 与驱动源码 drivers/perf/hisilicon/,完整讲解 HiSilicon uncore PMU 的 SoC 拓扑、sysfs 事件发现机制、perf list/perf stat的使用方法,以及 PMU v2(identifier0x30)与 v3(identifier0x40)新增的tt_corett_reqdatasrc_cfgextsrcid/tgtid等过滤参数,帮助你在 HiSilicon 平台上对 NoC、缓存与内存子系统做精细的性能剖析。

HiSilicon SoC 拓扑:SCCL、CCL 与 uncore 设备

理解 uncore PMU 之前,先要理解 HiSilicon SoC 的层次化封装结构。根据官方文档的描述:

  • HiSilicon SoC 芯片集成了多种相互独立的系统设备 PMU,例如 L3 缓存(L3C)、Hydra Home Agent(HHA)和 DDRC。这些 PMU 彼此独立,各自拥有硬件逻辑来采集统计与性能信息;
  • SoC 封装了多个 CPU die 与 IO die。每个 CPU 簇(CPU Cluster,CCL)由 4 个 CPU 核心组成,共享一片 L3 缓存;
  • 每个 CPU die 被称为 Super CPU Cluster(SCCL),由 6 个 CCL 构成;
  • 每个 SCCL 配备 2 个 HHA(编号 0–1)和 4 个 DDRC(编号 0–3)。

PMU v2 之后的 SoC 进一步封装了 I/O die:I/O die 被称为 Super I/O Cluster(SICL),包含多个 I/O Cluster(ICL)。SoC 中每个 CCL/ICL 都有唯一的 11 位 ID,其中高 6 位是 SCCL-ID,低 5 位是 CCL/ICL-ID。文档列出了 I/O die 上各 ICL 类型的编码:

低 5 位编码ICL 类型
5'b00000I/O_MGMT_ICL
5'b00001Network_ICL
5'b00011HAC_ICL
5'b10000PCIe_ICL

这套拓扑在驱动中由struct hisi_pmu_topology表达,见 hisi_uncore_pmu.h:其中sccl_id/sicl_id/scl_id三者共用一个 union(SCCL 与 SICL 是平行的,一个 PMU 不可能同时位于两者之上),ccl_id表示 CPU 簇,index_id表示同位置多个同类 PMU 的模块编号,sub_id则是 PMU 的子模块编号——文档注释里明确举例:DDRC PMU v2 因为每个 DDRC 内含多个 DMC 而使用了sub_id。任何无法定位的拓扑字段取值为-1

拓扑 ID 的来源在 hisi_uncore_pmu.c 的hisi_uncore_pmu_init_topology():驱动从设备固件属性hisilicon,scl-idhisilicon,ccl-idhisilicon,idx-idhisilicon,sub-id中读取。而对于 CPU 侧,hisi_read_sccl_and_ccl_id()(hisi_uncore_pmu.c)则从MPIDR_EL1的 affinity 层级解析出 SCCL/CCL ID,并按 CPU 型号区分三种编码:

  • TSV110 的 MT 版本:SCCL 取Aff2[7:3],CCL 取Aff2[2:0]
  • 其他 MT 部件:SCCL 取Aff3[7:0],CCL 取Aff2[7:0]
  • 非 MT 部件:SCCL 取Aff2[7:0],CCL 取Aff1[7:0]

驱动构建与 sysfs 事件发现

编译依赖

uncore PMU 驱动族的构建开关在 drivers/perf/hisilicon/Kconfig:HISI_PMU为 tristate 选项,依赖ARM64 && ACPI,即该套驱动仅面向 ARM64 且使用 ACPI 的 HiSilicon 系统。Makefile 显示CONFIG_HISI_PMU会编译 9 个目标文件:hisi_uncore_pmu.o(公共框架)以及hisi_uncore_l3c_pmu.ohisi_uncore_hha_pmu.ohisi_uncore_ddrc_pmu.ohisi_uncore_sllc_pmu.ohisi_uncore_pa_pmu.ohisi_uncore_cpa_pmu.ohisi_uncore_uc_pmu.ohisi_uncore_noc_pmu.ohisi_uncore_mn_pmu.o等具体设备 PMU。此外还有独立的HISI_PCIE_PMUHNS3_PMU选项,分别面向 PCIe 与 HNS3 网卡的 RCiEP 设备,与本文的 uncore PMU 主题无关。

每个模块注册为独立 PMU

文档指出:每个 L3C、HHA、DDRC 都会以独立的 PMU 身份向 perf 注册,PMU 名称在事件列表中形如hisi_sccl<sccl-id>_module<index-id>,其中sccl-id是 SCCL 标识,index-id是模块索引。例如:

  • hisi_sccl3_l3c0/rd_hit_cpipe:SCCL 3 上第 0 号 L3C 的READ_HIT_CPIPE事件;
  • hisi_sccl1_hha0/rx_operations:SCCL 1 上第 0 号 HHA 的RX_OPERATIONS事件。

对应地,设备节点位于:

/sys/bus/event_source/devices/hisi_sccl{X}_<l3c{Y}/hha{Y}/ddrc{Y}>

以 L3C 驱动为例,hisi_uncore_l3c_pmu.c 的 probe 函数会按拓扑生成名称:有sub_id时格式为hisi_sccl%d_l3c%d_%d(v3 命名),否则为hisi_sccl%d_l3c%d,随后调用perf_pmu_register()完成注册。事件与过滤参数则通过 sysfs 的events/format/属性组暴露,perf list就是读取这些属性列出的事件清单。每个 PMU 的 sysfs 属性组都由公共的hisi_pmu_cpumask_attr_grouphisi_pmu_identifier_group与各版本的 format/events 组拼成,例如 L3C 的组装见 hisi_uncore_l3c_pmu.c。

cpumask 与 associated_cpus

文档说明驱动还提供两个额外的 sysfs 属性:

  • cpumask:显示用于统计该 uncore PMU 事件的 CPU 核心 ID。它是给 perf 等用户态工具的提示(hint),通常只包含associated_cpus中的某一个关联 CPU;
  • associated_cpus:显示与该 PMU 关联的 CPU 集合。

源码印证了这一点。hisi_uncore_pmu.c 中cpumask属性只输出单个on_cpuassociated_cpus输出hisi_pmu->associated_cpus位图。on_cpu的选择逻辑在hisi_uncore_pmu_online_cpu()(hisi_uncore_pmu.c):当某个与 PMU 拓扑关联的 CPU 上线时,驱动把该 CPU 记入associated_cpus,并将其设为on_cpu,同时把 PMU 溢出中断的 affinity 绑到同一 CPU;若 PMU 没有关联 CPU(例如位于 SICL 上),则用cpumask_local_spread()按 NUMA 节点就近选取。当on_cpu离线时,hisi_uncore_pmu_offline_cpu()(hisi_uncore_pmu.c)会通过perf_pmu_migrate_context()把 PMU 上下文迁移到新的关联 CPU 并更新中断亲和性。此外 hisi_uncore_pmu.c 在event_init里会强制执行event->cpu = hisi_pmu->on_cpu——同一个 PMU 上的所有事件被约束在同一个 CPU 上计数,这与 uncore 计数器在 die 内共享的硬件特性一致。

基础用法:perf list 与 perf stat

文档给出的标准用法如下。先用perf list查看 uncore 事件:

$# perf list hisi_sccl3_l3c0/rd_hit_cpipe/ [kernel PMU event] ------------------------------------------ hisi_sccl3_l3c0/wr_hit_cpipe/ [kernel PMU event] ------------------------------------------ hisi_sccl1_l3c0/rd_hit_cpipe/ [kernel PMU event] ------------------------------------------ hisi_sccl1_l3c0/wr_hit_cpipe/ [kernel PMU event] ------------------------------------------

再对指定 PMU 事件做整机(-a)统计,既可以用事件名,也可以用原始事件码:

$# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5 $# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5

两条命令等价:从源码的事件表 hisi_uncore_l3c_pmu.c 可以确认 L3C PMU v1 注册的事件包括rd_cpipe(0x00)、wr_cpipe(0x01)、rd_hit_cpipe(0x02)、wr_hit_cpipe(0x03)、victim_num(0x04)、rd_spipe(0x20)、wr_spipe(0x21)、rd_hit_spipe(0x22)、wr_hit_spipe(0x23)、back_invalid(0x29)、retry_cpu(0x40)、retry_ring(0x41)、prefetch_drop(0x42)——config=0x02正是rd_hit_cpipe

PMU v2(identifier 0x30):新增过滤能力

文档指出 PMU v2 的 identifier 为0x30(驱动中定义为 hisi_uncore_pmu.h 的HISI_PMU_V2 0x30),拓扑与 v1 相同,但硬件增加了一组过滤功能,都通过 perf 事件的 config1/config2 字段下发。

1. tt_core:按核/线程过滤 L3C 计数

L3C PMU 支持在簇内按 core/thread 过滤,以位图形式指定:

$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5

上例只统计该簇中 core/thread 0 和 1 产生的操作。注意文档的告诫:不要使用tt_core_deprecated指定核/线程过滤,该选项仅为向后兼容保留,且只支持 8 位,可能覆盖不全共享该 L3C 的所有核/线程。

源码中这两者的位域定义见 hisi_uncore_l3c_pmu.c 的 v2 format 组:

  • eventconfig:0-7
  • tt_core_deprecatedconfig1:0-7
  • tt_reqconfig1:8-10
  • datasrc_cfgconfig1:11-15
  • datasrc_sktconfig1:16
  • tt_coreconfig2:0-15

tt_core从 8 位扩展到 16 位以覆盖共享 L3 的全部 CPU。驱动在hisi_l3c_pmu_get_tt_core()(hisi_uncore_l3c_pmu.c)中优先取config2的新字段,为空时回退到旧字段;而check_filter()(hisi_uncore_l3c_pmu.c)同时拒绝了两者同时设置的非法组合。命中过滤后,hisi_l3c_pmu_config_core_tracetag()会把位图写入L3C_CORE_CTRL寄存器并置位L3C_PERF_CTRL的核计数使能与 tracetag 核使能(hisi_uncore_l3c_pmu.c)。

2. tt_req:按读/写/原子操作类型过滤(Tracetag)

tt_req允许只统计读、写或原子操作,缺省为统计全部操作。tt_req是 3 位字段,编码如下:

编码含义
3'b100(0x4)读操作
3'b101(0x5)写操作
3'b110(0x6)原子 store 操作
3'b111(0x7)原子非 store 操作
其他保留

示例:

$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5

上例只统计该簇内的读操作。实现上,hisi_l3c_pmu_config_req_tracetag()(hisi_uncore_l3c_pmu.c)把tt_req左移 7 位写入L3C_TRACETAG_CTRL的请求类型域并置请求使能位,再在L3C_PERF_CTRL中打开L3C_TRACETAG_EN使能位;停止时由hisi_l3c_pmu_clear_req_tracetag()对称清除。

3. datasrc:确认数据来源

datasrc用于判断数据从哪里来,是 5 位编码。文档列出的重要编码:

编码数据来源
5'b00001本 die 的 L3C
5'b01000跨 die(cross-die)的 L3C
5'b01001另一个 socket 中的 L3C
5'b01110本地 DDR
5'b01111跨 die 的 DDR
5'b10000跨 socket 的 DDR

主要用途是帮助定位数据源相对 CPU 核心的远近。多芯片场景下使用datasrc_cfg过滤时,perf 命令中还需要配置datasrc_skt

$# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/, \ hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5

源码侧,hisi_l3c_pmu_config_ds()(hisi_uncore_l3c_pmu.c)将 5 位datasrc_cfg写入每 4 个计数器共享的 8 位数据源类型寄存器(前 4 个计数器用L3C_DATSRC_TYPE0,后 4 个用L3C_DATSRC_TYPE1);若设置了datasrc_skt,则置位L3C_DATSRC_CTRLL3C_DATSRC_SKT_EN

4. uring_channel:按 uring 通道过滤 UC PMU 事件

UC PMU 的事件0x47~0x59支持按 tx 请求 uring channel 过滤,该字段为 2 位:

编码含义
2'b11统计发送到 uring_ext(MATA)通道的事件
2'b012'b11相同
2'b10统计发送到 uring(非 MATA)通道的事件
2'b00缺省值,统计发送到 uring 与 uring_ext 两个通道的事件

5. ch:按 NoC 事务通道过滤

NoC PMU 支持用该选项过滤特定事务通道的计数,当前支持的通道:

编码通道
3'b010Request 通道
3'b100Snoop 通道
3'b110Response 通道
3'b111Data 通道

6. tt_en:只统计带 tracetag 的事务

若设置tt_en,NoC PMU 只统计设置了 tracetag 的事务。tracetag 的详细机制即上文 tt_req/tt_core 部分所述。

PMU v3(identifier 0x40):子 PMU 划分与 ext 选项

PMU v3 的 identifier 为0x40。为了获得更细粒度的跟踪能力,v3 把部分 uncore PMU 拆分为若干 part,每个 part 拥有专属 PMU,这些 PMU 合起来覆盖某个 uncore 设备的全部事件监控职责。sysfs 命名格式随之变化:

/sys/bus/event_source/devices/hisi_sccl{X}_<l3c{Y}_{Z}/ddrc{Y}_{Z}/noc{Y}_{Z}>

其中Z是 sub-id,表示同一硬件设备不同 part 对应的 PMU。不同 sub-id 的 PMU 用法基本一致;特别地,L3C PMU 提供了ext选项以探索更细粒度的 L3C 统计。驱动把ext作为向硬件下发 perf 命令时的“终止提示”,取值约束为:

  • ext=0:缺省值,可以直接使用事件名;
  • ext=1ext=2:必须使用事件码,不支持事件名。

文档给出的示例:

$# perf stat -a -e hisi_sccl0_l3c1_0/rd_spipe/ sleep 5

或:

$# perf stat -a -e hisi_sccl0_l3c1_0/event=0x1,ext=1/ sleep 5

其中hisi_sccl0_l3c1_0定位的是 SCCL 0 上 L3 缓存 1 的 pipe0。第一条命令因为隐含ext=0,定位到 L3C 的第一个 part;第二条命令则对 L3C 的另一个 part 以事件0x1发起计数。

源码与文档完全对应:hisi_get_ext()config:16-17提取 ext 值(hisi_uncore_l3c_pmu.c 及 v3 format 组)。在hisi_l3c_pmu_get_event_idx()(hisi_uncore_l3c_pmu.c)中,普通事件与扩展事件分别在不同的计数器位段中分配索引,并把对应的基地址(baseext_base[ext - 1])保存到event->hw.event_base——因为普通事件和扩展事件位于不同的地址空间。probe 阶段(hisi_uncore_l3c_pmu.c)若检测到硬件支持 ext,则按中断数量推算 ext 区域数并累加计数器总数,因此 v3 的 L3C 最多可监视 2~3 倍于单区域数量的并发事件。

按 CCL/ICL ID 过滤:srcid/tgtid

v3 下用户还可通过srcid_cmd & srcid_msk配置只统计来自特定 CCL/ICL 的数据,通过tgtid_cmd & tgtid_msk统计发往特定 CCL/ICL 的数据。注意掩码语义:srcid_msk/tgtid_msk中置 1 的位表示匹配时不检查该位。若上述所有过滤选项都未启用,PMU 按缺省值工作——不区分过滤条件与 ID 信息,直接返回 PMU 计数器中的总计数。

功能限制:不支持采样与 per-task 绑定

文档明确:当前驱动不支持采样,因此perf record不可用;由于事件全部属于 uncore,attach 到具体 task 也不被支持。源码在 hisi_uncore_pmu.c 的hisi_uncore_pmu_event_init()中给出了硬性校验:

  • 采样事件或带PERF_ATTACH_TASK的事件直接返回-EOPNOTSUPP,注释解释了原因:计数器为 CPU die(SCCL)内所有核共享,且 uncore 计数器不隶属于任何 CPU,无法支持 per-task 模式;
  • event->cpu < 0(未指定 CPU)返回-EINVAL
  • 事件组内的硬件事件数不得超过 PMU 可用计数器数(hisi_validate_event_group());
  • 事件码超过该 PMU 的check_event上限返回-EINVAL。例如 L3C v1 上限为0x59L3C_V1_NR_EVENTS),v2/v3 为0xFF

另外,从驱动结构看,公共头文件定义了HISI_MAX_COUNTERS0x18(24),即单个 PMU 事件最多可挂 24 个硬件计数器;L3C 每个区域固定 8 个计数器(L3C_NR_COUNTERS)。计数精度方面,L3C v1 为 48 位计数器,v2/v3 为 64 位,这由各版本的hisi_pmu_dev_info中的counter_bits字段声明(hisi_uncore_l3c_pmu.c)。公共框架的hisi_uncore_pmu_set_event_period()(hisi_uncore_pmu.c)会把回绕点设为2^(counter_bits - 1),为极端情况下的中断延迟留出余量。

小结与深入路径

  • 设备发现:/sys/bus/event_source/devices/hisi_sccl*_{l3c,hha,ddrc}*目录下的events/format/cpumaskassociated_cpusidentifier属性是理解每个 PMU 能力的权威入口,perf list是其用户态映射;
  • 事件统计:优先perf stat -a -e <pmu>/<event>/ sleep N,需要精细过滤时按 v2/v3 的tt_corett_reqdatasrc_cfg/datasrc_sktchtt_enextsrcid/tgtid组合;
  • 使用事件名最稳妥(ext != 0除外);原始config=0xNN编码需与format/属性及驱动中的事件表核对;
  • 由于不支持采样与 per-task 绑定,本套 PMU 适合做系统级(-a)带宽、命中率、延迟来源类的统计性剖析,而非逐样本的火焰图分析;
  • 源码入口:公共框架 hisi_uncore_pmu.c 与 hisi_uncore_pmu.h,L3C 实现 hisi_uncore_l3c_pmu.c,HHA/DDRC 等其余模块见 drivers/perf/hisilicon/;L3C 的 ACPI 设备 ID 为 HISI0213(v1)、HISI0214(v2)、HISI0215(v3),可用于在 ACPI 系统中确认硬件版本(hisi_uncore_l3c_pmu.c);
  • 文档最后提示:如需特定 SoC 上 PMU 设备的完整事件清单及其信息,建议联系驱动维护者获取。

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 4:11:15

AI转行五大核心赛道实战指南:ML/DL/NLP/CV/RL深度拆解

1. 这不是“AI科普文”&#xff0c;而是一份帮你避开三年弯路的学科地图你点开这篇内容&#xff0c;大概率正站在一个真实的人生岔路口&#xff1a;想转行进AI领域&#xff0c;但刷到的全是“3个月速成大模型工程师”“Python入门到年薪50万”的标题&#xff1b;报过课&#xf…

作者头像 李华
网站建设 2026/9/10 4:11:03

hyperframes全景视频拼接:关键帧与光流传播实战解析

说起“hyperframes”&#xff0c;不同圈子的人搜到的东西可能完全不一样。搞计算机视觉的可能会想到光流法里对极几何约束下的关键帧增强&#xff0c;做三维重建的也许会联想到多视角立体匹配里的超级帧概念&#xff0c;但如果你是在视频制作、全景内容生产这些偏实操的领域搜这…

作者头像 李华
网站建设 2026/9/10 4:10:47

Electron+Vue3桌面应用架构改造实战:从VSCode插件到独立打字游戏

1. 项目概述&#xff1a;为什么一个打字游戏值得做两次&#xff1f; Electron Vue 3 桌面打字游戏实战&#xff1a;从 VSCode 扩展到独立应用的架构改造——这个标题里藏着三个关键动作&#xff1a;“打字游戏”是功能载体&#xff0c;“VSCode 扩展”是起点形态&#xff0c;“…

作者头像 李华
网站建设 2026/9/10 4:10:43

CANN/ge图引擎API:创建浮点标量常量

EsCreateScalarFloat 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Tenso…

作者头像 李华
网站建设 2026/9/10 4:10:05

FDE现场部署工程师:AI硬件落地背后的关键角色与实战指南

有一次我去一家工厂客户现场交付一台边缘 AI 推理盒子&#xff0c;客户的产线主管看着我拆箱、挂机柜、接线&#xff0c;又蹲在地上敲了一下午命令&#xff0c;最后忍不住问了一句&#xff1a;你们这个岗位到底是干嘛的&#xff1f;我说这叫 FDE&#xff0c;现场部署工程师。他…

作者头像 李华