The jump-optimized kprobe template calls optimized_callback() with preemption still enabled for its first few instructions, so bracket the call with an increment/decrement of current->rcu_tramp_nesting. The template lives in .rodata and is memcpy()d into each optinsn slot without relocation processing, so the per-CPU reference to current_task must be an absolute %gs: address (R_X86_64_32S, relocated for KASLR like any other) rather than %rip-relative. %rax has already been saved by SAVE_REGS_STRING and is dead after the call. The slot itself is dynamically allocated text, so the instructions before the increment and after the decrement are covered by the irq-exit IP check. 64-bit only; 32-bit x86 does not take part. Assisted-by: LLM Signed-off-by: Josef Bacik --- arch/x86/kernel/kprobes/opt.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 3f8fea52619f..f722520bb989 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "common.h" @@ -101,6 +102,23 @@ static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val) *(unsigned long *)addr = val; } +/* + * Tasks RCU trampoline nesting, see rcu_tasks_trampoline_enter(). The + * template is memcpy()d into the slot without relocation processing, so the + * per-CPU reference must be absolute, not %rip-relative. + */ +#if defined(CONFIG_TASKS_RCU) && defined(CONFIG_X86_64) +#define OPTPROBE_RCU_TASKS_ENTER \ + " movq %gs:current_task, %rax\n" \ + " incl " __stringify(TASK_rcu_tramp_nesting) "(%rax)\n" +#define OPTPROBE_RCU_TASKS_EXIT \ + " movq %gs:current_task, %rax\n" \ + " decl " __stringify(TASK_rcu_tramp_nesting) "(%rax)\n" +#else +#define OPTPROBE_RCU_TASKS_ENTER +#define OPTPROBE_RCU_TASKS_EXIT +#endif + asm ( ".pushsection .rodata\n" ".global optprobe_template_entry\n" @@ -114,6 +132,7 @@ asm ( "optprobe_template_clac:\n" ASM_NOP3 SAVE_REGS_STRING + OPTPROBE_RCU_TASKS_ENTER " movq %rsp, %rsi\n" ".global optprobe_template_val\n" "optprobe_template_val:\n" @@ -122,6 +141,7 @@ asm ( ".global optprobe_template_call\n" "optprobe_template_call:\n" ASM_NOP5 + OPTPROBE_RCU_TASKS_EXIT /* Copy 'regs->flags' into 'regs->ss'. */ " movq 18*8(%rsp), %rdx\n" " movq %rdx, 20*8(%rsp)\n" -- 2.55.0