【写在前面】飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力,聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域,包含了应用使能套件、软件仓库、软件支持、软件适配认证四大板块,旨在共享尖端技术,为开发者提供一个涵盖多领域的开发平台和工具套件。点击这里开始你的技术升级之旅吧
本文分享至飞腾开发者平台《飞腾平台perf工具PMU事件集成指南》
1 软件介绍
perf是内置于Linux-2.6+内核源码中的性能剖析工具。通过对各类性能事件的计数统计,以及在事件发生时对运行代码路径(调用栈)等进行采样记录,支持查找性能瓶颈、定位热点代码。perf支持的性能事件包括:硬件事件、软件事件、跟踪事件。其中,硬件事件由处理器实现的PMU(Performance Monitor Unit,性能监视单元)产生,探测各类与架构、微架构等相关性能事件发生的次数,例如cache-misses、cpu-cycles、instructions、branch-misses等。关于perf的更多信息可阅读参考文献【2】、【3】,关于PMU的更多信息可阅读参考文献【1】。
如下表perf list查看事件名称所示,perf为常用的硬件事件提供了符号名称(又称“事件别名“”),可以通过“-e 事件名称”的方式指定进行统计或采用的事件。对于各厂商实现的未提供符号名称的硬件事件,可以通过原始硬件事件编号“rNNN”的方式进行指定,但是使用起来不够直观和便捷。
List of pre-defined events (to be used in -e):
branch-misses [Hardware event]
bus-cycles [Hardware event]
cache-misses [Hardware event]
...
L1-dcache-load-misses [Hardware cache event]
L1-dcache-loads [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
...
br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event]
br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event]
bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event]
...
rNNN [Raw hardware event descriptor]
cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor]
本文档以飞腾FTC6xx系列核心实现的硬件事件为例,说明如何在Linux内核上为飞腾PMU硬件事件建立perf符号名称、实现自定义硬件事件集成的方法。
2 环境要求
2.1 硬件环境
硬件环境要求如下表硬件环境所示。
项目 | 说明 |
---|---|
CPU | FTC66X系列核心(FT-2000/4、FT-2000+/64) |
2.2 软件环境
软件环境要求如下表所示。perf工具源码位于Linux内核源码目录中,使用内核的头文件。因此理论上保持perf和内核版本一致,能够完全保证接口的一致性。实践中,由于perf的用户-内核接口比较稳定,所以跨版本使用也没有问题。由于编译内核时并不会编译perf工具,因此可以从kernel.org获取与当前运行内核版本一致的内核源码包,解压内核源码并进入perf目录(cd tools/perf)执行make以构建perf工具。
项目 | 说明 |
---|---|
OS | CentOS 8.3 |
kernel | 4.19.5 |
patch | patch-4.19.5-phytium.patch(飞腾补丁) |
perf | 4.19.5 |
3 功能模块
perf由pmu-events模块(tools/perf/pmu-events)实现对各厂商自定义硬件事件的集成。
pmu-events由jevents工具、mapfile.csv文件、JSON文件组成:
1)JSON文件用于描述PMU事件,包括事件编号、事件名称、事件说明等信息;
2)mapfile.csv文件用于实现CPU型号与PMU事件集的映射;
3)jevents工具基于mapfile.csv文件和JSON文件,生成pmu-events.c文件,其中包含一组PMU事件表和一张映射表。每张PMU事件表(如下表PMU事件表示例所示)描述当前硬件架构下各种CPU型号的硬件事件信息,映射表(如下表映射表示例所示)则建立CPU型号与PMU事件表的映射关系。pmu-events.c文件编译后用于构建perf工具。
perf工具运行时通过确定所在的CPU型号,查找匹配的PMU事件表,从而为事件建立符号名称,实现自定义硬件事件的集成。
PMU事件表示例
struct pmu_event pme_arm_cortex_a53[] = {
{
.name = "br_indirect_spec",
.event = "event=0x7a",
.desc = "Branch speculatively executed, indirect branch",
.topic = "branch",
.long_desc = "Branch speculatively executed, indirect branch",
},
... ...
}
映射表示例
> struct pmu_events_map pmu_events_map[] = {
{
.cpuid = "0x00000000410fd03[[:xdigit:]]",
.version = "v1",
.type = "core",
.table = pme_arm_cortex_a53
},
... ...
}
4 接口说明
由上述功能模块组成可知,pmu-events模块主要通过JSON文件和mapfile.csv文件对外提供自定义硬件事件集成的接口。本节以arm的cortex-a53为例,对上述文件的布局和内容进行说明。
4.1 文件布局
如下表arch目录层次结构所示,arch目录下按照“架构/厂商/型号”的层次结构布局。
mapfile.csv文件放置在“架构”级别目录下。用于描述架构标准事件的架构标准JSON文件放置在“架构”级别目录下,例如armv8-recommended.json。用于描述各型号CPU的PMU事件JSON文件放置在对应“型号”级别目录下。型号JSON文件中可以使用“ArchStdEvent”来引用定义在架构标准JSON文件中的“架构标准事件”,基于“EventName”字段进行匹配。建议将CPU所支持的PMU事件按模块进行分组并放在独立的JSON文件里,例如cortex-a53的branch.json、bus.json、cache.json、memory.json、pipeline.json等。
pmu-events
├── arch
│ ├── arm64
│ │ ├── arm
│ │ │ └── cortex-a53
│ │ │ ├── branch.json
│ │ │ ├── bus.json
│ │ │ ├── cache.json
│ │ │ ├── memory.json
│ │ │ ├── other.json
│ │ │ └── pipeline.json
│ │ ├── armv8-recommended.json
│ │ ├── mapfile.csv
... ...
4.2 JSON文件
如下表JSON文件内容所示,用于描述PMU事件信息的主要项目包括:
- EventCode:事件原始编号;
- EventName:对应的事件符号名称;
- PublicDescription:事件的详细说明;
- BriefDescription:事件的简要说明;
ArchStdEvent:直接使用架构标准JSON文件中定义的事件信息,指定EventName进行匹配。
[ { "PublicDescription": "Attributable Level 1 data cache access, read", "EventCode": "0x40", "EventName": "L1D_CACHE_RD", "BriefDescription": "L1D cache access, read" }, ... ... { "ArchStdEvent": "BUS_ACCESS_RD", }, ... ... ]
4.3 mapfile.csv文件
如下表mapfile.csv文件内容所示,用于描述CPU型号与PMU事件集的映射关系的主要项目包括:
- Family-model:CPUID(64bits),其中,[31-24]是销售ID(Implementer),[23-20]是大版本号(Variant),[19-16]是架构版本(Architecture),[15-4]是产品代码(PartNum),[3-0](Revision)是小版本号。需要注意的是:大版本号和小版本号(即[23:20]和[3:0]位)需要置零;
- Version:JSON文件版本号(未使用);
- PathName:JSON文件的路径,相对于tools/perf/pmu-events/arch/[架构];
- Type:PMU事件的类型,如core/uncore等。
#Family-model,Version,Filename,EventType
0x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core
0x00000000420f5160,v1,cavium/thunderx2,core
0x00000000430f0af0,v1,cavium/thunderx2,core
... ...
文件实例
表phytium/ftc66x的JSON文件、表phytium/ftc66x的mapfile.csv文件所示,本节以飞腾FTC6xx系列核心实现的硬件事件为例,给出对应的mapfile.csv文件、JSON文件。
表phytium/ftc66x目录结构
pmu-events
├── arch
│ ├── arm64
│ │ ├── armv8-recommended.json
│ │ ├── mapfile.csv
│ │ └── phytium
│ │ └── ftc66x
│ │ └── ft.json
表phytium/ftc66x的JSON文件
[
{
"PublicDescription": "Architectural-CHAIN",
"EventCode": "0x1e",
"EventName": "CHAIN",
"BriefDescription": "Architectural-CHAIN"
},
{
"ArchStdEvent": "L1D_CACHE_RD"
},
{
"ArchStdEvent": "L1D_CACHE_WR"
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_RD"
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_WR"
},
{
"ArchStdEvent": "L1D_CACHE_WB_VICTIM"
},
... ...
]
表phytium/ftc66x的mapfile.csv文件
#Family-model,Version,Filename,EventType
... ...
0x00000000700f6620,v1,phytium/ftc66x,core
0x00000000700f6630,v1,phytium/ftc66x,core
完成上述事件集成操作之后,如表perf list可以列出新增的ft事件名称。
表perf list
List of pre-defined events (to be used in -e):
branch-misses [Hardware event]
bus-cycles [Hardware event]
cache-misses [Hardware event]
... ...
L1-dcache-load-misses [Hardware cache event]
L1-dcache-loads [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
... ...
armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event]
armv8_pmuv3_0/br_pred/ [Kernel PMU event]
armv8_pmuv3_0/bus_access/ [Kernel PMU event]
... ...
ft:
ase_spec
[Operation speculatively executed, Advanced SIMD instruction]
br_immed_spec
[Branch speculatively executed, immediate branch]
br_indirect_spec
[Branch speculatively executed, indirect branch]
... ...
rNNN [Raw hardware event descriptor]
cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor]
(see 'man perf-list' on how to encode it)
5 常见问题
5.1 问题描述
CPUID是mapfile.csv文件中的关键项目,用于匹配当前硬件环境中的CPU型号以实现perf中的PMU事件符号名称。那么,如何获取CPUID?
5.2 问题处理
方法一:
执行cat /sys/devices/system/cpu/cpu0/regs/identification/midr_el1。需要注意的是,大版本号和小版本号(即[23:20]和[3:0]位)需要置零。
表 cat /sys/devices/system/cpu/cpu0/regs/identification/midr_el1
#cat /sys/devices/system/cpu/cpu0/regs/identification/midr_el1
0x00000000701f6622
方法二:
执行 perf list --debug。可以直接获得可以用于当前硬件环境下的CPUID。
表perf list --debug
#perf list --debug
Using CPUID 0x00000000700f6620
List of pre-defined events (to be used in -e):
branch-misses [Hardware event]
... ...
6 参考资料
[1] ARM Cortex-A72 MPCore Processor Technical Reference Manual r0p3(2016)
[2] perf学习总结,https://zhuanlan.zhihu.com/p/141694060(2020)
[3] perf wiki, https://perf.wiki.kernel.org/index.php/Tutorial(2015)
推荐阅读
欢迎广大开发者来飞腾开发者平台获取更多前沿技术文档及资料
如开发者在使用飞腾产品有任何问题可通过在线工单联系我们
版权所有。飞腾信息技术有限公司 2023。保留所有权利。
未经本公司同意,任何单位、公司或个人不得擅自复制,翻译,摘抄本文档内容的部分或全部,不得以任何方式或途径进行传播和宣传。
商标声明
Phytium和其他飞腾商标均为飞腾信息技术有限公司的商标。
本文档提及的其他所有商标或注册商标,由各自的所有人拥有。
注意
本文档的内容视为飞腾的保密信息,您应当严格遵守保密任务;未经飞腾事先书面同意,您不得向任何第三方披露本文档内容或提供给任何第三方使用。
由于产品版本升级或其他原因,本文档内容会不定期进行更新。除非另有约定,本文档仅作为使用指导,飞腾在现有技术的基础上尽最大努力提供相应的介绍及操作指引,但飞腾在此明确声明对本文档内容的准确性、完整性、适用性、可靠性的等不作任何明示或暗示的保证。
本文档中所有内容,包括但不限于图片、架构设计、页面布局、文字描述,均由飞腾和/或其关联公司依法拥有其知识产权,包括但不限于商标权、专利权、著作权等。非经飞腾和/或其关联公司书面同意,任何人不得擅自使用、修改,复制上述内容。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。