[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
RISC-V Ftrace 实现原理(7)- RISC-V 架构总结
Corrector: TinyCorrect v0.1 - [codeblock] Author: sugarfillet sugarfillet@yeah.net Date: 2022/12/01 Revisor: Falcon falcon@tinylab.org Project: RISC-V Linux 内核剖析 Proposal: RISC-V ftrace 相关技术调研与分析 Sponsor: PLCT Lab, ISCAS
前言
Linux 在 RISC-V 架构的 Ftrace 特性目前已提供基本的函数跟踪(HAVE_FUNCTION_TRACER)和函数图跟踪能力(HAVE_FUNCTION_GRAPH_TRACER),但相比成熟的 x86_64 以及 arm64 还是有不少需要优化或者补充的地方。
本文以 include/linux/ftrace.h
以及 kernel/trace/ftrace.c
文件中描述的一些需要架构实现的功能或接口为基础对 ftrace 在 RISC-V 架构上已实现和待实现的功能进行整理,并对已经在上游有初步实现的功能进行背景介绍和解读。
说明:
- 本文的 Linux 版本采用
Linux v6.0
RISC-V ftrace 功能实现状态表
Function | Description | RISC-V status | References |
---|---|---|---|
HAVE_FUNCTION_TRACER | 支持 static function tracer | ok | 10626c32e382 |
HAVE_FUNCTION_GRAPH_TRACER | 支持 static function_graph tracer | ok | 10626c32e382 |
prepare_ftrace_return | 默认的函数图跟踪函数 | ok | |
return_to_handler | 函数图跟踪返回处理例程 | ok | |
HAVE_FTRACE_MCOUNT_RECORD | recordmcount.pl 支持 RISC-V 架构的 __mcount_loc 创建 | ok | a1d2a6b4cee8 |
HAVE_DYNAMIC_FTRACE | 动态 ftrace 支持 | ok | c15ac4fd60d5 / bc1a4c3a8425 |
ftrace_caller | 动态 ftrace 实现的 mcount | ok | |
ftrace_call | ftrace_caller 中调用跟踪函数的 label | ok | |
ftrace_make_nop | 替换函数入口为 nop | ok | |
ftrace_make_call | 替换函数入口为对 ftrace_[regs]_caller 的调用 | ok | |
ftrace_update_ftrace_func | 跟踪函数替换接口 | ok | |
ftrace_enable_ftrace_graph_caller | 开启函数图跟踪 | ok | |
ftrace_disable_ftrace_graph_caller | 关闭函数图跟踪 | ok | |
ftrace_init_nop | ftrace_init 阶段对函数入口执行 nop 替换 | ok | |
ftrace_need_init_nop | ftrace_init 阶段判断是否对函数入口执行 nop 替换 | ok | |
HAVE_DYNAMIC_FTRACE_WITH_REGS | 为跟踪函数提供 pt_regs 访问 | ok | aea4c671fb98 |
ftrace_regs_caller | REGS 版本的 ftrace_caller | ok | |
ftrace_regs_call | REGS 版本的 ftrace_call | ok | |
ftrace_modify_call | 修改函数入口的跳转 | ok | |
ARCH_SUPPORTS_FTRACE_OPS | 使能 ops 作为跟踪函数的第 3 个参数 | ok | 71e736a7d655 |
HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS | 提供 register_ftrace_direct[_multi] 接口 | wip | |
HAVE_SAMPLE_FTRACE_DIRECT | 提供 register_ftrace_direct 接口的实例代码 | wip | |
HAVE_SAMPLE_FTRACE_DIRECT_MULTI | 提供 register_ftrace_direct_multi 接口的实例代码 | wip | |
FTRACE_GRAPH_TRAMP_ADDR | 独立的函数图跟踪跳板 | no_need | |
ftrace_graph_caller | 独立的函数图跟踪跳板 | no_need | |
arch_ftrace_update_trampoline | 动态 trampline | no |
HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
此功能以 register_ftrace_function
函数为基础提供 register_ftrace_direct_[multi]
函数接口,使得用户可以直接编写类似于 ftrace_caller
的跳板代码 – direct_caller
来实现对目标函数的直接跟踪。HAVE_SAMPLE_FTRACE_DIRECT
和 HAVE_SAMPLE_FTRACE_DIRECT_MULTI
则在 ./samples/ftrace/
目录下提供 direct_caller
的示例代码。
RISC-V 当前的实现可参考 “riscv: ftrace: Add DYNAMIC_FTRACE_WITH_DIRECT_CALLS support” 和 “samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]”
FTRACE_GRAPH_TRAMP_ADDR
function_graph tracer 目前通过在 ftrace_[regs]_caller
的跟踪函数调用后,为默认的函数图跟踪函数 prepare_ftrace_return
设置参数并调用。如此情况下,会引入一个问题:某个目标函数没有开启函数跟踪,只开启图跟踪,则 ftrace_[regs]_caller
对跟踪函数 ftrace_stub
的参数设置和调用还是会执行。那么,能否让只开启图跟踪的函数直接去调用 prepare_ftrace_return
呢?对于此问题,思路有二:
- 创建一个只作函数图跟踪的跳板,通过
graph_ops->trampoline
来指定,并在执行函数入口替换时采用前者进行替换 - 能否直接把
prepare_ftrace_return
当作一个普通的跟踪函数,这样就可以去掉原来ftrace_[regs]_caller
后面的对prepare_ftrace_return
的参数设置和调用
第一个思路的答案就是 FTRACE_GRAPH_TRAMP_ADDR
以及 ftrace_graph_caller
,但在 RISC-V 架构下会与现有图跟踪机制不兼容。而第二个思路就不存在兼容问题,其具体的实现,可参考 “riscv: ftrace: Add ftrace_graph_func” 和 “riscv: ftrace: Make ftrace_caller call ftrace_graph_func”。
arch_ftrace_update_trampoline
有这样一种情况:如果用 function tracer (global_ops
) 来跟踪所有内核函数,再用 kprobe_ops
跟踪了某个函数 A,那么跟踪函数会被选择为 arch_ftrace_ops_list_func
,此函数在 ftrace 实现原理(4)- 替换跟踪函数) 一文中提到过。
arch_ftrace_ops_list_func,执行时会遍历 ftrace_ops_list,结合 ops->func_hash 来判断是否需要对当前 ip 执行 ops->func。
那么除了 A 以外的函数执行时,首先跳转到 ftrace_caller
,再调用 arch_ftrace_ops_list_func
,都会匹配 kprobes_ops->func_hash
,这显然是没有必要的。动态 trampoline 在 ops 注册时为其动态分配一个 trampoline,trampoline 中调用的跟踪函数即是 ops->func
,这样的话,前文中的除了 A 以外的函数都会跳转到 global_ops
注册时动态分配的 trampoline,而不是默认的 ftrace_caller
,并在动态 trampoline 中调用 global_ops->func
,而不是 arch_ftrace_ops_list_func
,这样就很好的解决了前述的问题。详细地可参考 commit f3bea49115b2 (“ftrace/x86: Add dynamic allocated trampoline for ftrace_ops”)。
>>>>> enable function tracer on all functions AND kprobes on func_A
func_A -> ftrace_regs_caller ---\
-> arch_ftrace_ops_list_func (global_ops && kprobe_ops)
func_others -> ftrace_caller ---/
>>>>> enable dynamic trampoline optimization
func_A -> ftrace_regs_caller -----> arch_ftrace_ops_list_func (global_ops && kprobe_ops)
func_others -> dynamic trampoline -----> global_ops->func
arch_ftrace_update_trampoline
就是用来在 ops 注册时,创建动态 trampoline 的架构实现。当前 RISC-V 还不支持。
小结
本文对 RISC-V 架构下 ftrace 特性的实现进行了总结,同时也指出了一些待实现的功能,并对已经在上游有初步实现的功能进行了背景介绍和解读。这里希望 HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
和 FTRACE_GRAPH_TRAMP_ADDR
相关补丁能尽快合入主线,也希望动态 trampoline 功能能尽快实现。
参考资料
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
支付宝打赏 ¥9.68元 | 微信打赏 ¥9.68元 | |
请作者喝杯咖啡吧 |
Read Album:
- TinyBPT 和面向 buildroot 的二进制包管理服务(1):设计简介与框架
- RISC-V Linux 内核及周边技术动态第 118 期
- RISC-V Linux 内核及周边技术动态第 117 期
- 实时分析工具 rtla timerlat 介绍(二):延迟测试原理
- 实时分析工具 rtla timerlat 介绍(一):交叉编译及使用