Skip to content

Commit 199cc14

Browse files
MQ-mengqingchenhuacai
authored andcommitted
LoongArch: Add kernel livepatching support
The arch-specified function ftrace_regs_set_instruction_pointer() has been implemented in arch/loongarch/include/asm/ftrace.h, so here only implement arch_stack_walk_reliable() function. Here are the test logs: [root@linux fedora]# cat /proc/cmdline BOOT_IMAGE=/vmlinuz-6.8.0-rc2 root=/dev/sda3 [root@linux fedora]# modprobe livepatch-sample [root@linux fedora]# cat /proc/cmdline this has been live patched [root@linux fedora]# echo 0 > /sys/kernel/livepatch/livepatch_sample/enabled [root@linux fedora]# rmmod livepatch_sample [root@linux fedora]# cat /proc/cmdline BOOT_IMAGE=/vmlinuz-6.8.0-rc2 root=/dev/sda3 [root@linux fedora]# dmesg -t | tail -5 livepatch: enabling patch 'livepatch_sample' livepatch: 'livepatch_sample': starting patching transition livepatch: 'livepatch_sample': patching complete livepatch: 'livepatch_sample': starting unpatching transition livepatch: 'livepatch_sample': unpatching complete Signed-off-by: Jinyang He <hejinyang@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent cb8a2ef commit 199cc14

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

arch/loongarch/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ config LOONGARCH
134134
select HAVE_KPROBES_ON_FTRACE
135135
select HAVE_KRETPROBES
136136
select HAVE_KVM
137+
select HAVE_LIVEPATCH
137138
select HAVE_MOD_ARCH_SPECIFIC
138139
select HAVE_NMI
139140
select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS
@@ -143,6 +144,7 @@ config LOONGARCH
143144
select HAVE_PERF_USER_STACK_DUMP
144145
select HAVE_PREEMPT_DYNAMIC_KEY
145146
select HAVE_REGS_AND_STACK_ACCESS_API
147+
select HAVE_RELIABLE_STACKTRACE if UNWINDER_ORC
146148
select HAVE_RETHOOK
147149
select HAVE_RSEQ
148150
select HAVE_RUST
@@ -636,6 +638,8 @@ config RANDOMIZE_BASE_MAX_OFFSET
636638

637639
This is limited by the size of the lower address memory, 256MB.
638640

641+
source "kernel/livepatch/Kconfig"
642+
639643
endmenu
640644

641645
config ARCH_SELECT_MEMORY_MODEL

arch/loongarch/include/asm/thread_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ register unsigned long current_stack_pointer __asm__("$sp");
8686
#define TIF_LASX_CTX_LIVE 18 /* LASX context must be preserved */
8787
#define TIF_USEDLBT 19 /* LBT was used by this task this quantum (SMP) */
8888
#define TIF_LBT_CTX_LIVE 20 /* LBT context must be preserved */
89+
#define TIF_PATCH_PENDING 21 /* pending live patching update */
8990

9091
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
9192
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
@@ -105,6 +106,7 @@ register unsigned long current_stack_pointer __asm__("$sp");
105106
#define _TIF_LASX_CTX_LIVE (1<<TIF_LASX_CTX_LIVE)
106107
#define _TIF_USEDLBT (1<<TIF_USEDLBT)
107108
#define _TIF_LBT_CTX_LIVE (1<<TIF_LBT_CTX_LIVE)
109+
#define _TIF_PATCH_PENDING (1<<TIF_PATCH_PENDING)
108110

109111
#endif /* __KERNEL__ */
110112
#endif /* _ASM_THREAD_INFO_H */

arch/loongarch/kernel/stacktrace.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,46 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
4040
}
4141
}
4242

43+
int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
44+
void *cookie, struct task_struct *task)
45+
{
46+
unsigned long addr;
47+
struct pt_regs dummyregs;
48+
struct pt_regs *regs = &dummyregs;
49+
struct unwind_state state;
50+
51+
if (task == current) {
52+
regs->regs[3] = (unsigned long)__builtin_frame_address(0);
53+
regs->csr_era = (unsigned long)__builtin_return_address(0);
54+
} else {
55+
regs->regs[3] = thread_saved_fp(task);
56+
regs->csr_era = thread_saved_ra(task);
57+
}
58+
regs->regs[1] = 0;
59+
regs->regs[22] = 0;
60+
61+
for (unwind_start(&state, task, regs);
62+
!unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) {
63+
addr = unwind_get_return_address(&state);
64+
65+
/*
66+
* A NULL or invalid return address probably means there's some
67+
* generated code which __kernel_text_address() doesn't know about.
68+
*/
69+
if (!addr)
70+
return -EINVAL;
71+
72+
if (!consume_entry(cookie, addr))
73+
return -EINVAL;
74+
}
75+
76+
/* Check for stack corruption */
77+
if (unwind_error(&state))
78+
return -EINVAL;
79+
80+
return 0;
81+
}
82+
4383
static int
4484
copy_stack_frame(unsigned long fp, struct stack_frame *frame)
4585
{

0 commit comments

Comments
 (0)