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