news 2026/9/10 1:23:39

Linux 内核实战:Amlogic Meson DDR 带宽 PMU(meson_ddr_bw)perf 事件与过滤机制详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 内核实战:Amlogic Meson DDR 带宽 PMU(meson_ddr_bw)perf 事件与过滤机制详解

Linux 内核实战:Amlogic Meson DDR 带宽 PMU(meson_ddr_bw)perf 事件与过滤机制详解

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

本文基于 Linux 内核文档 meson-ddr-pmu.rst 展开,讲解 Amlogic Meson G12 系列 SoC 内置的 DDR 带宽性能监控单元(PMU):如何用它通过perf命令测量系统总带宽与各通道带宽、如何用 AXI 端口过滤关键字(armgpupcie等)定位“性能瓶颈是否在 DDR 带宽上”,并结合 核心驱动 与 G12 硬件实现 源码剖析 100ms 定时器中断累加、16 字节计数粒度、设备树配置与 CPU 热插拔迁移等底层机制。读完本文,你可以在 Amlogic 平台上独立完成 DDR 带宽的采集、分通道拆解与按 IP 模块归因分析。

1. 硬件背景:DRAM 控制器内部的带宽监控器

Amlogic Meson G12 SoC 的 DRAM 控制器(DMC)内部集成了一台带宽监控器(bandwidth monitor)。其基本能力包括:

  • 4 个计数通道:每个通道都可以对访问 DRAM 的请求进行计数;
  • AXI 端口过滤:每个通道可以映射并统计指定的 AXI 端口(来自 SoC 内各个 IP 模块的 DDR 访问请求),从而区分“是谁在消耗带宽”;
  • 典型用途:判断系统性能瓶颈是否出在 DDR 带宽上——例如 GPU 解码、以太网转发、eMMC 读写等场景下,单独观察对应 IP 的带宽占用。

这一点直接决定了驱动的软件形态:它不是一个按 CPU 采样的 PMU,而是一个系统级(system-wide)带宽计数器 PMU,通过定时器周期性读硬件计数器并累加,最终换算成 MB 单位的带宽数据。

驱动由两层构成:

文件职责
meson_ddr_pmu_core.c通用 PMU 框架层:perf 事件生命周期、sysfs 事件/单位/缩放属性、中断累加、CPU 热插拔迁移
meson_g12_ddr_pmu.cG12 硬件层:寄存器定义、PLL 频率推算、定时器/过滤/计数寄存器操作,以及 g12a/g12b/sm1 三套平台配置

编译入口在 Kconfig 中的CONFIG_MESON_DDR_PMU(tristate,"Amlogic DDR Bandwidth Performance Monitor",依赖ARCH_MESON || COMPILE_TEST),Makefile 将两个目标文件合并为meson_ddr_pmu_g12.o

2. perf 事件模型:total 与 4 个通道事件

文档明确指出当前驱动支持5 个 perf 事件

meson_ddr_bw/total_rw_bytes/ meson_ddr_bw/chan_1_rw_bytes/ meson_ddr_bw/chan_2_rw_bytes/ meson_ddr_bw/chan_3_rw_bytes/ meson_ddr_bw/chan_4_rw_bytes/

其中chan_{1,2,3,4}_rw_bytes通道特定事件,每个通道都支持过滤,可以让某通道只监控 SoC 中的某个特定 IP 模块。

从源码结构看,通用层的能力上限其实更大:meson_ddr_pmu_core.c 的meson_ddr_perf_event_update()处理了ALL_CHAN_COUNTER_ID以及CHAN1_COUNTER_ID~CHAN8_COUNTER_ID共 9 种事件 ID(定义于 include/soc/amlogic/meson_ddr_pmu.h),事件属性表也预置了 8 个通道(L270-L280)。而 fill_event_attr() 在 probe 时按平台chann_nr动态填充 sysfs 属性——G12A/G12B/SM1 三套dmc_hw_info均为chann_nr = 4(meson_g12_ddr_pmu.c L314-L351),因此 sysfs 下实际暴露的就是文档所述的 5 个事件。

PMU 注册名为meson_ddr_bwDDR_PERF_DEV_NAME宏,L32),注册时 cpu 传-1(L534),表示这是非 CPU 事件源,必须用-a(系统级)方式使用。

