riscv: Optimize function trace
v7 cover riscv: Optimize function trace
From: Guo Ren <[email protected]>
The previous ftrace detour implementation fc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT") contain three problems.
- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
- The "-fpatchable-function-entry= CFLAG" wasted code size !RISCV_ISA_C.
- The ftrace detour implementation wasted code size.
- When livepatching, the trampoline (ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_L ra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result. (Found by Evgenii Shatokhin [4])
Patches 1,2,3 fixup above problems.
Patches 4,5,6,7 are the features based on reduced detour code patch, we include them in the series for test and maintenance.
You can directly try it with:
https://github.com/guoren83/linux/tree/ftrace_fixup_v7
Make function graph use ftrace directly [2] (patch 4, 5)
========================================================
In RISC-V architecture, when we enable the ftrace_graph tracer on some functions, the function tracings on other functions will suffer extra graph tracing work. In essence, graph_ops isn't limited by its func_hash due to the global ftrace_graph_[regs]_call label. That should be corrected.
What inspires me is the commit 0c0593b45c9b ("x86/ftrace: Make function graph use ftrace directly") that uses graph_ops::func function to install return_hooker and makes the function called against its func_hash.
This series of patches makes function graph use ftrace directly for riscv.
If FTRACE_WITH_REGS isn't defined, ftrace_caller keeps ftrace_graph_call so that it can be replaced with the calling of prepare_ftrace_return by the enable/disable helper.
As for defining FTRACE_WITH_REGS, ftrace_caller is adjusted to save the necessary regs against the pt_regs layout, so it can reasonably call the graph_ops::func function - ftrace_graph_func. And ftrace_graph_[regs]_call
and its enable/disable helper aren't needed.
Test log:
The tests generated by CONFIG_FTRACE_STARTUP_TEST have passed in the local
qemu-system-riscv64 virt machine. The following is the log during startup.
``` Nov 15 03:07:13 stage4 kernel: Testing tracer function: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #1: Nov 15 03:07:13 stage4 kernel: (1 0 1 0 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 0 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 0 365) Nov 15 03:07:13 stage4 kernel: (2 2 4 0 399) Nov 15 03:07:13 stage4 kernel: (3 2 4 0 146071) Nov 15 03:07:13 stage4 kernel: (3 3 5 0 146105) PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #2: Nov 15 03:07:13 stage4 kernel: (1 0 1 589 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 635 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 1 2) Nov 15 03:07:13 stage4 kernel: (2 2 4 125 126) Nov 15 03:07:13 stage4 kernel: (3 2 4 146001 146078) Nov 15 03:07:13 stage4 kernel: (3 3 5 146035 146112) PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion safe: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace regs: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer nop: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer irqsoff: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup: Nov 15 03:07:13 stage4 kernel: sched: DL replenish lagged too much Nov 15 03:07:13 stage4 kernel: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_rt: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_dl: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer function_graph: PASSED ```
Add WITH_DIRECT_CALLS support [3] (patch 6, 7)
==============================================
This series adds DYNAMIC_FTRACE_WITH_DIRECT_CALLS support for RISC-V. SAMPLE_FTRACE_DIRECT and SAMPLE_FTRACE_DIRECT_MULTI are also included here as the samples for testing DIRECT_CALLS related interface.
First, select the DYNAMIC_FTRACE_WITH_DIRECT_CALLS to provide register_ftrace_direct[_multi] interfaces allowing user to register the customed trampoline (direct_caller) as the mcount for one or more target functions. And modify_ftrace_direct[_multi] are also provided for modify direct_caller.
At the same time, the samples in ./samples/ftrace/ can be built as kerenl module for testing these interfaces with SAMPLE_FTRACE_DIRECT and SAMPLE_FTRACE_DIRECT_MULTI selected.
Second, to make the direct_caller and the other ftrace hooks (eg. function/fgraph tracer, k[ret]probes) co-exist, a temporary register
are nominated to store the address of direct_caller in ftrace_regs_caller.
After the setting of the address direct_caller by direct_ops->func and the RESTORE_REGS in ftrace_regs_caller, direct_caller will be jumped to by the jr inst.
The following tests have been passed in my local qemu-riscv64 virt machine.
1. tests with CONFIG_FTRACE_STARTUP_TEST
2. tests of samples/ftrace/ftrace*.ko
3. manual tests with any combination of the following hooks
- function/function_graph tracer
- ftrace*.ko
- kprobe/kretprobe
For your reference, here is the log when function tracer, kretprobe and ftrace-direct-too.ko co-hooks the handle_mm_fault function.
```
[root@stage4 tracing]# echo handle_mm_fault > set_ftrace_filter
[root@stage4 tracing]# echo 'r:myr handle_mm_fault' > kprobe_events
[root@stage4 tracing]# echo function > current_tracer
[root@stage4 tracing]# echo 1 > events/kprobes/myr/enable
[root@stage4 tracing]# insmod /root/ftrace-direct-too.ko
[root@stage4 tracing]#
[root@stage4 tracing]# cat trace | tail
cat-388 [000] ...1. 583.051438: myr:
(do_page_fault+0x16c/0x5f2 <- handle_mm_fault)
cat-388 [000] ...2. 583.057930: handle_mm_fault
<-do_page_fault
cat-388 [000] ..... 583.057990: my_direct_func:
handle mm fault vma=000000002d9fe19c address=ffffffae9b7000 flags=215
cat-388 [000] ...1. 583.058284: myr:
(do_page_fault+0x16c/0x5f2 <- handle_mm_fault)
tail-389 [001] ...2. 583.059062: handle_mm_fault
<-do_page_fault
tail-389 [001] ..... 583.059104: my_direct_func:
handle mm fault vma=0000000017f3c48e address=aaaaaabebf3000 flags=215
tail-389 [001] ...1. 583.059325: myr:
(do_page_fault+0x16c/0x5f2 <- handle_mm_fault)
tail-389 [001] ...2. 583.060371: handle_mm_fault
<-do_page_fault
tail-389 [001] ..... 583.060410: my_direct_func:
handle mm fault vma=0000000017f3c48e address=aaaaaabebf1000 flags=255
tail-389 [001] ...1. 583.060996: myr:
(do_page_fault+0x16c/0x5f2 <- handle_mm_fault)
```Note1:
The checkpatch.pl will output some warnings on this series, like this
``` WARNING: Prefer using '"%s...", __func__' to using 'my_direct_func2', this function's name, in a string 111: FILE: samples/ftrace/ftrace-direct-multi-modify.c:48: +" call my_direct_func2\n" ```
The reason is that checkpatch depends on patch context providing the function name. In the above warning, my_direct_func2 has some codeline distance with the changed trunk, so its declaration doesn't come into the patch, and then the warning jumps out.
You may notice the location of my_ip variable changes in the 2nd patch. I did that for reducing the warnings to some extent. But killing all the warnings will makes the patch less readable, so I stopped here.
[1] https://lpc.events/event/16/contributions/1171/
[2] https://lore.kernel.org/lkml/[email protected]/
[3] https://lore.kernel.org/linux-riscv/[email protected]/
[4] https://lore.kernel.org/linux-riscv/[email protected]/
Changes in v7:
- Fixup RESTORE_ABI_REGS by remove PT_T0(sp) overwrite.
- Add FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
- Fixup kconfig with HAVE_SAMPLE_FTRACE_DIRECT & HAVE_SAMPLE_FTRACE_DIRECT_MULTI
Changes in v6:
https://lore.kernel.org/linux-riscv/[email protected]/
- Replace 8 with MCOUNT_INSN_SIZE
- Replace "REG_L a1, PT_RA(sp)" with "mv a1, ra"
- Add Evgenii Shatokhin comment
Changes in v5:
https://lore.kernel.org/linux-riscv/[email protected]/
- Sort Kconfig entries in alphabetical order.
Changes in v4:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [3] for maintenance. [Song Shuai]
Changes in V3:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [2] for maintenance. [Song Shuai]
Changes in V2:
https://lore.kernel.org/linux-riscv/[email protected]/
- Add Signed-off for preemption fixup.
Changes in V1:
https://lore.kernel.org/linux-riscv/[email protected]/
Andy Chiu (1):
riscv: ftrace: Fixup panic by disabling preemption
Guo Ren (2):
riscv: ftrace: Remove wasted nops for !RISCV_ISA_C
riscv: ftrace: Reduce the detour code size to half
Song Shuai (4):
riscv: ftrace: Add ftrace_graph_func
riscv: ftrace: Add DYNAMIC_FTRACE_WITH_DIRECT_CALLS support
samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI] riscv : select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
arch/riscv/Kconfig | 6 +- arch/riscv/Makefile | 6 +- arch/riscv/include/asm/ftrace.h | 71 ++++++-- arch/riscv/kernel/ftrace.c | 91 ++++------ arch/riscv/kernel/mcount-dyn.S | 179 +++++++++++++------- samples/ftrace/ftrace-direct-modify.c | 33 ++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 ++++ samples/ftrace/ftrace-direct-multi.c | 22 +++ samples/ftrace/ftrace-direct-too.c | 26 +++ samples/ftrace/ftrace-direct.c | 22 +++ 10 files changed, 356 insertions(+), 137 deletions(-)
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v7 1/7 riscv: ftrace: Fixup panic by disabling preemption
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.
p: patched area performed by dynamic ftraceftrace_prologue:
p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)
func:
xxx
ret
--- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/Kconfig +1 -1
@@ -138,7 +138,7 @@ config RISCV select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_TRACER if !XIP_KERNEL + select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Mark Rutland
reviewerRe: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)
Quoted 3 lines
func:
xxx
ret
As mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the ftrace_prologue while another CPU is patching the ftrace_prologue, you have the exact same issue.
For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
Note that the above is even assuming that instruction fetches are atomic, which I'm not sure is the case; for example arm64 has special CMODX / "Concurrent MODification and eXecutuion of instructions" rules which mean only certain instructions can be patched atomically.
Either I'm missing something that provides mutual exclusion between the patching and execution of the ftrace_prologue, or this patch is not sufficient.
Thanks,
Mark.
Quoted 23 lines
Fixes afc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT")Signed-off-by Andy Chiu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/riscv/Kconfig +1
-1@@ -138,7 +138,7 @@ config RISCV select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_TRACER if !XIP_KERNEL + select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION config ARCH_MMAP_RND_BITS_MIN default 18 if 64BITSignature · 1 line
2.36.1
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Mark Rutland
reviewerRe: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
Quoted 35 lines · Mark Rutland
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)Quoted 3 lines
func:
xxx
retAs mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the
ftrace_prologuewhile another CPU is patching theftrace_prologue, you have the exact same issue.
Quoted 5 lines
For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
With that in mind, I think your current implementation of ftrace_make_call() and ftrace_make_nop() have a simlar bug. A caller might execute:
NOP // not yet patched to AUIPC
< AUIPC and JALR instructions both patched >
JALR
... and go to the wrong place.
Assuming individual instruction fetches are atomic, and that you only ever branch to the same trampoline, you could fix that by always leaving the AUIPC in place, so that you only patch the JALR to enable/disable the callsite.
Depending on your calling convention, if you have two free GPRs, you might be able to avoid the stacking of RA by always saving it to a GPR in the callsite, using a different GPR for the address generation, and having the ftrace trampoline restore the original RA value, e.g.
MV GPR1, ra
AUIPC GPR2, high_bits_of(ftrace_caller)
JALR ra, high_bits(GPR2) // only patch this
... which'd save an instruction per callsite.
Thanks,
Mark.
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
Quoted 50 lines · Mark Rutland
Quoted 35 lines · Mark Rutland
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)Quoted 3 lines
func:
xxx
retAs mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the
ftrace_prologuewhile another CPU is patching theftrace_prologue, you have the exact same issue.Quoted 5 lines
For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
With that in mind, I think your current implementation of
ftrace_make_call()andftrace_make_nop()have a simlar bug. A caller might execute:NOP // not yet patched to AUIPC
< AUIPC and JALR instructions both patched >
Quoted 7 lines
JALR
... and go to the wrong place.
Assuming individual instruction fetches are atomic, and that you only ever branch to the same trampoline, you could fix that by always leaving the AUIPC in place, so that you only patch the JALR to enable/disable the callsite.
Yes, the same trampoline is one of the antidotes.
Quoted 9 lines
Depending on your calling convention, if you have two free GPRs, you might be able to avoid the stacking of RA by always saving it to a GPR in the callsite, using a different GPR for the address generation, and having the ftrace trampoline restore the original RA value, e.g.
MV GPR1, ra AUIPC GPR2, high_bits_of(ftrace_caller) JALR ra, high_bits(GPR2) // only patch this
I think you mean temp registers here. We are at the prologue of a function, so we have all of them.
But why do you need another "MV GPR1, ra"
AUIPC GPR2, high_bits_of(ftrace_caller)
JALR GPR2, high_bits(GPR2) // only patch this
We could reserve ra on the trampoline.
MV XX, ra
Quoted 5 lines
... which'd save an instruction per callsite.
Thanks,
Mark.
Signature · 2 lines
Best Regards Guo Ren
Re: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
In reply to Mark RutlandQuoted 42 lines · Mark Rutland
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)Quoted 3 lines
func:
xxx
retAs mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the
ftrace_prologuewhile another CPU is patching theftrace_prologue, you have the exact same issue.For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
Quoted 7 lines
Note that the above is even assuming that instruction fetches are atomic, which I'm not sure is the case; for example arm64 has special CMODX / "Concurrent MODification and eXecutuion of instructions" rules which mean only certain instructions can be patched atomically.
Either I'm missing something that provides mutual exclusion between the patching and execution of the
ftrace_prologue, or this patch is not sufficient.
This patch is sufficient because riscv isn't the same as arm64. It uses default arch_ftrace_update_code, which uses stop_machine. See kernel/trace/ftrace.c:
void __weak arch_ftrace_update_code(int command)
{
ftrace_run_stop_machine(command);
}ps:
Yes, it's not good, and it's expensive.
Quoted 27 lines
Thanks,
Mark.Quoted 23 lines
Fixes afc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT")Signed-off-by Andy Chiu <[email protected]>Signed-off-by Guo Ren <[email protected]>--- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/riscv/Kconfig +1
-2@@ -138,7 +138,7 @@ config RISCV select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_TRACER if !XIP_KERNEL + select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT --2.36.1
Signature · 7 lines
Best Regards Guo Ren _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Mark Rutland
reviewerRe: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
Quoted 50 lines · Guo Ren
Quoted 42 lines · Mark Rutland
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)Quoted 3 lines
func:
xxx
retAs mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the
ftrace_prologuewhile another CPU is patching theftrace_prologue, you have the exact same issue.For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
Quoted 7 lines
Note that the above is even assuming that instruction fetches are atomic, which I'm not sure is the case; for example arm64 has special CMODX / "Concurrent MODification and eXecutuion of instructions" rules which mean only certain instructions can be patched atomically.
Either I'm missing something that provides mutual exclusion between the patching and execution of the
ftrace_prologue, or this patch is not sufficient.
Quoted 7 lines
This patch is sufficient because riscv isn't the same as arm64. It uses default
arch_ftrace_update_code, which usesstop_machine. Seekernel/trace/ftrace.c:
void__weakarch_ftrace_update_code(int command){ ftrace_run_stop_machine(command); }
Ah; sorry, I had misunderstood here, since the commit message spoke in terms of removing that.
As long as stop_machine() is used I agree this is safe; sorry for the noise.
Quoted 2 lines
ps:
Yes, it's not good, and it's expensive.
We can't have everything! :)
Thanks,
Mark.
Re: [PATCH -next V7 1/7] riscv: ftrace: Fixup panic by disabling preemption
Quoted 60 lines · Mark Rutland
Quoted 50 lines · Guo Ren
Quoted 42 lines · Mark Rutland
Hi Guo,
Quoted 19 lines · On Thu, Jan 12, 2023 at 04:05:57AM -0500, [email protected] wrote:
From: Andy Chiu <[email protected]>
In RISCV, we must use an AUIPC + JALR pair to encode an immediate, forming a jump that jumps to an address over 4K. This may cause errors if we want to enable kernel preemption and remove dependency from patching code with
stop_machine(). For example, if a task was switched out on auipc. And, if we changed the ftrace function before it was switched back, then it would jump to an address that has updated 11:0 bits mixing with previous XLEN:12 part.p: patched area performed by dynamic ftrace
ftrace_prologue:p| REG_S ra, -SZREG(sp) p| auipc ra, 0x? ------------> preempted ... change ftrace function ... p| jalr -?(ra) <------------- switched back p| REG_L ra, -SZREG(sp)Quoted 3 lines
func:
xxx
retAs mentioned on the last posting, I don't think this is sufficient to fix the issue. I've replied with more detail there:
https://lore.kernel.org/lkml/Y7%2F3hoFjS49yy52W@FVFF77S0Q05N/
Even in a non-preemptible SMP kernel, if one CPU can be in the middle of executing the
ftrace_prologuewhile another CPU is patching theftrace_prologue, you have the exact same issue.For example, if CPU X is in the prologue fetches the old AUIPC and the new JALR (because it races with CPU Y modifying those), CPU X will branch to the wrong address. The race window is much smaller in the absence of preemption, but it's still there (and will be exacerbated in virtual machines since the hypervisor can preempt a vCPU at any time).
Quoted 7 lines
Note that the above is even assuming that instruction fetches are atomic, which I'm not sure is the case; for example arm64 has special CMODX / "Concurrent MODification and eXecutuion of instructions" rules which mean only certain instructions can be patched atomically.
Either I'm missing something that provides mutual exclusion between the patching and execution of the
ftrace_prologue, or this patch is not sufficient.Quoted 7 lines
This patch is sufficient because riscv isn't the same as arm64. It uses default
arch_ftrace_update_code, which usesstop_machine. Seekernel/trace/ftrace.c:
void__weakarch_ftrace_update_code(int command){ ftrace_run_stop_machine(command); }
Quoted 4 lines
Ah; sorry, I had misunderstood here, since the commit message spoke in terms of removing that.
As long as
stop_machine()is used I agree this is safe; sorry for the noise.
Okay.
Hi Palmer,
Please take Andy's fixup patch. We would continue to find a way for PREEMPTION.
Quoted 8 lines
Quoted 3 lines
ps:
Yes, it's not good, and it's expensive.We can't have everything! :)
Thanks,
Mark.
Signature · 2 lines
Best Regards Guo Ren
PATCH v7 2/7 riscv: ftrace: Remove wasted nops for !RISCV_ISA_C
In reply to [email protected]From: Guo Ren <[email protected]>
When CONFIG_RISCV_ISA_C=n, -fpatchable-function-entry=8 would generate more nops than we expect. Because it treat nop opcode as 0x00000013 instead of 0x0001.
Dump of assembler code for function dw_pcie_free_msi:
0xffffffff806fce94 <+0>: sd ra,-8(sp) 0xffffffff806fce98 <+4>: auipc ra,0xff90f 0xffffffff806fce9c <+8>: jalr -684(ra) # 0xffffffff8000bbec <ftrace_caller> 0xffffffff806fcea0 <+12>: ld ra,-8(sp) 0xffffffff806fcea4 <+16>: nop /* wasted */ 0xffffffff806fcea8 <+20>: nop /* wasted */ 0xffffffff806fceac <+24>: nop /* wasted */ 0xffffffff806fceb0 <+28>: nop /* wasted */ 0xffffffff806fceb4 <+0>: addi sp,sp,-48 0xffffffff806fceb8 <+4>: sd s0,32(sp) 0xffffffff806fcebc <+8>: sd s1,24(sp) 0xffffffff806fcec0 <+12>: sd s2,16(sp) 0xffffffff806fcec4 <+16>: sd s3,8(sp) 0xffffffff806fcec8 <+20>: sd ra,40(sp) 0xffffffff806fcecc <+24>: addi s0,sp,48
--- arch/riscv/Makefile | 4 ++++ 1 file changed, 4 insertions(+)
arch/riscv/Makefile +4 -0
@@ -11,7 +11,11 @@ LDFLAGS_vmlinux := ifeq ($(CONFIG_DYNAMIC_FTRACE),y) LDFLAGS_vmlinux := --no-relax KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY +ifeq ($(CONFIG_RISCV_ISA_C),y) CC_FLAGS_FTRACE := -fpatchable-function-entry=8 +else + CC_FLAGS_FTRACE := -fpatchable-function-entry=4 +endif endif ifeq ($(CONFIG_CMODEL_MEDLOW),y)
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v7 3/7 riscv: ftrace: Reduce the detour code size to half
In reply to [email protected]From: Guo Ren <[email protected]>
Use a temporary register to reduce the size of detour code from 16 bytes to 8 bytes. The previous implementation is from 'commit afc76b8b8011 ("riscv:
Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT")'.
Before the patch:
<func_prolog>:
0: REG_S ra, -SZREG(sp) 4: auipc ra, ? 8: jalr ?(ra) 12: REG_L ra, -SZREG(sp)
(func_boddy)
After the patch:
<func_prolog>:
0: auipc t0, ?
4: jalr t0, ?(t0)
(func_boddy)
This patch not just reduces the size of detour code, but also fixes an important issue:
An Ftrace callback registered with FTRACE_OPS_FL_IPMODIFY flag can actually change the instruction pointer, e.g. to "replace" the given kernel function with a new one, which is needed for livepatching, etc.
In this case, the trampoline (ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_L ra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result.
This can be easily demonstrated if one tries to "replace", say, cmdline_proc_show() with a new function with the same signature using instruction_pointer_set(&fregs->regs, new_func_addr) in the Ftrace callback.
--- arch/riscv/Makefile | 4 +- arch/riscv/include/asm/ftrace.h | 50 +++++++++++++++++++------ arch/riscv/kernel/ftrace.c | 65 ++++++++++----------------------- arch/riscv/kernel/mcount-dyn.S | 42 ++++++++------------- 4 files changed, 75 insertions(+), 86 deletions(-)
arch/riscv/Makefile +2 -2
@@ -12,9 +12,9 @@ ifeq ($(CONFIG_DYNAMIC_FTRACE),y) LDFLAGS_vmlinux := --no-relax KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY ifeq ($(CONFIG_RISCV_ISA_C),y) - CC_FLAGS_FTRACE := -fpatchable-function-entry=8 -else CC_FLAGS_FTRACE := -fpatchable-function-entry=4 +else + CC_FLAGS_FTRACE := -fpatchable-function-entry=2 endif endif
arch/riscv/include/asm/ftrace.h +38 -12
69 lines not on this page · raw message
arch/riscv/kernel/ftrace.c +19 -46
138 lines not on this page · raw message
arch/riscv/kernel/mcount-dyn.S +16 -26
127 lines not on this page · raw message
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 3/7] riscv: ftrace: Reduce the detour code size to half
Hi,
Quoted 432 lines · On 12.01.2023 12:05, [email protected] wrote:
From: Guo Ren <[email protected]>
Use a temporary register to reduce the size of detour code from 16 bytes to 8 bytes. The previous implementation is from 'commit
afc76b8b8011("riscv:
UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT")'.Before the patch:
<func_prolog>:0: REG_S ra, -SZREG(sp) 4: auipc ra, ? 8: jalr ?(ra)12:
REG_Lra, -SZREG(sp)
(func_boddy)After the patch:
<func_prolog>:
0: auipc t0, ?
4: jalr t0, ?(t0)
(func_boddy)This patch not just reduces the size of detour code, but also fixes an important issue:
An Ftrace callback registered with
FTRACE_OPS_FL_IPMODIFYflag can actually change the instruction pointer, e.g. to "replace" the given kernel function with a new one, which is needed for livepatching, etc.In this case, the trampoline (
ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_Lra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result.This can be easily demonstrated if one tries to "replace", say,
cmdline_proc_show()with a new function with the same signature usinginstruction_pointer_set(&fregs->regs, new_func_addr)in the Ftrace callback.Co-developed-by Song Shuai <[email protected]>Signed-off-by Song Shuai <[email protected]>Signed-off-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Cc Evgenii Shatokhin <[email protected]>--- arch/riscv/Makefile | 4 +- arch/riscv/include/asm/ftrace.h | 50 +++++++++++++++++++------ arch/riscv/kernel/ftrace.c | 65 ++++++++++----------------------- arch/riscv/kernel/mcount-dyn.S | 42 ++++++++------------- 4 files changed, 75 insertions(+), 86 deletions(-)arch/riscv/Makefile +2
-2@@ -12,9 +12,9 @@ ifeq ($(CONFIG_DYNAMIC_FTRACE),y) LDFLAGS_vmlinux := --no-relax KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY ifeq ($(CONFIG_RISCV_ISA_C),y) - CC_FLAGS_FTRACE := -fpatchable-function-entry=8 -else CC_FLAGS_FTRACE := -fpatchable-function-entry=4 +else + CC_FLAGS_FTRACE := -fpatchable-function-entry=2 endif endifarch/riscv/include/asm/ftrace.h +38
-12@@ -42,6 +42,14 @@ struct dyn_arch_ftrace {* 2) jalr: setting low-12 offset to ra, jump to ra, and set ra to * return address (original pc + 4) * +*<ftrace enable>: +* 0: auipc t0/ra, 0x? +* 4: jalr t0/ra, ?(t0/ra) +* +*<ftrace disable>: +* 0: nop +* 4: nop +* * Dynamic ftrace generates probes to call sites, so we must deal with * both auipc and jalr at the same time. */ @@ -52,25 +60,43 @@ struct dyn_arch_ftrace {#define AUIPC_OFFSET_MASK (0xfffff000)#define AUIPC_PAD (0x00001000)#define JALR_SHIFT 20 -#define JALR_BASIC (0x000080e7) -#define AUIPC_BASIC (0x00000097) +#define JALR_RA (0x000080e7) +#define AUIPC_RA (0x00000097) +#define JALR_T0 (0x000282e7) +#define AUIPC_T0 (0x00000297)#define NOP4 (0x00000013) -#define make_call (caller, callee, call) \ +#define to_jalr_t0 (offset) \ + (((offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_T0) + +#define to_auipc_t0 (offset) \ + ((offset & JALR_SIGN_MASK) ? \ + (((offset & AUIPC_OFFSET_MASK) + AUIPC_PAD) | AUIPC_T0) : \ + ((offset & AUIPC_OFFSET_MASK) | AUIPC_T0)) + +#define make_call_t0 (caller, callee, call) \ do { \ - call[0] = to_auipc_insn((unsigned int)((unsigned long)callee - \ - (unsigned long)caller)); \ - call[1] = to_jalr_insn((unsigned int)((unsigned long)callee - \ - (unsigned long)caller)); \ + unsigned int offset = \ + (unsigned long) callee - (unsigned long) caller; \ + call[0] = to_auipc_t0(offset); \ + call[1] = to_jalr_t0(offset); \ } while (0) -#define to_jalr_insn (offset) \ - (((offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_BASIC) +#define to_jalr_ra (offset) \ + (((offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_RA) -#define to_auipc_insn (offset) \ +#define to_auipc_ra (offset) \ ((offset & JALR_SIGN_MASK) ? \ - (((offset & AUIPC_OFFSET_MASK) + AUIPC_PAD) | AUIPC_BASIC) : \ - ((offset & AUIPC_OFFSET_MASK) | AUIPC_BASIC)) + (((offset & AUIPC_OFFSET_MASK) + AUIPC_PAD) | AUIPC_RA) : \ + ((offset & AUIPC_OFFSET_MASK) | AUIPC_RA)) + +#define make_call_ra (caller, callee, call) \ +do { \ + unsigned int offset = \ + (unsigned long) callee - (unsigned long) caller; \ + call[0] = to_auipc_ra(offset); \ + call[1] = to_jalr_ra(offset); \ +} while (0)/* * Let auipc+jalr be the basic *mcount unit*, so we make it 8 bytes here. arch/riscv/kernel/ftrace.c +19
-46@@ -55,12 +55,15 @@ static int ftrace_check_current_call(unsigned long hook_pos, }static int __ftrace_modify_call (unsigned long hook_pos,unsigned long target, -bool enable) +bool enable,bool ra) {unsigned int call[2 ];unsigned int nops[2 ] = {NOP4 ,NOP4 }; -make_call (hook_pos, target, call); +if (ra) +make_call_ra (hook_pos, target, call); +else +make_call_t0 (hook_pos, target, call);/* Replace the auipc-jalr pair at once. Return -EPERM on write error. */ if (patch_text_nosync@@ -70,42 +73,13 @@ static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target,return 0 ; } -/* -* Put 5 instructions with 16 bytes at the front of function within -* patchable function entry nops' area. -* -* 0: REG_S ra, -SZREG(sp) -* 1: auipc ra, 0x? -* 2: jalr -?(ra) -* 3: REG_L ra, -SZREG(sp) -* -* So the opcodes is: -* 0: 0xfe113c23 (sd)/0xfe112e23 (sw) -* 1: 0x???????? -> auipc -* 2: 0x???????? -> jalr -* 3: 0xff813083 (ld)/0xffc12083 (lw) -*/ -#if __riscv_xlen ==64 -#define INSN0 0xfe113c23 -#define INSN3 0xff813083 -#elif __riscv_xlen ==32 -#define INSN0 0xfe112e23 -#define INSN3 0xffc12083 -#endif - -#define FUNC_ENTRY_SIZE 16 -#define FUNC_ENTRY_JMP 4 -int ftrace_make_call (struct dyn_ftrace *rec,unsigned long addr) { -unsigned int call[4 ] = {INSN0 ,0 ,0 ,INSN3 }; -unsigned long target = addr; -unsigned long caller = rec->ip +FUNC_ENTRY_JMP ; +unsigned int call[2 ]; - call[1 ] =to_auipc_insn ((unsigned int )(target - caller)); - call[2 ] =to_jalr_insn ((unsigned int )(target - caller)); +make_call_t0 (rec->ip, addr, call); -if (patch_text_nosync ((void *)rec->ip, call,FUNC_ENTRY_SIZE )) +if (patch_text_nosync ((void *)rec->ip, call,MCOUNT_INSN_SIZE ))return -EPERM ;return 0 ;@@ -114,15 +88,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)int ftrace_make_nop (struct module *mod,struct dyn_ftrace *rec,unsigned long addr) { -unsigned int nops[4 ] = {NOP4 ,NOP4 ,NOP4 ,NOP4 }; +unsigned int nops[2 ] = {NOP4 ,NOP4 }; -if (patch_text_nosync ((void *)rec->ip, nops,FUNC_ENTRY_SIZE )) +if (patch_text_nosync ((void *)rec->ip, nops,MCOUNT_INSN_SIZE ))return -EPERM ;return 0 ; } -/* * This is called early on, and isn't wrapped by * ftrace_arch_code_modify_{prepare,post_process}() and therefor doesn't hold @@ -144,10 +117,10 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)int ftrace_update_ftrace_func (ftrace_func_t func) {int ret =__ftrace_modify_call ((unsigned long )&ftrace_call, - (unsigned long )func, true); + (unsigned long )func, true, true);if (!ret) { ret =__ftrace_modify_call ((unsigned long )&ftrace_regs_call, - (unsigned long )func, true); + (unsigned long )func, true, true); }return ret;@@ -159,16 +132,16 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr) {unsigned int call[2 ]; -unsigned long caller = rec->ip +FUNC_ENTRY_JMP ; +unsigned long caller = rec->ip;int ret; -make_call (caller, old_addr, call); +make_call_t0 (caller, old_addr, call); ret =ftrace_check_current_call (caller, call);if (ret)return ret; -return __ftrace_modify_call (caller, addr, true); +return __ftrace_modify_call (caller, addr, true, false); }#endif @@ -203,12 +176,12 @@ int ftrace_enable_ftrace_graph_caller(void)int ret; ret =__ftrace_modify_call ((unsigned long )&ftrace_graph_call, - (unsigned long )&prepare_ftrace_return, true); + (unsigned long )&prepare_ftrace_return, true, true);if (ret)return ret;return __ftrace_modify_call ((unsigned long )&ftrace_graph_regs_call, - (unsigned long )&prepare_ftrace_return, true); + (unsigned long )&prepare_ftrace_return, true, true); }int ftrace_disable_ftrace_graph_caller (void )@@ -216,12 +189,12 @@ int ftrace_disable_ftrace_graph_caller(void)int ret; ret =__ftrace_modify_call ((unsigned long )&ftrace_graph_call, - (unsigned long )&prepare_ftrace_return, false); + (unsigned long )&prepare_ftrace_return, false, true);if (ret)return ret;return __ftrace_modify_call ((unsigned long )&ftrace_graph_regs_call, - (unsigned long )&prepare_ftrace_return, false); + (unsigned long )&prepare_ftrace_return, false, true); }#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ arch/riscv/kernel/mcount-dyn.S +16
-27@@ -13,8 +13,8 @@ .text -#define FENTRY_RA_OFFSET 12 -#define ABI_SIZE_ON_STACK 72 +#define FENTRY_RA_OFFSET 8 +#define ABI_SIZE_ON_STACK 80 #define ABI_A0 0 #define ABI_A1 8 #define ABI_A2 16@@ -23,10 +23,10 @@ #define ABI_A5 40 #define ABI_A6 48 #define ABI_A7 56 -#define ABI_RA 64 +#define ABI_T0 64 +#define ABI_RA 72 .macro SAVE_ABI - addi sp, sp, -SZREG addi sp, sp, -ABI_SIZE_ON_STACK REG_S a0, ABI_A0(sp)@@ -37,6 +37,7 @@ REG_S a5, ABI_A5(sp) REG_S a6, ABI_A6(sp) REG_S a7, ABI_A7(sp) + REG_S t0, ABI_T0(sp) REG_S ra, ABI_RA(sp) .endm@@ -49,24 +50,18 @@ REG_L a5, ABI_A5(sp) REG_L a6, ABI_A6(sp) REG_L a7, ABI_A7(sp) + REG_L t0, ABI_T0(sp) REG_L ra, ABI_RA(sp) addi sp, sp, ABI_SIZE_ON_STACK - addi sp, sp, SZREG .endm #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS .macro SAVE_ALL - addi sp, sp, -SZREG addi sp, sp, -PT_SIZE_ON_STACK - REG_S x1, PT_EPC(sp) - addi sp, sp, PT_SIZE_ON_STACK - REG_L x1, (sp) - addi sp, sp, -PT_SIZE_ON_STACK + REG_S t0, PT_EPC(sp) REG_S x1, PT_RA(sp) - REG_L x1, PT_EPC(sp) - REG_S x2, PT_SP(sp) REG_S x3, PT_GP(sp) REG_S x4, PT_TP(sp)@@ -100,15 +95,11 @@ .endm .macro RESTORE_ALL + REG_L t0, PT_EPC(sp) REG_L x1, PT_RA(sp) - addi sp, sp, PT_SIZE_ON_STACK - REG_S x1, (sp) - addi sp, sp, -PT_SIZE_ON_STACK - REG_L x1, PT_EPC(sp) REG_L x2, PT_SP(sp) REG_L x3, PT_GP(sp) REG_L x4, PT_TP(sp) - REG_L x5, PT_T0(sp) REG_L x6, PT_T1(sp) REG_L x7, PT_T2(sp) REG_L x8, PT_S0(sp)@@ -137,17 +128,16 @@ REG_L x31, PT_T6(sp) addi sp, sp, PT_SIZE_ON_STACK - addi sp, sp, SZREG .endm #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ ENTRY(ftrace_caller) SAVE_ABI - addi a0, ra, -FENTRY_RA_OFFSET + addi a0, t0, -FENTRY_RA_OFFSET la a1, function_trace_op REG_L a2, 0(a1) - REG_L a1, ABI_SIZE_ON_STACK(sp) + mv a1, ra mv a3, sp ftrace_call:@@ -155,8 +145,8 @@ ftrace_call: call ftrace_stub #ifdef CONFIG_FUNCTION_GRAPH_TRACER - addi a0, sp, ABI_SIZE_ON_STACK - REG_L a1, ABI_RA(sp) + addi a0, sp, ABI_RA + REG_L a1, ABI_T0(sp) addi a1, a1, -FENTRY_RA_OFFSET #ifdef HAVE_FUNCTION_GRAPH_FP_TEST mv a2, s0@@ -166,17 +156,17 @@ ftrace_graph_call: call ftrace_stub #endif RESTORE_ABI - ret + jr t0 ENDPROC(ftrace_caller) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS ENTRY(ftrace_regs_caller) SAVE_ALL - addi a0, ra, -FENTRY_RA_OFFSET + addi a0, t0, -FENTRY_RA_OFFSET la a1, function_trace_op REG_L a2, 0(a1) - REG_L a1, PT_SIZE_ON_STACK(sp) + mv a1, ra mv a3, sp ftrace_regs_call:@@ -196,6 +186,6 @@ ftrace_graph_regs_call: #endif RESTORE_ALL - ret + jr t0 ENDPROC(ftrace_regs_caller) #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ --
Quoted 3 lines
2.36.1
Looks good to me.
I also re-checked if "replacement" of cmdline_proc_show() with a custom function via Ftrace works in this case - it does. Rollback to the original cmdline_proc_show() seems to work OK too.
Regards,
Evgenii
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v7 4/7 riscv: ftrace: Add ftrace_graph_func
In reply to [email protected]From: Song Shuai <[email protected]>
Here implements ftrace_graph_func as the function graph tracing function with FTRACE_WITH_REGS defined.
function_graph_func gets the point of the parent IP and the frame pointer from fregs and call prepare_ftrace_return for function graph tracing.
If FTRACE_WITH_REGS isn't defined, the enable/disable helpers of ftrace_graph_[regs]_call are revised for serving only ftrace_graph_call in the !FTRACE_WITH_REGS version ftrace_caller.
--- arch/riscv/include/asm/ftrace.h | 13 ++- arch/riscv/kernel/ftrace.c | 30 +++---- arch/riscv/kernel/mcount-dyn.S | 139 +++++++++++++++++++++++--------- 3 files changed, 126 insertions(+), 56 deletions(-)
arch/riscv/include/asm/ftrace.h +11 -2
@@ -107,8 +107,17 @@ do { \struct dyn_ftrace ;int ftrace_init_nop (struct module *mod,struct dyn_ftrace *rec);#define ftrace_init_nop ftrace_init_nop -#endif -#endif +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +struct ftrace_ops ; +struct ftrace_regs ; +void ftrace_graph_func (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct ftrace_regs *fregs); +#define ftrace_graph_func ftrace_graph_func +#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ + +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* _ASM_RISCV_FTRACE_H */
arch/riscv/kernel/ftrace.c +13 -17
@@ -169,32 +169,28 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, }#ifdef CONFIG_DYNAMIC_FTRACE +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +void ftrace_graph_func (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct ftrace_regs *fregs) +{ +struct pt_regs *regs =arch_ftrace_get_regs (fregs); +unsigned long *parent = (unsigned long *)®s->ra; + +prepare_ftrace_return (parent, ip,frame_pointer (regs)); +} +#else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ extern void ftrace_graph_call (void ); -extern void ftrace_graph_regs_call (void );int ftrace_enable_ftrace_graph_caller (void ) { -int ret; - - ret =__ftrace_modify_call ((unsigned long )&ftrace_graph_call, - (unsigned long )&prepare_ftrace_return, true, true); -if (ret) -return ret; - -return __ftrace_modify_call ((unsigned long )&ftrace_graph_regs_call, +return __ftrace_modify_call ((unsigned long )&ftrace_graph_call, (unsigned long )&prepare_ftrace_return, true, true); }int ftrace_disable_ftrace_graph_caller (void ) { -int ret; - - ret =__ftrace_modify_call ((unsigned long )&ftrace_graph_call, - (unsigned long )&prepare_ftrace_return, false, true); -if (ret) -return ret; - -return __ftrace_modify_call ((unsigned long )&ftrace_graph_regs_call, +return __ftrace_modify_call ((unsigned long )&ftrace_graph_call, (unsigned long )&prepare_ftrace_return, false, true); } +#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
arch/riscv/kernel/mcount-dyn.S +102 -37
194 lines not on this page · raw message
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v7 5/7 riscv: ftrace: Add DYNAMIC_FTRACE_WITH_DIRECT_CALLS support
In reply to [email protected]From: Song Shuai <[email protected]>
This patch adds DYNAMIC_FTRACE_WITH_DIRECT_CALLS support for RISC-V.
select the DYNAMIC_FTRACE_WITH_DIRECT_CALLS to provide the register_ftrace_direct[_multi] interfaces allowing users to register the customed trampoline (direct_caller) as the mcount for one or more target functions. And modify_ftrace_direct[_multi] are also provided for modifying direct_caller.
To make the direct_caller and the other ftrace hooks (eg. function/fgraph tracer, k[ret]probes) co-exist, a temporary register is nominated to store the address of direct_caller in ftrace_regs_caller. After the setting of the address direct_caller by direct_ops->func and the RESTORE_REGS in ftrace_regs_caller, direct_caller will be jumped to by the jr inst.
--- arch/riscv/Kconfig | 1 + arch/riscv/include/asm/ftrace.h | 8 ++++++++ arch/riscv/kernel/mcount-dyn.S | 4 ++++ 3 files changed, 13 insertions(+)
arch/riscv/Kconfig +1 -0
@@ -135,6 +135,7 @@ config RISCV select UACCESS_MEMCPY if !MMU select ZONE_DMA32 if 64BIT select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && $(cc-option,-fpatchable-function-entry=8) + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL select HAVE_FUNCTION_GRAPH_TRACER
arch/riscv/include/asm/ftrace.h +8 -0
@@ -114,6 +114,14 @@ struct ftrace_regs;void ftrace_graph_func (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op,struct ftrace_regs *fregs);#define ftrace_graph_func ftrace_graph_func + +static inline void +__arch_ftrace_set_direct_caller (struct pt_regs *regs,unsigned long addr) +{ + regs->t1 = addr; +} +#define arch_ftrace_set_direct_caller (fregs, addr) \ + __arch_ftrace_set_direct_caller(&(fregs)->regs, addr)#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ #endif /* __ASSEMBLY__ */
arch/riscv/kernel/mcount-dyn.S +4 -0
@@ -231,6 +231,7 @@ ENDPROC(ftrace_caller) #else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ ENTRY(ftrace_regs_caller) + move t1, zero SAVE_ABI_REGS 1 PREPARE_ARGS
@@ -239,7 +240,10 @@ ftrace_regs_call: call ftrace_stub RESTORE_ABI_REGS 1 + bnez t1,.Ldirect jr t0 +.Ldirect: + jr t1 ENDPROC(ftrace_regs_caller) ENTRY(ftrace_caller)
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v7 6/7 samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
In reply to [email protected]From: Song Shuai <[email protected]>
select HAVE_SAMPLE_FTRACE_DIRECT and HAVE_SAMPLE_FTRACE_DIRECT_MULTI for ARCH_RV64I in arch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files in samples/ftrace/.
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)
arch/riscv/Kconfig +2 -0
@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQ
samples/ftrace/ftrace-direct-modify.c +33 -0
@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h>
samples/ftrace/ftrace-direct-multi-modify.c +37 -0
@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h>
samples/ftrace/ftrace-direct-multi.c +22 -0
@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h>
samples/ftrace/ftrace-direct-too.c +26 -0
@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h>
samples/ftrace/ftrace-direct.c +22 -0
@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h>
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>
Quoted 8 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)
The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
migration/1-19 [001] ..... 3858.532131: my_direct_func1: my
direct func1 ip 0
migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my
direct func1 ip ff60000001ba9600
migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my
direct func1 ip ff60000003334d00
migration/0-15 [000] ..... 3858.532232: my_direct_func1: my
direct func1 ip 0
rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my
direct func1 ip 0
insmod-415 [000] ..... 3858.532270: my_direct_func1: my
direct func1 ip 7fffffffffffffff
<idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my
direct func1 ip ff60000001ba9600
<idle>-0 [001] dns2. 3858.539124: my_direct_func1: my
direct func1 ip ff60000001ba9600
rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: my direct func1 ip 0
[...]
If I understand it right, my_direct_func1() should print the address of some location in the code, probably - at the beginning of the traced functions.
The printed values (0x0, 0x7fffffffffffffff, ...) are not valid code addresses.
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 210 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-1@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> --
Quoted 3 lines
2.36.1
Regards,
Evgenii
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Hi, Evgenii:
Quoted 50 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 8 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]
Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.
The invalid code address is only printed by accessing the schedule() function's first argument whose address stores in a0 register. While schedule() actually has no parameter declared, so my_direct_func just prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.
I can't really understand why tracing the first argument of the schedule() function, but it seems nonsense at this point.
As for this patch, it just impls a simple mcount (direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do. so It shouldn't be blamed.
I started an independent patch to replace schedule with kick_process to make these samples more reasonable. And It has no conflict with the current patch, so we can go on.
Quoted 212 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 208 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64
Quoted 10 lines
Quoted 5 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
Regards,
Evgenii
--
Thanks,
Song
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Hi, Song,
Quoted 62 lines · Song Shuai
Hi, Evgenii:
Quoted 50 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 8 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.
Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.
The question is, what should be passed as the argument(s) of my_direct_func() in this particular sample module. The kernel docs and commit logs seem to contain no info on that.
With direct functions, I suppose, the trampoline can pass anything it wants to my_direct_func(), not just the arguments of the traced function.
I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
Quoted 224 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do. so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Quoted 212 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 208 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64
Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
Song
Regards,
Evgenii
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Quoted 72 lines · Evgenii Shatokhin
Hi, Song,
Quoted 69 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 17 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>---
arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++samples/ftrace/ftrace-direct-multi-modify.c| 37
+++++++++++++++++++++
samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++Quoted 1 line
6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | | migration/1-19 [001] ..... 3858.532131:my_direct_func1: my direct func1 ip 0
migration/0-15 [000] d.s2. 3858.532136:my_direct_func1: my direct func1 ipff60000001ba9600
migration/0-15 [000] d..2. 3858.532204:my_direct_func1: my direct func1 ipff60000003334d00
migration/0-15 [000] ..... 3858.532232:my_direct_func1: my direct func1 ip 0
rcu_sched-14 [001] ..... 3858.532257:my_direct_func1: my direct func1 ip 0
insmod-415 [000] ..... 3858.532270:my_direct_func1: my direct func1 ip7fffffffffffffff
<idle>-0 [001] ..s1. 3858.539051:my_direct_func1: my direct func1 ipff60000001ba9600
<idle>-0 [001] dns2. 3858.539124:my_direct_func1: my direct func1 ipff60000001ba9600
rcu_sched-14 [001] ..... 3858.539208:my_direct_func1: my direct func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.
Quoted 8 lines
Quoted 2 lines
I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to my_direct_func().
ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip
ffffffff87332f45 // wake_up_process+0x5
rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip
ffffffff8828d935 // schedule+0x5
insmod-10829 [000] ..... 1719.518708: my_direct_func: ip
ffffffff8828d935
systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip
ffffffff8828d935
systemd-1 [000] ..... 1719.519141: my_direct_func: ip
ffffffff8828d935
<idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip
ffffffff87332f45
<idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip
ffffffff87332f45
rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip ffffffff8828d935
[...]
The ip values are wake_up_process+0x5 and schedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to my_direct_func() in a0.
Quoted 234 lines
Quoted 225 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do. so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Quoted 212 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 208 lines
arch/riscv/Kconfig +0
-0@@ -112,6 +112,8 @@ config RISCVselect
HAVE_POSIX_CPU_TIMERS_TASK_WORK
selectHAVE_REGS_AND_STACK_ACCESS_API
selectHAVE_FUNCTION_ARG_ACCESS_API
+ selectHAVE_SAMPLE_FTRACE_DIRECT
+ selectHAVE_SAMPLE_FTRACE_DIRECT_MULTI
selectHAVE_STACKPROTECTOR
selectHAVE_SYSCALL_TRACEPOINTS
selectHAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *); static unsigned long my_ip = (unsigned long)schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ + #ifdef CONFIG_X86_64 #include <asm/ibt.h>samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip) extern void my_tramp1(void *); extern void my_tramp2(void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ + #ifdef CONFIG_X86_64 #include <asm/ibt.h>samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip) extern void my_tramp(void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ + #ifdef CONFIG_X86_64 #include <asm/ibt.h>samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma, extern void my_tramp(void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ + #ifdef CONFIG_X86_64 #include <asm/ibt.h>samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p) extern void my_tramp(void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ + #ifdef CONFIG_X86_64Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-0#include <asm/ibt.h>Signature · 1 line
2.36.1Signature · 2 lines
Thanks, Song
Quoted 2 lines
Regards,
Evgenii
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.
Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.
Yes, you're right.
I added 'mv a0,t0' in front of call my_direct_func to pass the address of traced function with mcount offset.
Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318
Quoted 246 lines
Quoted 244 lines
Quoted 233 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongRegards,
Evgenii
Signature · 2 lines
Thanks, Song
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.
Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318
Thank you for the quick fix. This one looks good to me.
ftrace-direct-multi*.ko now report the ip values corresponding to schedule+0x8 and wake_up_process+0x8, which is what was expected here.
One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 250 lines
Quoted 244 lines
Quoted 244 lines
Quoted 243 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongQuoted 4 lines
Quoted 2 lines
Regards,
Evgenii
Quoted 4 lines
--
Thanks,
Song
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Thx Evgenii & Song,
I got it; it would be put into v8.
Quoted 401 lines · Evgenii Shatokhin
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Thank you for the quick fix. This one looks good to me.
ftrace-direct-multi*.ko now report the ip values corresponding to
schedule+0x8andwake_up_process+0x8, which is what was expected here.One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 254 lines
Quoted 244 lines
Quoted 244 lines
Quoted 243 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongQuoted 4 lines
Quoted 2 lines
Regards,
Evgenii--
Thanks,
Song
Signature · 7 lines
Best Regards Guo Ren _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Palmer Dabbelt
maintainerRe: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Quoted 3 lines · On Wed, 18 Jan 2023 22:05:04 PST (-0800), [email protected] wrote:
Thx Evgenii & Song,
I got it; it would be put into v8.
Sorry if I missed it, but I don't see a v8 on patchwork. I queued up the first three patches onto for-next as they seem like pretty independent fixes/cleanups, I'll hold off on the others until v8.
Thanks!
Quoted 398 lines
Quoted 395 lines · Evgenii Shatokhin
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Thank you for the quick fix. This one looks good to me.
ftrace-direct-multi*.ko now report the ip values corresponding to
schedule+0x8andwake_up_process+0x8, which is what was expected here.One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 250 lines
Quoted 248 lines
Quoted 246 lines
Quoted 235 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongRegards,
Evgenii
Quoted 11 lines
Quoted 6 lines
Quoted 4 lines
--
Thanks,
SongSignature · 2 lines
Best Regards Guo Ren
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Hi,Guo:
Quoted 6 lines · Palmer Dabbelt <[email protected]> 于2023年2月18日周六 21:30写道:
Quoted 3 lines · On Wed, 18 Jan 2023 22:05:04 PST (-0800), [email protected] wrote:
Thx Evgenii & Song,
I got it; it would be put into v8.
There were 2 problems for this patch in its V6 and V7 version:
1. build error resulted by including of nospec-branch.h file in V6
- this common fixup patch had been sent to the linux-trace mail
list and would show up in Linux v6.3
- here is the link:
https://lore.kernel.org/lkml/[email protected]/
2. invalid code address reported by Evgenii in V7
- for your convenience, the link to this updated patch is
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318
Is it time to launch the V8 with this updated patch, or waiting for the common fixup patch to be merged?
Quoted 415 lines
Sorry if I missed it, but I don't see a v8 on patchwork. I queued up the first three patches onto for-next as they seem like pretty independent fixes/cleanups, I'll hold off on the others until v8.
Thanks!
Quoted 409 lines
Quoted 137 lines · Evgenii Shatokhin
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Thank you for the quick fix. This one looks good to me.
Quoted 264 lines
ftrace-direct-multi*.ko now report the ip values corresponding to
schedule+0x8andwake_up_process+0x8, which is what was expected here.One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 254 lines
Quoted 244 lines
Quoted 244 lines
Quoted 243 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongQuoted 4 lines
Quoted 2 lines
Regards,
Evgenii--
Thanks,
Song--
Best Regards
Guo Ren
Signature · 7 lines
Thanks, Song _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
Quoted 18 lines · Song Shuai
Hi,Guo:
Quoted 6 lines · Palmer Dabbelt <[email protected]> 于2023年2月18日周六 21:30写道:
Quoted 3 lines · On Wed, 18 Jan 2023 22:05:04 PST (-0800), [email protected] wrote:
Thx Evgenii & Song,
I got it; it would be put into v8.
There were 2 problems for this patch in its V6 and V7 version:
1. build error resulted by including of
nospec-branch.hfile in V6
- this common fixup patch had been sent to the linux-trace mail
list and would show up in Linux v6.3
- here is the link:
https://lore.kernel.org/lkml/[email protected]/
Quoted 6 lines
2. invalid code address reported by Evgenii in V7
- for your convenience, the link to this updated patch is
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Is it time to launch the V8 with this updated patch, or waiting for the common fixup patch to be merged?
I don't know.
I've made v8 based on the newest remotes/palmer/for-next with your newest branch:
https://github.com/guoren83/linux/tree/ftrace_fixup_v8
I fixed some conflicts with the palmer/for-next, You could send them any time.
Quoted 422 lines
Quoted 416 lines
Sorry if I missed it, but I don't see a v8 on patchwork. I queued up the first three patches onto for-next as they seem like pretty independent fixes/cleanups, I'll hold off on the others until v8.
Thanks!
Quoted 409 lines
Quoted 137 lines · Evgenii Shatokhin
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Thank you for the quick fix. This one looks good to me.
Quoted 264 lines
ftrace-direct-multi*.ko now report the ip values corresponding to
schedule+0x8andwake_up_process+0x8, which is what was expected here.One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 254 lines
Quoted 244 lines
Quoted 244 lines
Quoted 243 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongQuoted 4 lines
Quoted 2 lines
Regards,
Evgenii--
Thanks,
Song--
Best Regards
Guo Ren--
Thanks,
Song
Signature · 7 lines
Best Regards Guo Ren _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Re: [PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]
In reply to Palmer DabbeltQuoted 9 lines · Palmer Dabbelt
Quoted 3 lines · On Wed, 18 Jan 2023 22:05:04 PST (-0800), [email protected] wrote:
Thx Evgenii & Song,
I got it; it would be put into v8.
Sorry if I missed it, but I don't see a v8 on patchwork. I queued up the first three patches onto for-next as they seem like pretty independent fixes/cleanups, I'll hold off on the others until v8.
Thx for approving. I would keep the patch series more independent next time.
Quoted 412 lines
Thanks!
Quoted 409 lines
Quoted 137 lines · Evgenii Shatokhin
Quoted 125 lines · Song Shuai
Quoted 116 lines · Evgenii Shatokhin <[email protected]> 于2023年1月17日周二 16:22写道:
Quoted 79 lines · Evgenii Shatokhin
Hi, Song,
Quoted 63 lines · Song Shuai
Hi, Evgenii:
Quoted 51 lines · Evgenii Shatokhin <[email protected]> 于2023年1月16日周一 14:30写道:
Hi,
Quoted 9 lines · On 12.01.2023 12:06, [email protected] wrote:
From: Song Shuai <[email protected]>
select
HAVE_SAMPLE_FTRACE_DIRECTandHAVE_SAMPLE_FTRACE_DIRECT_MULTIforARCH_RV64Iinarch/riscv/Kconfig. And add riscv asm code for the ftrace-direct*.c files insamples/ftrace/.Signed-off-by Song Shuai <[email protected]>Tested-by Guo Ren <[email protected]>Signed-off-by Guo Ren <[email protected]>Quoted 9 lines
--- arch/riscv/Kconfig | 2 ++ samples/ftrace/ftrace-direct-modify.c | 33 ++++++++++++++++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 +++++++++++++++++++++ samples/ftrace/ftrace-direct-multi.c | 22 ++++++++++++ samples/ftrace/ftrace-direct-too.c | 26 +++++++++++++++ samples/ftrace/ftrace-direct.c | 22 ++++++++++++ 6 files changed, 142 insertions(+)The samples were built OK now, but ftrace-direct-multi and ftrace-direct-multi-modify report incorrect values of ip/pc it seems.
I ran 'insmod ftrace-direct-multi.ko', waited a little and then checked the messages in the trace:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | migration/1-19 [001] ..... 3858.532131: my_direct_func1: my direct func1 ip 0 migration/0-15 [000] d.s2. 3858.532136: my_direct_func1: my direct func1 ip ff60000001ba9600 migration/0-15 [000] d..2. 3858.532204: my_direct_func1: my direct func1 ip ff60000003334d00 migration/0-15 [000] ..... 3858.532232: my_direct_func1: my direct func1 ip 0 rcu_sched-14 [001] ..... 3858.532257: my_direct_func1: my direct func1 ip 0 insmod-415 [000] ..... 3858.532270: my_direct_func1: my direct func1 ip 7fffffffffffffff <idle>-0 [001] ..s1. 3858.539051: my_direct_func1: my direct func1 ip ff60000001ba9600 <idle>-0 [001] dns2. 3858.539124: my_direct_func1: my direct func1 ip ff60000001ba9600 rcu_sched-14 [001] ..... 3858.539208: my_direct_func1: mydirect func1 ip 0
[...]Quoted 7 lines
If I understand it right,
my_direct_func1()should print the address of some location in the code, probably - at the beginning of the traced functions.The printed values (
0x0,0x7fffffffffffffff, ...) are not valid code addresses.Quoted 8 lines
The invalid code address is only printed by accessing the
schedule()function's first argument whose address stores in a0 register. Whileschedule()actually has no parameter declared, somy_direct_funcjust prints the a0 in the context of the schedule()'s caller and the address maybe varies depending on the caller.I can't really understand why tracing the first argument of the
schedule()function, but it seems nonsense at this point.The question is, what should be passed as the argument(s) of
my_direct_func()in this particular sample module. The kernel docs and commit logs seem to contain no info on that.Quoted 5 lines
With direct functions, I suppose, the trampoline can pass anything it wants to
my_direct_func(), not just the arguments of the traced function.I'd check what these sample modules do on x86 and would try to match that behaviour on RISC-V.
I have checked ftrace-direct-multi.ko and ftrace-direct-multi-modify.ko on 6.2-rc4 built for x86-64 - yes, ip/pc in the traced function should be passed to
my_direct_func().ftrace-direct-multi.ko:
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | insmod-10829 [000] d.h1. 1719.518535: my_direct_func: ip ffffffff87332f45 // wake_up_process+0x5 rcu_tasks_kthre-11 [000] ..... 1719.518696: my_direct_func: ip ffffffff8828d935 // schedule+0x5 insmod-10829 [000] ..... 1719.518708: my_direct_func: ip ffffffff8828d935 systemd-journal-293 [001] ..... 1719.518823: my_direct_func: ip ffffffff8828d935 systemd-1 [000] ..... 1719.519141: my_direct_func: ip ffffffff8828d935 <idle>-0 [001] ..s1. 1719.521889: my_direct_func: ip ffffffff87332f45 <idle>-0 [000] d.s2. 1719.521901: my_direct_func: ip ffffffff87332f45 rcu_preempt-15 [001] ..... 1719.521917: my_direct_func: ip
ffffffff8828d935
[...]The ip values are
wake_up_process+0x5andschedule+0x5, the locations where the execution of the traced functions resumes after the Ftrace trampoline has finished.Quoted 7 lines
The results with ftrace-direct-multi-modify.ko are similar to that.
The samples look like a demonstration, that one can pass anything necessary to the handler in case of "direct" functions.
I suppose, the RISC-V-specific asm code in these two sample modules could be updated to pass the saved pc value to
my_direct_func()in a0.Quoted 7 lines
Yes, you're right.
I added 'mv a0,t0' in front of
call my_direct_functo pass the address of traced function with mcount offset.Here is the updated patch for your reference.
https://github.com/sugarfillet/linux/commit/95b174fb104dd970b982ee6fa19879393e229318Thank you for the quick fix. This one looks good to me.
Quoted 264 lines
ftrace-direct-multi*.ko now report the ip values corresponding to
schedule+0x8andwake_up_process+0x8, which is what was expected here.One more thing: please change my "Co-developed-by:" into "Tested-by:" in your patch, becase this is what I actually did: tested it and reported the results. I cannot take your credit for development of this patch ;-)
Looking forward for v8 of the series.
Quoted 254 lines
Quoted 244 lines
Quoted 244 lines
Quoted 243 lines
As for this patch, it just impls a simple mcount (
direct_caller) to trace kernel functions, and basically saves the necessary ABI, call the tracing function, and restores the ABI, just like other arches do.
so It shouldn't be blamed.I started an independent patch to replace schedule with
kick_processto make these samples more reasonable. And It has no conflict with the current patch, so we can go on.Link:
https://lore.kernel.org/linux-kernel/[email protected]/T/#uQuoted 217 lines
The same issue is with ftrace-direct-multi-modify.ko.
Is anything missing here?
Quoted 213 lines
arch/riscv/Kconfig +2
-0@@ -112,6 +112,8 @@ config RISCV select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_RSEQsamples/ftrace/ftrace-direct-modify.c +33
-0@@ -23,6 +23,39 @@ extern void my_tramp2(void *);static unsigned long my_ip = (unsigned long )schedule; +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func1\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-16\n" +" sd t0,0(sp)\n" +" sd ra,8(sp)\n" +" call my_direct_func2\n" +" ld t0,0(sp)\n" +" ld ra,8(sp)\n" +" addi sp,sp,16\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi-modify.c +37
-0@@ -21,6 +21,43 @@ void my_direct_func2(unsigned long ip)extern void my_tramp1 (void *);extern void my_tramp2 (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func1\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func2\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-multi.c +22
-0@@ -16,6 +16,28 @@ void my_direct_func(unsigned long ip)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct-too.c +26
-0@@ -18,6 +18,32 @@ void my_direct_func(struct vm_area_struct *vma,extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-40\n" +" sd a0,0(sp)\n" +" sd a1,8(sp)\n" +" sd a2,16(sp)\n" +" sd t0,24(sp)\n" +" sd ra,32(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld a1,8(sp)\n" +" ld a2,16(sp)\n" +" ld t0,24(sp)\n" +" ld ra,32(sp)\n" +" addi sp,sp,40\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 #include <asm/ibt.h> samples/ftrace/ftrace-direct.c +22
-0@@ -15,6 +15,28 @@ void my_direct_func(struct task_struct *p)extern void my_tramp (void *); +#ifdef CONFIG_RISCV + +asm (" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" addi sp,sp,-24\n" +" sd a0,0(sp)\n" +" sd t0,8(sp)\n" +" sd ra,16(sp)\n" +" call my_direct_func\n" +" ld a0,0(sp)\n" +" ld t0,8(sp)\n" +" ld ra,16(sp)\n" +" addi sp,sp,24\n" +" jr t0\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_RISCV */ +#ifdef CONFIG_X86_64 Quoted 3 lines
Quoted 3 lines
samples/ftrace/ftrace-direct.c +0
-1#include <asm/ibt.h> --2.36.1
--
Thanks,
SongQuoted 4 lines
Quoted 2 lines
Regards,
Evgenii--
Thanks,
Song--
Best Regards
Guo Ren
Signature · 2 lines
Best Regards Guo Ren
PATCH v7 7/7 riscv : select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
In reply to [email protected]From: Song Shuai <[email protected]>
In RISC-V, -fpatchable-function-entry option is used to support dynamic ftrace in this commit afc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT"). So recordmcount don't have to be called to create the __mcount_loc section before the vmlinux linking.
Here selects FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY to tell Makefile not to run recordmcount.
--- arch/riscv/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/riscv/Kconfig +1 -0
@@ -54,6 +54,7 @@ config RISCV select COMMON_CLK select CPU_PM if CPU_IDLE select EDAC_SUPPORT + select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY if DYNAMIC_FTRACE select GENERIC_ARCH_TOPOLOGY select GENERIC_ATOMIC64 if !64BIT select GENERIC_CLOCKEVENTS_BROADCAST if SMP
Signature · 7 lines
2.36.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Hi,
Quoted 8 lines · On 12.01.2023 12:05, [email protected] wrote:
From: Guo Ren <[email protected]>
The previous ftrace detour implementation
fc76b8b8011("riscv: UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT") contain three problems.- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
It seems, the patches #2-#7 of this series do not require "riscv: ftrace: Fixup panic by disabling preemption" and can be used without it.
How about moving that patch out of the series and processing it separately?
As it was pointed out in the discussion of that patch, some other solution to non-atomic changes of the prologue might be needed anyway.
Quoted 230 lines
- The "-fpatchable-function-entry= CFLAG" wasted code size
!RISCV_ISA_C.- The ftrace detour implementation wasted code size.
- When livepatching, the trampoline (ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_Lra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result. (Found by Evgenii Shatokhin [4])Patches 1,2,3 fixup above problems.
Patches 4,5,6,7 are the features based on reduced detour code patch, we include them in the series for test and maintenance.
You can directly try it with:
https://github.com/guoren83/linux/tree/ftrace_fixup_v7Make function graph use ftrace directly [2] (patch 4, 5)
========================================================In RISC-V architecture, when we enable the
ftrace_graphtracer on some functions, the function tracings on other functions will suffer extra graph tracing work. In essence,graph_opsisn't limited by itsfunc_hashdue to the global ftrace_graph_[regs]_call label. That should be corrected.What inspires me is the commit
0c0593b45c9b("x86/ftrace: Make function graph use ftrace directly") that usesgraph_ops::funcfunction to installreturn_hookerand makes the function called against itsfunc_hash.This series of patches makes function graph use ftrace directly for riscv.
If
FTRACE_WITH_REGSisn't defined,ftrace_callerkeepsftrace_graph_callso that it can be replaced with the calling ofprepare_ftrace_returnby the enable/disable helper.As for defining
FTRACE_WITH_REGS,ftrace_calleris adjusted to save the necessary regs against thept_regslayout, so it can reasonably call thegraph_ops::funcfunction -ftrace_graph_func. And ftrace_graph_[regs]_call
and its enable/disable helper aren't needed.Test log:
The tests generated by
CONFIG_FTRACE_STARTUP_TESThave passed in the local
qemu-system-riscv64 virt machine. The following is the log during startup.``` Nov 15 03:07:13 stage4 kernel: Testing tracer function: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #1: Nov 15 03:07:13 stage4 kernel: (1 0 1 0 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 0 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 0 365) Nov 15 03:07:13 stage4 kernel: (2 2 4 0 399) Nov 15 03:07:13 stage4 kernel: (3 2 4 0 146071) Nov 15 03:07:13 stage4 kernel: (3 3 5 0 146105) PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #2: Nov 15 03:07:13 stage4 kernel: (1 0 1 589 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 635 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 1 2) Nov 15 03:07:13 stage4 kernel: (2 2 4 125 126) Nov 15 03:07:13 stage4 kernel: (3 2 4 146001 146078) Nov 15 03:07:13 stage4 kernel: (3 3 5 146035 146112) PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion safe: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace regs: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer nop: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer irqsoff: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup: Nov 15 03:07:13 stage4 kernel: sched: DL replenish lagged too much Nov 15 03:07:13 stage4 kernel: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_rt: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_dl: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer function_graph: PASSED ```Add
WITH_DIRECT_CALLSsupport [3] (patch 6, 7)
==============================================This series adds
DYNAMIC_FTRACE_WITH_DIRECT_CALLSsupport for RISC-V.SAMPLE_FTRACE_DIRECTandSAMPLE_FTRACE_DIRECT_MULTIare also included here as the samples for testingDIRECT_CALLSrelated interface.First, select the
DYNAMIC_FTRACE_WITH_DIRECT_CALLSto provide register_ftrace_direct[_multi] interfaces allowing user to register the customed trampoline (direct_caller) as the mcount for one or more target functions. And modify_ftrace_direct[_multi] are also provided for modifydirect_caller.At the same time, the samples in
./samples/ftrace/can be built as kerenl module for testing these interfaces withSAMPLE_FTRACE_DIRECTandSAMPLE_FTRACE_DIRECT_MULTIselected.Second, to make the
direct_callerand the other ftrace hooks (eg. function/fgraph tracer, k[ret]probes) co-exist, a temporary register
are nominated to store the address ofdirect_callerinftrace_regs_caller.
After the setting of the addressdirect_callerbydirect_ops->funcand theRESTORE_REGSinftrace_regs_caller,direct_callerwill be jumped to by thejrinst.The following tests have been passed in my local qemu-riscv64 virt machine.
1. tests with
CONFIG_FTRACE_STARTUP_TEST
2. tests ofsamples/ftrace/ftrace*.ko
3. manual tests with any combination of the following hooks
- function/function_graph tracer
- ftrace*.ko
- kprobe/kretprobeFor your reference, here is the log when function tracer, kretprobe and ftrace-direct-too.ko co-hooks the
handle_mm_faultfunction.``` [root@stage4 tracing]# echo handle_mm_fault > set_ftrace_filter [root@stage4 tracing]# echo 'r:myr handle_mm_fault' > kprobe_events [root@stage4 tracing]# echo function > current_tracer [root@stage4 tracing]# echo 1 > events/kprobes/myr/enable [root@stage4 tracing]# insmod /root/ftrace-direct-too.ko [root@stage4 tracing]# [root@stage4 tracing]# cat trace | tail cat-388 [000] ...1. 583.051438: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) cat-388 [000] ...2. 583.057930: handle_mm_fault <-do_page_fault cat-388 [000] ..... 583.057990: my_direct_func: handle mm fault vma=000000002d9fe19c address=ffffffae9b7000 flags=215 cat-388 [000] ...1. 583.058284: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) tail-389 [001] ...2. 583.059062: handle_mm_fault <-do_page_fault tail-389 [001] ..... 583.059104: my_direct_func: handle mm fault vma=0000000017f3c48e address=aaaaaabebf3000 flags=215 tail-389 [001] ...1. 583.059325: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) tail-389 [001] ...2. 583.060371: handle_mm_fault <-do_page_fault tail-389 [001] ..... 583.060410: my_direct_func: handle mm fault vma=0000000017f3c48e address=aaaaaabebf1000 flags=255 tail-389 [001] ...1. 583.060996: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) ```Note1:
The checkpatch.pl will output some warnings on this series, like this
``` WARNING: Prefer using '"%s...", __func__' to using 'my_direct_func2', this function's name, in a string 111: FILE: samples/ftrace/ftrace-direct-multi-modify.c:48: +" call my_direct_func2\n" ```The reason is that checkpatch depends on patch context providing the function name. In the above warning,
my_direct_func2has some codeline distance with the changed trunk, so its declaration doesn't come into the patch, and then the warning jumps out.You may notice the location of
my_ipvariable changes in the 2nd patch. I did that for reducing the warnings to some extent. But killing all the warnings will makes the patch less readable, so I stopped here.[1] https://lpc.events/event/16/contributions/1171/
[2] https://lore.kernel.org/lkml/[email protected]/
[3] https://lore.kernel.org/linux-riscv/[email protected]/
[4] https://lore.kernel.org/linux-riscv/[email protected]/Changes in v7:
- FixupRESTORE_ABI_REGSby removePT_T0(sp)overwrite.
- AddFTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
- Fixup kconfig withHAVE_SAMPLE_FTRACE_DIRECT&HAVE_SAMPLE_FTRACE_DIRECT_MULTIChanges in v6:
https://lore.kernel.org/linux-riscv/[email protected]/
- Replace 8 withMCOUNT_INSN_SIZE
- Replace "REG_La1,PT_RA(sp)" with "mv a1, ra"
- Add Evgenii Shatokhin commentChanges in v5:
https://lore.kernel.org/linux-riscv/[email protected]/
- SortKconfigentries in alphabetical order.Changes in v4:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [3] for maintenance. [Song Shuai]Changes in V3:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [2] for maintenance. [Song Shuai]Changes in V2:
https://lore.kernel.org/linux-riscv/[email protected]/
- Add Signed-off for preemption fixup.Changes in V1:
https://lore.kernel.org/linux-riscv/[email protected]/Andy Chiu (1):
riscv: ftrace: Fixup panic by disabling preemptionGuo Ren (2):
riscv: ftrace: Remove wasted nops for !RISCV_ISA_C
riscv: ftrace: Reduce the detour code size to halfSong Shuai (4):
riscv: ftrace: Addftrace_graph_func
riscv: ftrace: AddDYNAMIC_FTRACE_WITH_DIRECT_CALLSsupport
samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI] riscv : selectFTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRYarch/riscv/Kconfig | 6 +- arch/riscv/Makefile | 6 +- arch/riscv/include/asm/ftrace.h | 71 ++++++-- arch/riscv/kernel/ftrace.c | 91 ++++------ arch/riscv/kernel/mcount-dyn.S | 179 +++++++++++++------- samples/ftrace/ftrace-direct-modify.c | 33 ++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 ++++ samples/ftrace/ftrace-direct-multi.c | 22 +++ samples/ftrace/ftrace-direct-too.c | 26 +++ samples/ftrace/ftrace-direct.c | 22 +++ 10 files changed, 356 insertions(+), 137 deletions(-)
Quoted 4 lines
--
2.36.1
I tested this series a bit on top of 6.2-rc4, with https://github.com/sugarfillet/linux/commit/9539a80dc6e7d1137ec7a96ebef2ab912a694bd7.patch added.
The kernel was built with CONFIG_DYNAMIC_FTRACE_WITH_REGS=y and CONFIG_RISCV_ISA_C=y.
Here are some results:
* The kernel was built without visible issues.
* Most of the Ftrace startup tests ran and passed. Certain event-specific tests caused soft lockups in one of the test runs but they are likely unrelated to this patchset and could happen without it too.
* "function" and "function_graph" tracers worked in my simple use cases.
* "ipmodify" functionality worked.
* kprobe sample modules worked OK, which is good, because they actually use Ftrace: they plant the probes at the beginning of the resp. functions.
* ftrace-direct-multi and ftrace-direct-multi-modify sample modules reported possibly invalid data. More info - in my reply to "[PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]"
Regards,
Evgenii
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 9 lines · Evgenii Shatokhin
Hi,
Quoted 5 lines · On 12.01.2023 12:05, [email protected] wrote:
From: Guo Ren <[email protected]>
The previous ftrace detour implementation
fc76b8b8011("riscv: UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT") contain three problems.
Quoted 8 lines
Quoted 3 lines
- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
It seems, the patches #2-#7 of this series do not require "riscv:
ftrace: Fixup panic by disabling preemption" and can be used without it.How about moving that patch out of the series and processing it separately?
Okay.
Quoted 3 lines
As it was pointed out in the discussion of that patch, some other solution to non-atomic changes of the prologue might be needed anyway.
I think you mean Mark Rutland's DYNAMIC_FTRACE_WITH_CALL_OPS. But that still needs to be ready. Let's disable PREEMPT for ftrace first.
Quoted 251 lines
Quoted 231 lines
- The "-fpatchable-function-entry= CFLAG" wasted code size
!RISCV_ISA_C.- The ftrace detour implementation wasted code size.
- When livepatching, the trampoline (ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_Lra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result. (Found by Evgenii Shatokhin [4])Patches 1,2,3 fixup above problems.
Patches 4,5,6,7 are the features based on reduced detour code patch, we include them in the series for test and maintenance.
You can directly try it with:
https://github.com/guoren83/linux/tree/ftrace_fixup_v7Make function graph use ftrace directly [2] (patch 4, 5)
========================================================In RISC-V architecture, when we enable the
ftrace_graphtracer on some functions, the function tracings on other functions will suffer extra graph tracing work. In essence,graph_opsisn't limited by itsfunc_hashdue to the global ftrace_graph_[regs]_call label. That should be corrected.What inspires me is the commit
0c0593b45c9b("x86/ftrace: Make function graph use ftrace directly") that usesgraph_ops::funcfunction to installreturn_hookerand makes the function called against itsfunc_hash.This series of patches makes function graph use ftrace directly for riscv.
If
FTRACE_WITH_REGSisn't defined,ftrace_callerkeepsftrace_graph_callso that it can be replaced with the calling ofprepare_ftrace_returnby the enable/disable helper.As for defining
FTRACE_WITH_REGS,ftrace_calleris adjusted to save the necessary regs against thept_regslayout, so it can reasonably call thegraph_ops::funcfunction -ftrace_graph_func. And ftrace_graph_[regs]_call
and its enable/disable helper aren't needed.Test log:
The tests generated by
CONFIG_FTRACE_STARTUP_TESThave passed in the local
qemu-system-riscv64 virt machine. The following is the log during startup.``` Nov 15 03:07:13 stage4 kernel: Testing tracer function: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace: PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #1: Nov 15 03:07:13 stage4 kernel: (1 0 1 0 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 0 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 0 365) Nov 15 03:07:13 stage4 kernel: (2 2 4 0 399) Nov 15 03:07:13 stage4 kernel: (3 2 4 0 146071) Nov 15 03:07:13 stage4 kernel: (3 3 5 0 146105) PASSED Nov 15 03:07:13 stage4 kernel: Testing dynamic ftrace ops #2: Nov 15 03:07:13 stage4 kernel: (1 0 1 589 0) Nov 15 03:07:13 stage4 kernel: (1 1 2 635 0) Nov 15 03:07:13 stage4 kernel: (2 1 3 1 2) Nov 15 03:07:13 stage4 kernel: (2 2 4 125 126) Nov 15 03:07:13 stage4 kernel: (3 2 4 146001 146078) Nov 15 03:07:13 stage4 kernel: (3 3 5 146035 146112) PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace recursion safe: PASSED Nov 15 03:07:13 stage4 kernel: Testing ftrace regs: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer nop: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer irqsoff: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup: Nov 15 03:07:13 stage4 kernel: sched: DL replenish lagged too much Nov 15 03:07:13 stage4 kernel: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_rt: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer wakeup_dl: PASSED Nov 15 03:07:13 stage4 kernel: Testing tracer function_graph: PASSED ```Add
WITH_DIRECT_CALLSsupport [3] (patch 6, 7)
==============================================This series adds
DYNAMIC_FTRACE_WITH_DIRECT_CALLSsupport for RISC-V.SAMPLE_FTRACE_DIRECTandSAMPLE_FTRACE_DIRECT_MULTIare also included here as the samples for testingDIRECT_CALLSrelated interface.First, select the
DYNAMIC_FTRACE_WITH_DIRECT_CALLSto provide register_ftrace_direct[_multi] interfaces allowing user to register the customed trampoline (direct_caller) as the mcount for one or more target functions. And modify_ftrace_direct[_multi] are also provided for modifydirect_caller.At the same time, the samples in
./samples/ftrace/can be built as kerenl module for testing these interfaces withSAMPLE_FTRACE_DIRECTandSAMPLE_FTRACE_DIRECT_MULTIselected.Second, to make the
direct_callerand the other ftrace hooks (eg. function/fgraph tracer, k[ret]probes) co-exist, a temporary register
are nominated to store the address ofdirect_callerinftrace_regs_caller.
After the setting of the addressdirect_callerbydirect_ops->funcand theRESTORE_REGSinftrace_regs_caller,direct_callerwill be jumped to by thejrinst.The following tests have been passed in my local qemu-riscv64 virt machine.
1. tests with
CONFIG_FTRACE_STARTUP_TEST
2. tests ofsamples/ftrace/ftrace*.ko
3. manual tests with any combination of the following hooks
- function/function_graph tracer
- ftrace*.ko
- kprobe/kretprobeFor your reference, here is the log when function tracer, kretprobe and ftrace-direct-too.ko co-hooks the
handle_mm_faultfunction.``` [root@stage4 tracing]# echo handle_mm_fault > set_ftrace_filter [root@stage4 tracing]# echo 'r:myr handle_mm_fault' > kprobe_events [root@stage4 tracing]# echo function > current_tracer [root@stage4 tracing]# echo 1 > events/kprobes/myr/enable [root@stage4 tracing]# insmod /root/ftrace-direct-too.ko [root@stage4 tracing]# [root@stage4 tracing]# cat trace | tail cat-388 [000] ...1. 583.051438: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) cat-388 [000] ...2. 583.057930: handle_mm_fault <-do_page_fault cat-388 [000] ..... 583.057990: my_direct_func: handle mm fault vma=000000002d9fe19c address=ffffffae9b7000 flags=215 cat-388 [000] ...1. 583.058284: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) tail-389 [001] ...2. 583.059062: handle_mm_fault <-do_page_fault tail-389 [001] ..... 583.059104: my_direct_func: handle mm fault vma=0000000017f3c48e address=aaaaaabebf3000 flags=215 tail-389 [001] ...1. 583.059325: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) tail-389 [001] ...2. 583.060371: handle_mm_fault <-do_page_fault tail-389 [001] ..... 583.060410: my_direct_func: handle mm fault vma=0000000017f3c48e address=aaaaaabebf1000 flags=255 tail-389 [001] ...1. 583.060996: myr: (do_page_fault+0x16c/0x5f2 <- handle_mm_fault) ```Note1:
The checkpatch.pl will output some warnings on this series, like this
``` WARNING: Prefer using '"%s...", __func__' to using 'my_direct_func2', this function's name, in a string 111: FILE: samples/ftrace/ftrace-direct-multi-modify.c:48: +" call my_direct_func2\n" ```The reason is that checkpatch depends on patch context providing the function name. In the above warning,
my_direct_func2has some codeline distance with the changed trunk, so its declaration doesn't come into the patch, and then the warning jumps out.You may notice the location of
my_ipvariable changes in the 2nd patch. I did that for reducing the warnings to some extent. But killing all the warnings will makes the patch less readable, so I stopped here.[1] https://lpc.events/event/16/contributions/1171/
[2] https://lore.kernel.org/lkml/[email protected]/
[3] https://lore.kernel.org/linux-riscv/[email protected]/
[4] https://lore.kernel.org/linux-riscv/[email protected]/Changes in v7:
- FixupRESTORE_ABI_REGSby removePT_T0(sp)overwrite.
- AddFTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
- Fixup kconfig withHAVE_SAMPLE_FTRACE_DIRECT&HAVE_SAMPLE_FTRACE_DIRECT_MULTIChanges in v6:
https://lore.kernel.org/linux-riscv/[email protected]/
- Replace 8 withMCOUNT_INSN_SIZE
- Replace "REG_La1,PT_RA(sp)" with "mv a1, ra"
- Add Evgenii Shatokhin commentChanges in v5:
https://lore.kernel.org/linux-riscv/[email protected]/
- SortKconfigentries in alphabetical order.Changes in v4:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [3] for maintenance. [Song Shuai]Changes in V3:
https://lore.kernel.org/linux-riscv/[email protected]/
- Include [2] for maintenance. [Song Shuai]Changes in V2:
https://lore.kernel.org/linux-riscv/[email protected]/
- Add Signed-off for preemption fixup.Changes in V1:
https://lore.kernel.org/linux-riscv/[email protected]/Andy Chiu (1):
riscv: ftrace: Fixup panic by disabling preemptionGuo Ren (2):
riscv: ftrace: Remove wasted nops for !RISCV_ISA_C
riscv: ftrace: Reduce the detour code size to halfSong Shuai (4):
riscv: ftrace: Addftrace_graph_func
riscv: ftrace: AddDYNAMIC_FTRACE_WITH_DIRECT_CALLSsupport
samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI] riscv : selectFTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRYarch/riscv/Kconfig | 6 +- arch/riscv/Makefile | 6 +- arch/riscv/include/asm/ftrace.h | 71 ++++++-- arch/riscv/kernel/ftrace.c | 91 ++++------ arch/riscv/kernel/mcount-dyn.S | 179 +++++++++++++------- samples/ftrace/ftrace-direct-modify.c | 33 ++++ samples/ftrace/ftrace-direct-multi-modify.c | 37 ++++ samples/ftrace/ftrace-direct-multi.c | 22 +++ samples/ftrace/ftrace-direct-too.c | 26 +++ samples/ftrace/ftrace-direct.c | 22 +++ 10 files changed, 356 insertions(+), 137 deletions(-)Quoted 4 lines
--
2.36.1I tested this series a bit on top of 6.2-rc4, with
https://github.com/sugarfillet/linux/commit/9539a80dc6e7d1137ec7a96ebef2ab912a694bd7.patch
added.The kernel was built with
CONFIG_DYNAMIC_FTRACE_WITH_REGS=yandCONFIG_RISCV_ISA_C=y.Here are some results:
* The kernel was built without visible issues.
* Most of the Ftrace startup tests ran and passed. Certain event-specific tests caused soft lockups in one of the test runs but they are likely unrelated to this patchset and could happen without it too.
Quoted 6 lines
* "function" and "
function_graph" tracers worked in my simple use cases.* "ipmodify" functionality worked.
* kprobe sample modules worked OK, which is good, because they actually use Ftrace: they plant the probes at the beginning of the resp. functions.
Thx for test
Quoted 5 lines
* ftrace-direct-multi and ftrace-direct-multi-modify sample modules reported possibly invalid data. More info - in my reply to "[PATCH -next V7 6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI]"
Good report! We will solve it in the next version.
Quoted 4 lines
Regards,
Evgenii
--
Best Regards
Guo Ren
Mark Rutland
reviewerQuoted 18 lines · Guo Ren
Quoted 16 lines · Evgenii Shatokhin
Hi,
Quoted 8 lines · On 12.01.2023 12:05, [email protected] wrote:
From: Guo Ren <[email protected]>
The previous ftrace detour implementation
fc76b8b8011("riscv: UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT") contain three problems.- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
It seems, the patches #2-#7 of this series do not require "riscv:
ftrace: Fixup panic by disabling preemption" and can be used without it.
Quoted 8 lines
Quoted 1 line
How about moving that patch out of the series and processing it separately?
Okay.
Quoted 3 lines
As it was pointed out in the discussion of that patch, some other solution to non-atomic changes of the prologue might be needed anyway.
I think you mean Mark Rutland's
DYNAMIC_FTRACE_WITH_CALL_OPS. But that still needs to be ready. Let's disable PREEMPT for ftrace first.
FWIW, taking the patch to disable FTRACE with PREEMPT for now makes sense to me, too.
The DYNAMIC_FTRACE_WITH_CALL_OPS patches should be in v6.3. They're currently queued in the arm64 tree in the for-next/ftrace branch:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/ftrace
https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/
... and those *should* be in v6.3.
Patches to imeplement DIRECT_CALLS atop that are in review at the moment:
https://lore.kernel.org/linux-arm-kernel/[email protected]/
... and if riscv uses the CALL_OPS approach, I believe it can do much the same there.
If riscv wants to do a single atomic patch to each patch-site (to avoid stop_machine()), then direct calls would always needs to bounce through the ftrace_caller trampoline (and acquire the direct call from the ftrace_ops), but that might not be as bad as it sounds -- from benchmarking on arm64, the bulk of the overhead seen with direct calls is when using the list_ops or having to do a hash lookup, and both of those are avoided with the CALL_OPS approach. Calling directly from the patch-site is a minor optimization relative to skipping that work.
Thanks,
Mark.
Quoted 24 lines · Mark Rutland
Quoted 22 lines · Guo Ren
Quoted 9 lines · Evgenii Shatokhin
Hi,
Quoted 5 lines · On 12.01.2023 12:05, [email protected] wrote:
From: Guo Ren <[email protected]>
The previous ftrace detour implementation
fc76b8b8011("riscv: UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT") contain three problems.Quoted 8 lines
Quoted 3 lines
- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
It seems, the patches #2-#7 of this series do not require "riscv:
ftrace: Fixup panic by disabling preemption" and can be used without it.How about moving that patch out of the series and processing it separately?
Okay.
Quoted 1 line
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
As it was pointed out in the discussion of that patch, some other solution to non-atomic changes of the prologue might be needed anyway.
I think you mean Mark Rutland's
DYNAMIC_FTRACE_WITH_CALL_OPS. But that still needs to be ready. Let's disable PREEMPT for ftrace first.FWIW, taking the patch to disable FTRACE with PREEMPT for now makes sense to me, too.
Thx, you agree with that.
Quoted 8 lines
The
DYNAMIC_FTRACE_WITH_CALL_OPSpatches should be in v6.3. They're currently queued in the arm64 tree in the for-next/ftrace branch:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.gitfor-next/ftrace
https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/... and those *should* be in v6.3.
Glade to hear that. Great!
Quoted 4 lines
Patches to imeplement
DIRECT_CALLSatop that are in review at the moment:
Good reference. Thx for sharing.
Quoted 4 lines
... and if riscv uses the
CALL_OPSapproach, I believe it can do much the same there.
Quoted 8 lines
If riscv wants to do a single atomic patch to each patch-site (to avoid
stop_machine()), then direct calls would always needs to bounce through theftrace_callertrampoline (and acquire the direct call from theftrace_ops), but that might not be as bad as it sounds -- from benchmarking on arm64, the bulk of the overhead seen with direct calls is when using thelist_opsor having to do a hash lookup, and both of those are avoided with theCALL_OPSapproach. Calling directly from the patch-site is a minor optimization relative to skipping that work.
Yes, CALL_OPS could solve the PREEMPTION & stop_machine problems. I would follow up.
The difference from arm64 is that RISC-V is 16bit/32bit mixed instruction ISA, so we must keep ftrace_caller & ftrace_regs_caller in 2048 aligned. Then:FTRACE_UPDATE_MAKE_CALL:
* addr+00: NOP // Literal (first 32 bits)
* addr+04: NOP // Literal (last 32 bits)
* addr+08: func: auipc t0, ? // All trampolines are in the 2048
aligned place, so this point won't be changed.
* addr+12: jalr ?(t0) // For different trampolines:ftrace_regs_caller, ftrace_caller
FTRACE_UPDATE_MAKE_NOP:
* addr+00: NOP // Literal (first 32 bits)
* addr+04: NOP // Literal (last 32 bits)
* addr+08: func: c.j // jump to addr + 16 and skip broken insn & jalr
* addr+10: xxx // last half & broken insn of auipc t0, ?
* addr+12: jalr ?(t0) // To be patched to jalr ?<t0> ()
* addr+16: func body
Right? (The call site would be increased from 64bit to 128bit ahead of func.)
Quoted 3 lines
Thanks,
Mark.
--
Best Regards
Guo Ren
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Mark Rutland
reviewerQuoted 28 lines · Guo Ren
Quoted 7 lines · Mark Rutland
The
DYNAMIC_FTRACE_WITH_CALL_OPSpatches should be in v6.3. They're currently queued in the arm64 tree in the for-next/ftrace branch:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.gitfor-next/ftrace
https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/... and those *should* be in v6.3.
Glade to hear that. Great!
Quoted 4 lines
Patches to imeplement
DIRECT_CALLSatop that are in review at the moment:Good reference. Thx for sharing.
Quoted 4 lines
... and if riscv uses the
CALL_OPSapproach, I believe it can do much the same there.Quoted 8 lines
If riscv wants to do a single atomic patch to each patch-site (to avoid
stop_machine()), then direct calls would always needs to bounce through theftrace_callertrampoline (and acquire the direct call from theftrace_ops), but that might not be as bad as it sounds -- from benchmarking on arm64, the bulk of the overhead seen with direct calls is when using thelist_opsor having to do a hash lookup, and both of those are avoided with theCALL_OPSapproach. Calling directly from the patch-site is a minor optimization relative to skipping that work.
Quoted 6 lines
Yes,
CALL_OPScould solve the PREEMPTION &stop_machineproblems. I would follow up.The difference from arm64 is that RISC-V is 16bit/32bit mixed instruction ISA, so we must keep
ftrace_caller&ftrace_regs_callerin 2048 aligned. Then:
Where does the 2048-bit alignment requirement come from?
Note that I'm assuming you will *always* go through a common ftrace_caller trampoline (even for direct calls), with the trampoline responsible for recovering the direct trampoline (or ops->func) from the ops pointer.
That would only require 64-bit alignment on 64-bit (or 32-bit alignment on 32-bit) to keep the literal naturally-aligned; the rest of the instructions wouldn't require additional alignment.
For example, I would expect that (for 64-bit) you'd use:
# place 2 NOPs *immediately before* the function, and 3 NOPs at the start -fpatchable-function-entry=5,2
# Align the function to 8-bytes
-falign=functions=8
... and your trampoline in each function could be initialized to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // set to ftrace_nop_ops
addr-04 // Literal (last 32-bits) // set to ftrace_nop_ops
addr+00 func: mv t0, ra
addr+04 auipc t1, ftrace_caller
addr+08 nop
... and when enabled can be set to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr
addr-04 // Literal (last 32-bits) // patched to ops ptr
addr+00 func: mv t0, ra
addr+04 auipc t1, ftrace_caller
addr+08 jalr ftrace_caller(t1)
Note: this *only* requires patching the literal and NOP<->JALR; the MV and AUIPC aren't harmful and can always be there. This way, you won't need to use stop_machine().
With that, the ftrace_caller trampoline can recover the ops pointer at a negative offset from ra, and can recover the instrumented function's return address in t0. Using the ops pointer, it can figure out whether to branch to a direct trampoline or whether to save/restore the regs around invoking ops->func.
For 32-bit it would be exactly the same, except you'd only need a single nop before the function, and the offset would be -0x10.
That's what arm64 does; the only difference is that riscv would *always* need to go via the trampoline in order to make direct calls.
Thanks,
Mark.
Hi Mark,
Thx for the thoughtful reply.
Quoted 30 lines · Mark Rutland
Quoted 28 lines · Guo Ren
Quoted 7 lines · Mark Rutland
The
DYNAMIC_FTRACE_WITH_CALL_OPSpatches should be in v6.3. They're currently queued in the arm64 tree in the for-next/ftrace branch:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.gitfor-next/ftrace
https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/... and those *should* be in v6.3.
Glade to hear that. Great!
Quoted 4 lines
Patches to imeplement
DIRECT_CALLSatop that are in review at the moment:Good reference. Thx for sharing.
Quoted 12 lines
... and if riscv uses the
CALL_OPSapproach, I believe it can do much the same there.If riscv wants to do a single atomic patch to each patch-site (to avoid
stop_machine()), then direct calls would always needs to bounce through theftrace_callertrampoline (and acquire the direct call from theftrace_ops), but that might not be as bad as it sounds -- from benchmarking on arm64, the bulk of the overhead seen with direct calls is when using thelist_opsor having to do a hash lookup, and both of those are avoided with theCALL_OPSapproach. Calling directly from the patch-site is a minor optimization relative to skipping that work.
Quoted 8 lines
Quoted 6 lines
Yes,
CALL_OPScould solve the PREEMPTION &stop_machineproblems. I would follow up.The difference from arm64 is that RISC-V is 16bit/32bit mixed instruction ISA, so we must keep
ftrace_caller&ftrace_regs_callerin 2048 aligned. Then:Where does the 2048-bit alignment requirement come from?
Sorry for the typo. It's one 2048 bytes for keeping two trampolines (ftrace_caller & ftrace_regs_caller) in one aligned part. Because the jalr has only +-2048 bytes offset range.
Then the "auipc t1, ftrace(_regs)_caller" is fixed.
Quoted 26 lines
Note that I'm assuming you will *always* go through a common
ftrace_callertrampoline (even for direct calls), with the trampoline responsible for recovering the direct trampoline (orops->func) from the ops pointer.That would only require 64-bit alignment on 64-bit (or 32-bit alignment on 32-bit) to keep the literal naturally-aligned; the rest of the instructions wouldn't require additional alignment.
For example, I would expect that (for 64-bit) you'd use:
# place 2 NOPs *immediately before* the function, and 3 NOPs at the start -fpatchable-function-entry=5,2# Align the function to 8-bytes
-falign=functions=8... and your trampoline in each function could be initialized to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // set to ftrace_nop_ops addr-04 // Literal (last 32-bits) // set to ftrace_nop_ops addr+00 func: mv t0, ra addr+04 auipc t1, ftrace_caller addr+08 nop
Quoted 6 lines
... and when enabled can be set to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, ra
We needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)
Here is the call-site:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
Quoted 4 lines
Note: this *only* requires patching the literal and NOP<->JALR; the MV and AUIPC aren't harmful and can always be there. This way, you won't need to use
stop_machine().
Yes, simplest nop is better than c.j. I confused.
Quoted 9 lines
With that, the
ftrace_callertrampoline can recover theopspointer at a negative offset fromra, and can recover the instrumented function's return address int0. Using theopspointer, it can figure out whether to branch to a direct trampoline or whether to save/restore the regs around invokingops->func.For 32-bit it would be exactly the same, except you'd only need a single nop before the function, and the offset would be -0x10.
Yes, we reduced another 4 bytes & a smaller alignment for better code size when 32-bit.
# Note: aligned to 4 bytes
addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
Quoted 3 lines
That's what arm64 does; the only difference is that riscv would *always* need to go via the trampoline in order to make direct calls.
We need one more trampoline here beside ftrace_caller &ftrace_regs_caller: It's "direct_caller".
addr+04 nop -> direct_caller/ftrace_caller/ftrace_regs_caller
Quoted 3 lines
Thanks,
Mark.
Signature · 2 lines
Best Regards Guo Ren
Mark Rutland
reviewerQuoted 32 lines · Guo Ren
Hi Mark,
Thx for the thoughtful reply.
Quoted 27 lines · Mark Rutland
Note that I'm assuming you will *always* go through a common
ftrace_callertrampoline (even for direct calls), with the trampoline responsible for recovering the direct trampoline (orops->func) from the ops pointer.That would only require 64-bit alignment on 64-bit (or 32-bit alignment on 32-bit) to keep the literal naturally-aligned; the rest of the instructions wouldn't require additional alignment.
For example, I would expect that (for 64-bit) you'd use:
# place 2 NOPs *immediately before* the function, and 3 NOPs at the start -fpatchable-function-entry=5,2# Align the function to 8-bytes
-falign=functions=8... and your trampoline in each function could be initialized to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // set to ftrace_nop_ops addr-04 // Literal (last 32-bits) // set to ftrace_nop_ops addr+00 func: mv t0, ra addr+04 auipc t1, ftrace_caller addr+08 nop... and when enabled can be set to:
Quoted 7 lines
Quoted 4 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, raWe needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Ah; I thought JALR always clobbered ra? Or can that specify the register to save the link address to?
I'm not that familiar with riscv asm, so I've probably just got that wrong.
Quoted 9 lines
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
I'm a bit confused there; I thought that the symbol(reg) addressing mode was generating additional bits that the AUPIC didn't -- have I got that wrong?
What specifies which register the JALR will write the link address to?
Quoted 22 lines
Quoted 3 lines
Note: this *only* requires patching the literal and NOP<->JALR; the MV and AUIPC aren't harmful and can always be there. This way, you won't need to use
stop_machine().Yes, simplest nop is better than c.j. I confused.
Quoted 9 lines
With that, the
ftrace_callertrampoline can recover theopspointer at a negative offset fromra, and can recover the instrumented function's return address int0. Using theopspointer, it can figure out whether to branch to a direct trampoline or whether to save/restore the regs around invokingops->func.For 32-bit it would be exactly the same, except you'd only need a single nop before the function, and the offset would be -0x10.
Yes, we reduced another 4 bytes & a smaller alignment for better code size when 32-bit.
# Note: aligned to 4 bytesaddr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)Quoted 1 line
Quoted 6 lines
Quoted 2 lines
That's what arm64 does; the only difference is that riscv would *always* need to go via the trampoline in order to make direct calls.
We need one more trampoline here beside
ftrace_caller&ftrace_regs_caller: It's "direct_caller".addr+04 nop -> direct_caller/ftrace_caller/ftrace_regs_caller
I'd strongly recommend that you instead implement FTRACE_WITH_ARGS and deprecate FTRACE_WITH_REGS, like arm64 has done, then you only need a single ftrace_caller, as I mentioned above. That way there's no risk that you need to patch the AUIPC after initialization.
The arm64 FTRACE_WITH_ARGS conversion is in mainline, and arm64's FTRACE_WITH_CALL_OPS is based upon that. Florent's DIRECT_CALLS patches add the direct call logic to the same ftrace_caller trampoline.
Thanks,
Mark.
Quoted 38 lines · Mark Rutland
Quoted 36 lines · Guo Ren
Hi Mark,
Thx for the thoughtful reply.
Quoted 31 lines · Mark Rutland
Note that I'm assuming you will *always* go through a common
ftrace_callertrampoline (even for direct calls), with the trampoline responsible for recovering the direct trampoline (orops->func) from the ops pointer.That would only require 64-bit alignment on 64-bit (or 32-bit alignment on 32-bit) to keep the literal naturally-aligned; the rest of the instructions wouldn't require additional alignment.
For example, I would expect that (for 64-bit) you'd use:
# place 2 NOPs *immediately before* the function, and 3 NOPs at the start -fpatchable-function-entry=5,2# Align the function to 8-bytes
-falign=functions=8... and your trampoline in each function could be initialized to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // set to ftrace_nop_ops addr-04 // Literal (last 32-bits) // set to ftrace_nop_ops addr+00 func: mv t0, ra addr+04 auipc t1, ftrace_caller addr+08 nop... and when enabled can be set to:
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, ra
Quoted 6 lines
Quoted 3 lines
We needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Ah; I thought JALR always clobbered ra? Or can that specify the register to save the link address to?
Yes, that's the feature of riscv :) We could use any register to save the link address.
Quoted 12 lines
I'm not that familiar with riscv asm, so I've probably just got that wrong.
Quoted 9 lines
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
Sorry, it should be:
addr+04 jalr t0, ftrace_caller(t0)
Quoted 5 lines
I'm a bit confused there; I thought that the
symbol(reg)addressing mode was generating additional bits that the AUPIC didn't -- have I got that wrong?What specifies which register the JALR will write the link address to?
According to the spec, auipc t1,0x0 should write PC + 0x0<<12 (which is equal to PC) to t1 and then jalr t0, (t0)0 jumps to the address stored in t0 + 0x0 and stores the return address to t0.
That means auipc defines xxx << 12 bits, jalr defines lowest 12 bits.
Quoted 13 lines
Quoted 13 lines
Quoted 4 lines
Note: this *only* requires patching the literal and NOP<->JALR; the MV and AUIPC aren't harmful and can always be there. This way, you won't need to use
stop_machine().Yes, simplest nop is better than c.j. I confused.
Quoted 7 lines
With that, the
ftrace_callertrampoline can recover theopspointer at a negative offset fromra, and can recover the instrumented function's return address int0. Using theopspointer, it can figure out whether to branch to a direct trampoline or whether to save/restore the regs around invokingops->func.
Quoted 8 lines
Quoted 8 lines
Quoted 2 lines
For 32-bit it would be exactly the same, except you'd only need a single nop before the function, and the offset would be -0x10.
Yes, we reduced another 4 bytes & a smaller alignment for better code size when 32-bit.
# Note: aligned to 4 bytesaddr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
addr+04 jalr t0, ftrace_caller(t0)
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines
That's what arm64 does; the only difference is that riscv would *always* need to go via the trampoline in order to make direct calls.
We need one more trampoline here beside
ftrace_caller&ftrace_regs_caller: It's "direct_caller".addr+04 nop -> direct_caller/ftrace_caller/ftrace_regs_caller
Quoted 8 lines
I'd strongly recommend that you instead implement
FTRACE_WITH_ARGSand deprecateFTRACE_WITH_REGS, like arm64 has done, then you only need a singleftrace_caller, as I mentioned above. That way there's no risk that you need to patch the AUIPC after initialization.The arm64
FTRACE_WITH_ARGSconversion is in mainline, and arm64'sFTRACE_WITH_CALL_OPSis based upon that. Florent'sDIRECT_CALLSpatches add the direct call logic to the sameftrace_callertrampoline.
Thx for the suggestion of only keeping the ftrace_caller idea, but it's another topic.
What I want to point out:
If we keep "auipc (addr+00)" fixed, we could use the different trampolines at "jalr (addr+0x4)" (All of them must be in one 2k aligned area).
Quoted 3 lines
Thanks,
Mark.
Signature · 2 lines
Best Regards Guo Ren
From: Guo Ren
Quoted 1 line
Sent: 09 February 2023 01:31
...
Quoted 10 lines
Quoted 4 lines
I'm a bit confused there; I thought that the
symbol(reg)addressing mode was generating additional bits that the AUPIC didn't -- have I got that wrong?What specifies which register the JALR will write the link address to?
According to the spec, auipc t1,0x0 should write PC + 0x0<<12 (which is equal to PC) to t1 and then jalr t0, (t0)0 jumps to the address stored in t0 +
0x0and stores the return address to t0.That means auipc defines xxx << 12 bits, jalr defines lowest 12 bits.
...
Quoted 4 lines
What I want to point out:
If we keep "auipc (addr+00)" fixed, we could use the different trampolines at "jalr (addr+0x4)" (All of them must be in one 2k aligned area).
I looked up auipc:
"AUIPC is used to build PC-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the address of the AUIPC instruction, then places the result in rd."
So it generates 'pc + (val << 12)'.
And the jalr then adds in a 12bit offset.
I think that means that if you have two trampolines you might need to change both instructions even if the two trampolines are actually adjacent instructions.
It is the distance from the call site that mustn't cross a 2k boundary - not the absolute address of the trampoline itself.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Quoted 21 lines · David Laight
From: Guo Ren
Quoted 1 line
Sent: 09 February 2023 01:31
...
Quoted 10 lines
Quoted 4 lines
I'm a bit confused there; I thought that the
symbol(reg)addressing mode was generating additional bits that the AUPIC didn't -- have I got that wrong?What specifies which register the JALR will write the link address to?
According to the spec, auipc t1,0x0 should write PC + 0x0<<12 (which is equal to PC) to t1 and then jalr t0, (t0)0 jumps to the address stored in t0 +
0x0and stores the return address to t0.That means auipc defines xxx << 12 bits, jalr defines lowest 12 bits.
...
Quoted 4 lines
What I want to point out:
If we keep "auipc (addr+00)" fixed, we could use the different trampolines at "jalr (addr+0x4)" (All of them must be in one 2k aligned area).
Quoted 8 lines
I looked up auipc:
"AUIPC is used to build PC-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the address of the AUIPC instruction, then places the result in rd."So it generates 'pc + (val << 12)'.
And the jalr then adds in a 12bit offset.
Correct!
Quoted 6 lines
I think that means that if you have two trampolines you might need to change both instructions even if the two trampolines are actually adjacent instructions.
It is the distance from the call site that mustn't cross a 2k boundary - not the absolute address of the trampoline itself.
We could have multiple adjacent trampolines, which must be kept in the same 2k boundary area. Then we needn't change auipc part when modifying.
Quoted 6 lines
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Signature · 2 lines
Best Regards Guo Ren
Quoted 9 lines
Quoted 4 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, raWe needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)
Is that some kind of 'load high' and 'add offset' pair? I guess 64bit kernels guarantee to put all module code within +-2G of the main kernel?
Quoted 6 lines
Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
Could you even do something like:
addr-n call ftrace-function
addr-n+x literals
addr+0 nop or jmp addr-n
addr+4 function_code
So that all the code executed when tracing is enabled is before the label and only one 'nop' is in the body. The called code can use the return address to find the literals and then modify it to return to addr+4. The code cost when trace is enabled is probably irrelevant here - dominated by what happens later.
It probably isn't even worth aligning a 64bit constant. Doing two reads probably won't be noticable.
What you do want to ensure is that the initial patch is overwriting nop - just in case the gap isn't there.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Quoted 5 lines · David Laight
Quoted 5 lines
Quoted 5 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, ra
Quoted 7 lines
Quoted 5 lines
We needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)Is that some kind of 'load high' and 'add offset' pair?
Yes.
Quoted 2 lines
I guess 64bit kernels guarantee to put all module code within +-2G of the main kernel?
Yes, 32-bit is enough. So we only need one 32-bit literal size for the current rv64, just like CONFIG_32BIT.
Quoted 8 lines
Quoted 7 lines
Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)
Quoted 5 lines
Could you even do something like:
addr-n call ftrace-function
addr-n+x literals
addr+0 nop or jmp addr-n
addr+4function_code
Yours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4 function_code
Quoted 17 lines
So that all the code executed when tracing is enabled is before the label and only one 'nop' is in the body. The called code can use the return address to find the literals and then modify it to return to addr+4. The code cost when trace is enabled is probably irrelevant here - dominated by what happens later.
It probably isn't even worth aligning a 64bit constant. Doing two reads probably won't be noticable.What you do want to ensure is that the initial patch is overwriting nop - just in case the gap isn't there.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Signature · 2 lines
Best Regards Guo Ren
Quoted 13 lines · Guo Ren
Quoted 11 lines · David Laight
Quoted 10 lines
Quoted 5 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, raWe needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)
Quoted 7 lines
Quoted 1 line
Is that some kind of 'load high' and 'add offset' pair?
Yes.
Quoted 2 lines
I guess 64bit kernels guarantee to put all module code within +-2G of the main kernel?
Yes, 32-bit is enough. So we only need one 32-bit literal size for the current rv64, just like
CONFIG_32BIT.
We need kernel_addr_base + this 32-bit Literal.
@Mark Rutland
What do you think the idea about reducing one more 32-bit in call-site? (It also sould work for arm64.)
Quoted 44 lines
Quoted 9 lines
Quoted 8 lines
Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)Quoted 5 lines
Could you even do something like:
addr-n call ftrace-function
addr-n+x literals
addr+0 nop or jmp addr-n
addr+4function_codeYours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4function_codeQuoted 9 lines
So that all the code executed when tracing is enabled is before the label and only one 'nop' is in the body. The called code can use the return address to find the literals and then modify it to return to addr+4. The code cost when trace is enabled is probably irrelevant here - dominated by what happens later.
It probably isn't even worth aligning a 64bit constant. Doing two reads probably won't be noticable.Quoted 8 lines
What you do want to ensure is that the initial patch is overwriting nop - just in case the gap isn't there.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)--
Best Regards
Guo Ren
Signature · 2 lines
Best Regards Guo Ren
Mark Rutland
reviewerQuoted 19 lines · Guo Ren
Quoted 18 lines · Guo Ren
Quoted 5 lines · David Laight
Quoted 5 lines
Quoted 5 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, raQuoted 7 lines
Quoted 5 lines
We needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)Is that some kind of 'load high' and 'add offset' pair?
Yes.
Quoted 2 lines
I guess 64bit kernels guarantee to put all module code within +-2G of the main kernel?
Quoted 7 lines
Quoted 2 lines
Yes, 32-bit is enough. So we only need one 32-bit literal size for the current rv64, just like
CONFIG_32BIT.We need
kernel_addr_base+ this 32-bit Literal.@Mark Rutland
What do you think the idea about reducing one more 32-bit in call-site? (It also sould work for arm64.)
The literal pointer is for a struct ftrace_ops, which is data, not code.
An ftrace_ops can be allocated from anywhere (e.g. core kernel data, module data, linear map, vmalloc space), and so is not guaranteed to be within 2GiB of all code. The literal needs to be able to address the entire kernel addresss range, and since it can be modified concurrently (with PREEMPT and not using stop_machine()) it needs to be possible to read/write atomically. So practically speaking it needs to be the native pointer size (i.e. 64-bit on a 64-bit kernel).
Other schemes for compressing that (e.g. using an integer into an array of pointers) is possible, but uses more memory and gets more complicated for concurrent manipulation, so I would strongly recommend keeping this simple and using a native pointer size here.
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 6 lines
Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)Could you even do something like:
addr-n call ftrace-function
addr-n+x literals
addr+0 nop or jmp addr-n
addr+4function_code
Quoted 6 lines
Quoted 6 lines
Yours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4function_code
Placing instructions before the entry point is going to confuse symbol resolution and unwind code, so I would not recommend that. It also means the trampoline will need to re-adjust the return address back into the function, but that is relatively simple.
I also think that this is micro-optimizing. The AUPIC *should* be cheap, so executing that unconditionally should be fine. I think the form that Guo suggested with AUIPC + {JALR || NOP} in the function (and 64-bits reserved immediately bfore the function) is the way to go, so long as that does the right thing with ra.
Thanks,
Mark.
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 31 lines · Mark Rutland
Quoted 19 lines · Guo Ren
Quoted 18 lines · Guo Ren
Quoted 5 lines · David Laight
Quoted 5 lines
Quoted 5 lines
# Note: aligned to 8 bytes
addr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 func: mv t0, raQuoted 7 lines
Quoted 5 lines
We needn't "mv t0, ra" here because our "jalr" could work with t0 and won't affect ra. Let's do it in the trampoline code, and then we can save another word here.
Quoted 2 lines
addr+04 auipc t1, ftrace_caller addr+08 jalr ftrace_caller(t1)Is that some kind of 'load high' and 'add offset' pair?
Yes.
Quoted 2 lines
I guess 64bit kernels guarantee to put all module code within +-2G of the main kernel?
Quoted 7 lines
Quoted 2 lines
Yes, 32-bit is enough. So we only need one 32-bit literal size for the current rv64, just like
CONFIG_32BIT.We need
kernel_addr_base+ this 32-bit Literal.@Mark Rutland
What do you think the idea about reducing one more 32-bit in call-site? (It also sould work for arm64.)The literal pointer is for a struct
ftrace_ops, which is data, not code.
Quoted 7 lines
An
ftrace_opscan be allocated from anywhere (e.g. core kernel data, module data, linear map, vmalloc space), and so is not guaranteed to be within 2GiB of all code. The literal needs to be able to address the entire kernel addresss range, and since it can be modified concurrently (with PREEMPT and not usingstop_machine()) it needs to be possible to read/write atomically. So practically speaking it needs to be the native pointer size (i.e. 64-bit on a 64-bit kernel).
Got it, thx. Let's use an absolute pointer as the beginning.
Quoted 38 lines
Other schemes for compressing that (e.g. using an integer into an array of pointers) is possible, but uses more memory and gets more complicated for concurrent manipulation, so I would strongly recommend keeping this simple and using a native pointer size here.
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 6 lines
Here is the call-site:
# Note: aligned to 8 bytesaddr-08 // Literal (first 32-bits) // patched to ops ptr addr-04 // Literal (last 32-bits) // patched to ops ptr addr+00 auipc t0, ftrace_caller addr+04 jalr ftrace_caller(t0)Could you even do something like:
addr-n call ftrace-function
addr-n+x literals
addr+0 nop or jmp addr-n
addr+4function_codeQuoted 6 lines
Quoted 6 lines
Yours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4function_codePlacing instructions before the entry point is going to confuse symbol resolution and unwind code, so I would not recommend that. It also means the trampoline will need to re-adjust the return address back into the function, but that is relatively simple.
I also think that this is micro-optimizing. The AUPIC *should* be cheap, so executing that unconditionally should be fine. I think the form that Guo suggested with AUIPC + {JALR || NOP} in the function (and 64-bits reserved immediately bfore the function) is the way to go, so long as that does the right thing with ra.
Thanks,
Mark.
Signature · 2 lines
Best Regards Guo Ren
From: Guo Ren
Quoted 1 line
Sent: 09 February 2023 01:51
...
Quoted 6 lines
Yours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4function_code
Yes, it is 4 bytes larger but there is one less instruction executed (only one nop) when ftrace is disabled. That probably matters more than anything in the ftrace 'prologue' code.
I also suspect that you can use a 32bit integer as a table index in 64bit mode to save a word there.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Quoted 11 lines · David Laight
From: Guo Ren
Quoted 1 line
Sent: 09 February 2023 01:51
...
Quoted 6 lines
Yours cost one more instruction, right?
addr-12 auipc
addr-8 jalr
addr-4 // Literal (32-bits)
addr+0 nop or jmp addr-n // one more?
addr+4function_code
Quoted 4 lines
Yes, it is 4 bytes larger but there is one less instruction executed (only one nop) when ftrace is disabled. That probably matters more than anything in the ftrace 'prologue' code.
I've got your point, thx. I would consider your advice and make the tradeoff.
Quoted 3 lines
I also suspect that you can use a 32bit integer as a table index in 64bit mode to save a word there.
Yes, good idea. I've asked Mark Rutland. Let's wait for his feedback. It also helps arm64.
Quoted 6 lines
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Signature · 2 lines
Best Regards Guo Ren
This series was applied to riscv/linux.git (for-next) by Palmer Dabbelt <[email protected]>:
Hello:
This series was applied to riscv/linux.git (for-next) by Palmer Dabbelt <[email protected]>:
Quoted 17 lines · On Thu, 12 Jan 2023 04:05:56 -0500 you wrote:
From: Guo Ren <[email protected]>
The previous ftrace detour implementation
fc76b8b8011("riscv: UsingPATCHABLE_FUNCTION_ENTRYinstead of MCOUNT") contain three problems.- The most horrible bug is preemption panic which found by Andy [1]. Let's disable preemption for ftrace first, and Andy could continue the ftrace preemption work.
- The "-fpatchable-function-entry= CFLAG" wasted code size !RISCV_ISA_C.
- The ftrace detour implementation wasted code size.
- When livepatching, the trampoline (ftrace_regs_caller) would not return to <func_prolog+12> but would rather jump to the new function. So, "REG_Lra, -SZREG(sp)" would not run and the original return address would not be restored. The kernel is likely to hang or crash as a result. (Found by Evgenii Shatokhin [4])
Quoted 1 line
[...]
Here is the summary with links:
- [-next,V7,1/7] riscv: ftrace: Fixup panic by disabling preemption
https://git.kernel.org/riscv/c/8547649981e6 - [-next,V7,2/7] riscv: ftrace: Remove wasted nops for !RISCV_ISA_C https://git.kernel.org/riscv/c/409c8fb20c66 - [-next,V7,3/7] riscv: ftrace: Reduce the detour code size to half https://git.kernel.org/riscv/c/6724a76cff85
- [-next,V7,4/7] riscv: ftrace: Add ftrace_graph_func
(no matching commit)
- [-next,V7,5/7] riscv: ftrace: Add DYNAMIC_FTRACE_WITH_DIRECT_CALLS support (no matching commit)
- [-next,V7,6/7] samples: ftrace: Add riscv support for SAMPLE_FTRACE_DIRECT[_MULTI] (no matching commit)
- [-next,V7,7/7] riscv : select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY (no matching commit)
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html