summaryrefslogtreecommitdiff
path: root/arch/riscv/kernel/traps.c
diff options
context:
space:
mode:
authorGuo Ren <guoren@linux.alibaba.com>2020-12-17 16:01:42 +0000
committerPalmer Dabbelt <palmerdabbelt@google.com>2021-01-14 15:09:06 -0800
commitc22b0bcb1dd024cb9caad9230e3a387d8b061df5 (patch)
treef35a8b91116cb256acdcdd85939c6f06dc967bb9 /arch/riscv/kernel/traps.c
parentafc76b8b80112189b6f11e67e19cf58301944814 (diff)
riscv: Add kprobes supported
This patch enables "kprobe & kretprobe" to work with ftrace interface. It utilized software breakpoint as single-step mechanism. Some instructions which can't be single-step executed must be simulated in kernel execution slot, such as: branch, jal, auipc, la ... Some instructions should be rejected for probing and we use a blacklist to filter, such as: ecall, ebreak, ... We use ebreak & c.ebreak to replace origin instruction and the kprobe handler prepares an executable memory slot for out-of-line execution with a copy of the original instruction being probed. In execution slot we add ebreak behind original instruction to simulate a single-setp mechanism. The patch is based on packi's work [1] and csky's work [2]. - The kprobes_trampoline.S is all from packi's patch - The single-step mechanism is new designed for riscv without hw single-step trap - The simulation codes are from csky - Frankly, all codes refer to other archs' implementation [1] https://lore.kernel.org/linux-riscv/20181113195804.22825-1-me@packi.ch/ [2] https://lore.kernel.org/linux-csky/20200403044150.20562-9-guoren@kernel.org/ Signed-off-by: Guo Ren <guoren@linux.alibaba.com> Co-developed-by: Patrick Stählin <me@packi.ch> Signed-off-by: Patrick Stählin <me@packi.ch> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Tested-by: Zong Li <zong.li@sifive.com> Reviewed-by: Pekka Enberg <penberg@kernel.org> Cc: Patrick Stählin <me@packi.ch> Cc: Palmer Dabbelt <palmerdabbelt@google.com> Cc: Björn Töpel <bjorn.topel@gmail.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
Diffstat (limited to 'arch/riscv/kernel/traps.c')
-rw-r--r--arch/riscv/kernel/traps.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index ad14f4466d92..19a788a271f7 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -12,6 +12,7 @@
#include <linux/signal.h>
#include <linux/kdebug.h>
#include <linux/uaccess.h>
+#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/irq.h>
@@ -145,6 +146,14 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
asmlinkage __visible void do_trap_break(struct pt_regs *regs)
{
+#ifdef CONFIG_KPROBES
+ if (kprobe_single_step_handler(regs))
+ return;
+
+ if (kprobe_breakpoint_handler(regs))
+ return;
+#endif
+
if (user_mode(regs))
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->epc);
#ifdef CONFIG_KGDB