2.1 单位与缩放:为什么原始计数要乘 1.52587890625e-05

perf 框架会通过/sys/bus/event_source/devices/meson_ddr_bw/events/<event>.unit.scale两个属性把原始计数换算成带单位的显示值。驱动中两者分别是:

  • unit = MB:见 event_show_unit();
  • scale = 1.52587890625e-05:见 event_show_scale(),注释写明one count = 16 byte,即硬件每记 1 次代表传了 16 字节,16 / 1e6 = 1.52587890625e-05 MB

所以perf输出的带宽数值 = 原始计数 × 16 字节,再换算为 MB。理解这一点后就能正确解读perf statperiod/计数值。

2.2 使用限制:只支持系统级统计,不支持采样

meson_ddr_perf_event_init() 中有三条硬性检查,使用时要注意:

if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) return -EOPNOTSUPP; if (event->cpu < 0) return -EOPNOTSUPP;
  • 不支持 sampling(不能写period采样);
  • 不支持绑定到 task(不能perf record -p <pid>单进程模式),必须-a全系统采集;
  • 过滤参数个数受限:通道事件的config1/config2置位总数超过MAX_AXI_PORTS_OF_CHANNEL(定义为 4,L33)时返回-EOPNOTSUPP。注意文档正文描述为“每个通道可同时统计至多 3 个 AXI 端口”,而源码的校验上限是 4——以实际内核版本源码中的校验逻辑为准。

3. 通道过滤关键字:把带宽按 IP 模块拆开

chan_*_rw_bytes事件的强大之处在于过滤:在事件参数中用关键字=1的形式声明要统计的 AXI 端口,perf 会把它们编码进config1/config2,驱动再据此写硬件的端口-通道映射寄存器。文档列出的 DDR 访问请求过滤关键字共 25 个,结合 meson_g12_ddr_pmu.c 中PMU_FORMAT_ATTR的定义,对应的config1位号如下:

关键字含义(来源 IP)config1 位
armCPU0
gpu3D GPU1
pciePCIe 控制器2
hdcpHDCP 控制器3
hevc_frontHEVC 解码前端4
usb3_0USB3.0 控制器6
hevc_backHEVC 解码后端8
h265encHEVC 编码器9
vpu_read1OSD + VPP 读16
vpu_read2DI 读17
vpu_write1VDIN 写19
vpu_write2DI 写20
vdec传统编解码器视频解码器21
hcodecH264 编码器22
ge2dge2d 2D 图形引擎23
spicc1SPI 控制器 132
usb0USB2.0 控制器 033
dma系统 DMA 控制器 134
arb0arb0 仲裁器35
sd_emmc_bSD/eMMC b 控制器36
usb1USB2.0 控制器 137
audioAudio 模块38
sd_emmc_cSD/eMMC c 控制器43
spicc2SPI 控制器 244
ethernet以太网控制器45

几个值得注意的实现细节:

  1. config1config2的拼接:sysfs format 属性声明的是config1:0~45;在 meson_ddr_perf_event_add() 中,config1的每个置位 biti映射为 AXI idiconfig2的每个置位 biti则映射为 AXI idi + 64。也就是说 format 组中只暴露config1,perf 工具按标准 PMU 格式约定自动拆分高位参数。
  2. 不同芯片可见的关键字不同:meson_ddr_perf_format_attr_visible() 会用平台capability位掩码过滤 format 属性的可见性。三套平台的掩码分别为 g12a0x7EFF00FF03DF、g12b0x7FFF00FF3FDF、sm10x7EFF00FF07DF(L314-L351)。例如nna(config1:10)在注释中标注“for sm1 and g12b”,gdc/mipi_isp/arm1/sd_emmc_a标注“for g12b only”。因此某台机器上/sys/bus/event_source/devices/meson_ddr_bw/format/里能列出哪些过滤项,取决于具体芯片。
  3. 源码中还存在文档未列出的过滤项(如devicevpu_read3aififoparsersana等,见 L44-L84),是否可用同样受上述 capability 掩码控制。
  4. “device” 端口的子端口机制config1:7device这一聚合端口;在 dmc_g12_config_fiter() 中,AXI id ≥ 32(PORT_MAJOR)会被视为 device 端口的子端口,先置位BIT(23)选择 device,再在rs寄存器中按子端口位置位。

4. 实操:用 perf 采集 DDR 带宽

