xref: /linux/arch/riscv/kernel/probes/uprobes.c (revision 58b1294dd1d65bb62f08dddbf418f954210c2057)
174784081SGuo Ren // SPDX-License-Identifier: GPL-2.0-only
274784081SGuo Ren 
374784081SGuo Ren #include <linux/highmem.h>
474784081SGuo Ren #include <linux/ptrace.h>
574784081SGuo Ren #include <linux/uprobes.h>
674784081SGuo Ren 
774784081SGuo Ren #include "decode-insn.h"
874784081SGuo Ren 
974784081SGuo Ren #define UPROBE_TRAP_NR	UINT_MAX
1074784081SGuo Ren 
1174784081SGuo Ren bool is_swbp_insn(uprobe_opcode_t *insn)
1274784081SGuo Ren {
1374784081SGuo Ren #ifdef CONFIG_RISCV_ISA_C
1474784081SGuo Ren 	return (*insn & 0xffff) == UPROBE_SWBP_INSN;
1574784081SGuo Ren #else
1674784081SGuo Ren 	return *insn == UPROBE_SWBP_INSN;
1774784081SGuo Ren #endif
1874784081SGuo Ren }
1974784081SGuo Ren 
2074784081SGuo Ren unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
2174784081SGuo Ren {
2274784081SGuo Ren 	return instruction_pointer(regs);
2374784081SGuo Ren }
2474784081SGuo Ren 
2574784081SGuo Ren int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
2674784081SGuo Ren 			     unsigned long addr)
2774784081SGuo Ren {
2874784081SGuo Ren 	probe_opcode_t opcode;
2974784081SGuo Ren 
3074784081SGuo Ren 	opcode = *(probe_opcode_t *)(&auprobe->insn[0]);
3174784081SGuo Ren 
3274784081SGuo Ren 	auprobe->insn_size = GET_INSN_LENGTH(opcode);
3374784081SGuo Ren 
3474784081SGuo Ren 	switch (riscv_probe_decode_insn(&opcode, &auprobe->api)) {
3574784081SGuo Ren 	case INSN_REJECTED:
3674784081SGuo Ren 		return -EINVAL;
3774784081SGuo Ren 
3874784081SGuo Ren 	case INSN_GOOD_NO_SLOT:
3974784081SGuo Ren 		auprobe->simulate = true;
4074784081SGuo Ren 		break;
4174784081SGuo Ren 
4274784081SGuo Ren 	case INSN_GOOD:
4374784081SGuo Ren 		auprobe->simulate = false;
4474784081SGuo Ren 		break;
4574784081SGuo Ren 
4674784081SGuo Ren 	default:
4774784081SGuo Ren 		return -EINVAL;
4874784081SGuo Ren 	}
4974784081SGuo Ren 
5074784081SGuo Ren 	return 0;
5174784081SGuo Ren }
5274784081SGuo Ren 
5374784081SGuo Ren int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
5474784081SGuo Ren {
5574784081SGuo Ren 	struct uprobe_task *utask = current->utask;
5674784081SGuo Ren 
5774784081SGuo Ren 	utask->autask.saved_cause = current->thread.bad_cause;
5874784081SGuo Ren 	current->thread.bad_cause = UPROBE_TRAP_NR;
5974784081SGuo Ren 
6074784081SGuo Ren 	instruction_pointer_set(regs, utask->xol_vaddr);
6174784081SGuo Ren 
6274784081SGuo Ren 	return 0;
6374784081SGuo Ren }
6474784081SGuo Ren 
6574784081SGuo Ren int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
6674784081SGuo Ren {
6774784081SGuo Ren 	struct uprobe_task *utask = current->utask;
6874784081SGuo Ren 
6974784081SGuo Ren 	WARN_ON_ONCE(current->thread.bad_cause != UPROBE_TRAP_NR);
70*58b1294dSTiezhu Yang 	current->thread.bad_cause = utask->autask.saved_cause;
7174784081SGuo Ren 
7274784081SGuo Ren 	instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size);
7374784081SGuo Ren 
7474784081SGuo Ren 	return 0;
7574784081SGuo Ren }
7674784081SGuo Ren 
7774784081SGuo Ren bool arch_uprobe_xol_was_trapped(struct task_struct *t)
7874784081SGuo Ren {
7974784081SGuo Ren 	if (t->thread.bad_cause != UPROBE_TRAP_NR)
8074784081SGuo Ren 		return true;
8174784081SGuo Ren 
8274784081SGuo Ren 	return false;
8374784081SGuo Ren }
8474784081SGuo Ren 
8574784081SGuo Ren bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
8674784081SGuo Ren {
8774784081SGuo Ren 	probe_opcode_t insn;
8874784081SGuo Ren 	unsigned long addr;
8974784081SGuo Ren 
9074784081SGuo Ren 	if (!auprobe->simulate)
9174784081SGuo Ren 		return false;
9274784081SGuo Ren 
9374784081SGuo Ren 	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
9474784081SGuo Ren 	addr = instruction_pointer(regs);
9574784081SGuo Ren 
9674784081SGuo Ren 	if (auprobe->api.handler)
9774784081SGuo Ren 		auprobe->api.handler(insn, addr, regs);
9874784081SGuo Ren 
9974784081SGuo Ren 	return true;
10074784081SGuo Ren }
10174784081SGuo Ren 
10274784081SGuo Ren void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
10374784081SGuo Ren {
10474784081SGuo Ren 	struct uprobe_task *utask = current->utask;
10574784081SGuo Ren 
106*58b1294dSTiezhu Yang 	current->thread.bad_cause = utask->autask.saved_cause;
10774784081SGuo Ren 	/*
10874784081SGuo Ren 	 * Task has received a fatal signal, so reset back to probbed
10974784081SGuo Ren 	 * address.
11074784081SGuo Ren 	 */
11174784081SGuo Ren 	instruction_pointer_set(regs, utask->vaddr);
11274784081SGuo Ren }
11374784081SGuo Ren 
11474784081SGuo Ren bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
11574784081SGuo Ren 		struct pt_regs *regs)
11674784081SGuo Ren {
11774784081SGuo Ren 	if (ctx == RP_CHECK_CHAIN_CALL)
11874784081SGuo Ren 		return regs->sp <= ret->stack;
11974784081SGuo Ren 	else
12074784081SGuo Ren 		return regs->sp < ret->stack;
12174784081SGuo Ren }
12274784081SGuo Ren 
12374784081SGuo Ren unsigned long
12474784081SGuo Ren arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
12574784081SGuo Ren 				  struct pt_regs *regs)
12674784081SGuo Ren {
12774784081SGuo Ren 	unsigned long ra;
12874784081SGuo Ren 
12974784081SGuo Ren 	ra = regs->ra;
13074784081SGuo Ren 
13174784081SGuo Ren 	regs->ra = trampoline_vaddr;
13274784081SGuo Ren 
13374784081SGuo Ren 	return ra;
13474784081SGuo Ren }
13574784081SGuo Ren 
13674784081SGuo Ren int arch_uprobe_exception_notify(struct notifier_block *self,
13774784081SGuo Ren 				 unsigned long val, void *data)
13874784081SGuo Ren {
13974784081SGuo Ren 	return NOTIFY_DONE;
14074784081SGuo Ren }
14174784081SGuo Ren 
14274784081SGuo Ren bool uprobe_breakpoint_handler(struct pt_regs *regs)
14374784081SGuo Ren {
14474784081SGuo Ren 	if (uprobe_pre_sstep_notifier(regs))
14574784081SGuo Ren 		return true;
14674784081SGuo Ren 
14774784081SGuo Ren 	return false;
14874784081SGuo Ren }
14974784081SGuo Ren 
15074784081SGuo Ren bool uprobe_single_step_handler(struct pt_regs *regs)
15174784081SGuo Ren {
15274784081SGuo Ren 	if (uprobe_post_sstep_notifier(regs))
15374784081SGuo Ren 		return true;
15474784081SGuo Ren 
15574784081SGuo Ren 	return false;
15674784081SGuo Ren }
15774784081SGuo Ren 
15874784081SGuo Ren void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
15974784081SGuo Ren 			   void *src, unsigned long len)
16074784081SGuo Ren {
16174784081SGuo Ren 	/* Initialize the slot */
16274784081SGuo Ren 	void *kaddr = kmap_atomic(page);
16374784081SGuo Ren 	void *dst = kaddr + (vaddr & ~PAGE_MASK);
16474784081SGuo Ren 
16574784081SGuo Ren 	memcpy(dst, src, len);
16674784081SGuo Ren 
16774784081SGuo Ren 	/* Add ebreak behind opcode to simulate singlestep */
16874784081SGuo Ren 	if (vaddr) {
16974784081SGuo Ren 		dst += GET_INSN_LENGTH(*(probe_opcode_t *)src);
17074784081SGuo Ren 		*(uprobe_opcode_t *)dst = __BUG_INSN_32;
17174784081SGuo Ren 	}
17274784081SGuo Ren 
17374784081SGuo Ren 	kunmap_atomic(kaddr);
17474784081SGuo Ren 
17574784081SGuo Ren 	/*
17674784081SGuo Ren 	 * We probably need flush_icache_user_page() but it needs vma.
17774784081SGuo Ren 	 * This should work on most of architectures by default. If
17874784081SGuo Ren 	 * architecture needs to do something different it can define
17974784081SGuo Ren 	 * its own version of the function.
18074784081SGuo Ren 	 */
18174784081SGuo Ren 	flush_dcache_page(page);
18274784081SGuo Ren }
183