一、问题描述
环境如下所示:
硬件环境:Milk-V Pioneer(SOPHON SG2042)
软件环境:openEuler24.03 6.6.0-27.0.0.31.oe2403.riscv64
问题复现步骤:
第一步
内核源码下载:
git clone -b OLK-6.6 https://gitee.com/openeuler/riscv-kernel.git
第二步
安装perf依赖的第三方库
第三步:源码编译perf
cd riscv-kernel/tools/perf
make ARCH=riscv WERROR=0 -j4
第四步:在riscv-kernel/tools/perf目录下安装perf
sudo cp ./perf /usr/bin/
第五步:下载hackbench
git clone https://github.com/FraSharp/hackbench.git
第六步:编译hackbench
gcc -static -O0 -g -fno-omit-frame-pointer hackbench.c -o hackbench -lpthread
第七步:测试
sudo perf record -e cpu-cycles -g ./hackbench
sudo perf report --no-children -G > perf_hackbench.txt
问题现象描述:
查看生成的perf_hackbench.txt中,可发现内核函数显示的是地址,而用户态函数显示的是函数符号名称
二、定位问题
1、排除问题仅仅存在于perf record和perf report上,对perf script和perf top也进行了测试,均发现了相同问题,这表明perf工具解析perf.data均会发生错误(根因在内核采集或者用户态解析出现故障);而且perf top会报出一个错误信息:A vmlinux file was not found.Kernel samples will not be resolved.
2、根据perf top的报错信息,在源码中找到对应的函数,进行源码分析、并加入大量的打印信息,最后在Milk-V Pioneer(SOPHON SG2042)中进行测试(perf top对加入的打印显示不友好,因此实际是用perf script对perf.data进行分析)。
sudo perf record -e cpu-cycles -F 10 ./hackbench
sudo perf script
3、在Milk-V Pioneer(SOPHON SG2042)中打印信息如下
此时,依旧无法精准定位问题。
4、考虑到鲲鹏920(openEuler23.09 linux6.4)那边perf功能是正常的,所以在鲲鹏920上进行相同的操作,打印信息如下所示:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.4.1.tar.gz
5、因为最终是在 /proc/kcore查询内核函数符号的,因此猜测是与kcore强相关的。于是去kcore - search results 中找类似的代码提交。最后发现有一处提交很可疑:[PATCH] riscv: select ARCH_PROC_KCORE_TEXT - Andreas Schwab ,
再去GitHub上查找也可以找到(主线分支在Linux6.7上正式合入的)
riscv: select ARCH_PROC_KCORE_TEXT · torvalds/linux@e0c0a7c · GitHub
6、验证猜想
在荔枝派(openEuler24.03 linux6.6)上,使用与Milk-V Pioneer(SOPHON SG2042)相同代码仓的内核源码进行测试,发现荔枝派上也出现了相同的问题。将上述补丁合入,重新进行测试,发现问题得到了解决。以下是在荔枝派上的perf截图:
因此,问题的根因是在RISC-V架构上没有开启CONFIG_ARCH_PROC_KCORE_TEXT,而开启了CONFIG_PROC_KCORE。实际使用时,必须保证同时开启 CONFIG_PROC_KCORE、 CONFIG_ARCH_PROC_KCORE_TEXT,否则在开启CONFIG_PROC_KCORE之后,系统会生成/proc/kcore,而/proc/kcore中又没有内核的符号信息,但最终又需要根据采样的内核地址去/proc/kcore查找内核符号。