以下命令直接来自原文档示例,要求内核开启CONFIG_MESON_DDR_PMU且设备树中存在对应节点,用户态安装perf工具。

4.1 每秒输出系统总 DDR 带宽

perf stat -a -e meson_ddr_bw/total_rw_bytes/ -I 1000 sleep 10
  • -a:全系统采集(该 PMU 不支持 task 级绑定,见第 2.2 节);
  • -I 1000:每 1000ms 输出一行,得到“每秒带宽”的曲线;
  • 事件值单位为 MB(.unit 属性),计数粒度 16 字节(.scale 属性)。

4.2 分别统计 CPU 与 GPU 的 DDR 带宽并求和

perf stat -a -e meson_ddr_bw/chan_1_rw_bytes,arm=1/ -I 1000 sleep 10 perf stat -a -e meson_ddr_bw/chan_2_rw_bytes,gpu=1/ -I 1000 sleep 10 perf stat -a -e meson_ddr_bw/chan_3_rw_bytes,arm=1,gpu=1/ -I 1000 sleep 10

三条命令的分工:

  1. chan_1过滤arm=1:只统计 CPU(ARM 核)发起的 DDR 访问;
  2. chan_2过滤gpu=1:只统计 3D GPU 的 DDR 访问;
  3. chan_3同时过滤arm=1,gpu=1:统计两者之和,可与前两条交叉验证。

每条命令占用一个硬件通道,这正是“4 通道可同时监控”的用法——例如可以同时挂起 4 个chan_*事件,把 CPU、GPU、PCIe、以太网各自拆到独立通道上并行观测。注意每个通道上叠加的过滤项不得超过第 2.2 节所述的端口上限。

5. 底层实现:100ms 硬件定时器 + 中断累加

理解带宽数字是怎么产生的,关键在 G12 硬件层的 enable/IRQ/get_counters 三条路径。

5.1 寄存器布局

带宽监控寄存器(偏移均按 4 字节字编址):

偏移宏地址用途
DMC_MON_G12_CTRL00x00全局控制(使能、用定时器、4 通道使能位、bit30 为 QoS/计时中断标志)
DMC_MON_G12_CTRL1~CTRL80x04~0x204 组通道的端口映射寄存器对(CTRL1/2、CTRL3/4、CTRL5/6、CTRL7/8)
DMC_MON_G12_ALL_REQ_CNT0x24总请求计数
DMC_MON_G12_ALL_GRANT_CNT0x28总带宽(grant)计数
DMC_MON_G12_ONE_GRANT_CNT~FOR_GRANT_CNT0x2C~0x3C通道 1~4 各自带宽计数
DMC_MON_G12_TIMER0x40定时器重载值

定义见 meson_g12_ddr_pmu.c L24-L40。

5.2 定时器周期如何确定:从 PLL 寄存器反推 DDR 频率

定时器以 DDR 时钟为时基,因此要先知道 DDR 频率。dmc_g12_get_freq_quick() 直接读取设备树第二个 reg 指向的 PLL 寄存器,按xtal(24MHz) × m/n ÷ od1 ÷ od_div推算(DEFAULT_XTAL_FREQ固定 24MHz,od_div由寄存器位域映射为 2/3/4/6/8)。

然后 dmc_g12_counter_enable() 执行:

unsigned long clock_count = dmc_g12_get_freq_quick(info) / 10; /* 100ms */ writel(clock_count, info->ddr_reg[0] + DMC_MON_G12_TIMER); /* CTRL0: bit31 使能 | bit20 用定时器 | 低 4 位使能 4 通道 */

即定时器周期固定为100ms

5.3 中断处理与软件侧累加

计数器在定时器到期中断中被读取。dmc_irq_handler()(通用层)调用硬件层 dmc_g12_irq_handler():后者检查CTRL0DMC_QOS_IRQBIT(30)),置位则读出全部计数器并写回CTRL0清中断。

通用层随后把本次读到的计数累加pmu->countersall_cnt/all_req/每通道channel_cnt[i],结构见 meson_ddr_pmu.h L26-L36),并在pmu_enabled时重新调用hw_info->enable()——源码注释解释了原因:the timer interrupt only supports one shot mode, we have to re-enable it in ISR to support continue mode,即硬件定时器是单次触发模式,软件在中断里滚动重装以形成连续计时。

事件 stop 时(PERF_EF_UPDATE路径),meson_ddr_perf_event_update() 再读一次寄存器余量,用 ddr_cnt_addition() 把“软件累计值 + 寄存器当前值”合成最终计数,按事件 ID 选择all_cnt(total 事件)或对应通道值写入event->count。start 时则先清零软件累计值并使能硬件(L143-L149)。这样无论perf stat的采样窗口与 100ms 中断是否对齐,结果都是完整的区间累计。

5.4 CPU 热插拔:PMU 上下文的自动迁移

该 PMU 的计数上下文绑定在一个具体 CPU 上(perf 的 per-CPU 上下文机制)。当绑定 CPU 下线时,ddr_perf_offline_cpu() 会把上下文迁移到另一个在线 CPU(perf_pmu_migrate_context),并用irq_set_affinity把中断也改投过去。probe 阶段通过cpuhp_setup_state_multi+cpuhp_state_add_instance_nocalls注册(L520-L530),同时 sysfs 暴露只读cpumask属性(L188-L198)可以查看当前绑定的 CPU。

6. 设备树配置

硬件使能的前提是设备树中声明了 DDR PMU 节点。设备树绑定文档 amlogic,g12-ddr-pmu.yaml 定义了三个compatibleamlogic,g12a-ddr-pmuamlogic,g12b-ddr-pmuamlogic,sm1-ddr-pmu),与驱动 of_device_id 表 一一对应。必填项:

#include <dt-bindings/interrupt-controller/arm-gic.h> pmu@ff638000 { compatible = "amlogic,g12a-ddr-pmu"; reg = <0x0 0xff638000 0x0 0x100>, /* DMC 带宽监控寄存器空间 */ <0x0 0xff638c00 0x0 0x100>; /* DMC PLL 寄存器空间 */ interrupts = <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>; /* 内部定时器超时中断 */ };
  • reg共两段:前dmc_nr(此处为 1)段是 DMC 监控寄存器基址,最后一位是 PLL 寄存器基址(用于 5.2 节的频率推算)——驱动在 ddr_pmu_parse_dt() 中按此顺序ioremap
  • interrupts为内部定时器超时中断,驱动以IRQF_NOBALANCING申请,保证热插拔时能自由控制亲和性。

7. 小结与适用前提

  • 适用平台:Amlogic G12A/G12B/SM1(Meson 家族),对应compatible见第 6 节;内核配置项为CONFIG_MESON_DDR_PMU
  • 该 PMU 提供的是系统级 DDR 带宽统计:5 个事件(total + 4 通道)、MB 单位、16 字节计数粒度、100ms 硬件定时器中断采样累加;
  • 通道过滤允许把带宽归因到 CPU/GPU/PCIe/以太网/编解码/存储等具体 IP,是定位“带宽型瓶颈”的核心手段;
  • 限制:不支持采样与 task 级绑定(必须-a);单通道过滤端口数受硬件上限约束;不同芯片可见的过滤关键字由 capability 掩码决定,以/sys/bus/event_source/devices/meson_ddr_bw/format/实际输出为准。

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

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

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

企业级代码生成选型:补全/重构/Agent三层架构与Bedrock实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 1:19:53

T_MATS安装实战:MATLAB/Simulink燃气轮机建模入门与避坑指南

简介&#xff1a;T_MATS是一款基于MATLAB的热力学系统建模与分析开源工具箱&#xff0c;专为燃气轮机、涡扇发动机等复杂热力系统仿真设计&#xff0c;面向航空工程领域的工程师、科研人员及高年级学生&#xff0c;适用于教学演示与课题研究。安装包共含400个文件&#xff0c;以…

作者头像 李华
网站建设 2026/9/10 1:17:56

8款降AI率工具实测:毕业论文AIGC检测如何从67%降到20%?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 1:14:52

安卓漫画APP选择与调优:正版平台与开源阅读器的实用指南

1. 选漫画APP前必须想明白的几件事 1.1 先分清“正版平台”和“第三方阅读器” 经常有朋友问我&#xff1a;“安卓手机上到底哪个漫画APP最好用&#xff1f;”说实话&#xff0c;这个问题如果不加前提&#xff0c;根本没法回答。因为市面上的漫画阅读工具大致分成两类&#xf…

作者头像 李华