Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Add uprobes support.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+597 -2
+4
arch/mips/Kconfig
··· 1 1 config MIPS 2 2 bool 3 3 default y 4 + select ARCH_SUPPORTS_UPROBES 4 5 select ARCH_MIGHT_HAVE_PC_PARPORT 5 6 select ARCH_MIGHT_HAVE_PC_SERIO 6 7 select ARCH_USE_CMPXCHG_LOCKREF if 64BIT ··· 1041 1040 1042 1041 config ARCH_DMA_ADDR_T_64BIT 1043 1042 def_bool (HIGHMEM && ARCH_PHYS_ADDR_T_64BIT) || 64BIT 1043 + 1044 + config ARCH_SUPPORTS_UPROBES 1045 + bool 1044 1046 1045 1047 config DMA_MAYBE_COHERENT 1046 1048 select DMA_NONCOHERENT
+3 -1
arch/mips/include/asm/kdebug.h
··· 11 11 DIE_PAGE_FAULT, 12 12 DIE_BREAK, 13 13 DIE_SSTEPBP, 14 - DIE_MSAFP 14 + DIE_MSAFP, 15 + DIE_UPROBE, 16 + DIE_UPROBE_XOL, 15 17 }; 16 18 17 19 #endif /* _ASM_MIPS_KDEBUG_H */
+80
arch/mips/include/asm/ptrace.h
··· 14 14 #include <linux/linkage.h> 15 15 #include <linux/types.h> 16 16 #include <asm/isadep.h> 17 + #include <asm/page.h> 18 + #include <asm/thread_info.h> 17 19 #include <uapi/asm/ptrace.h> 18 20 19 21 /* 20 22 * This struct defines the way the registers are stored on the stack during a 21 23 * system call/exception. As usual the registers k0/k1 aren't being saved. 24 + * 25 + * If you add a register here, also add it to regoffset_table[] in 26 + * arch/mips/kernel/ptrace.c. 22 27 */ 23 28 struct pt_regs { 24 29 #ifdef CONFIG_32BIT ··· 48 43 unsigned long long mpl[6]; /* MTM{0-5} */ 49 44 unsigned long long mtp[6]; /* MTP{0-5} */ 50 45 #endif 46 + unsigned long __last[0]; 51 47 } __aligned(8); 48 + 49 + static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) 50 + { 51 + return regs->regs[31]; 52 + } 53 + 54 + /* 55 + * Don't use asm-generic/ptrace.h it defines FP accessors that don't make 56 + * sense on MIPS. We rather want an error if they get invoked. 57 + */ 58 + 59 + static inline void instruction_pointer_set(struct pt_regs *regs, 60 + unsigned long val) 61 + { 62 + regs->cp0_epc = val; 63 + } 64 + 65 + /* Query offset/name of register from its name/offset */ 66 + extern int regs_query_register_offset(const char *name); 67 + #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last)) 68 + 69 + /** 70 + * regs_get_register() - get register value from its offset 71 + * @regs: pt_regs from which register value is gotten. 72 + * @offset: offset number of the register. 73 + * 74 + * regs_get_register returns the value of a register. The @offset is the 75 + * offset of the register in struct pt_regs address which specified by @regs. 76 + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. 77 + */ 78 + static inline unsigned long regs_get_register(struct pt_regs *regs, 79 + unsigned int offset) 80 + { 81 + if (unlikely(offset > MAX_REG_OFFSET)) 82 + return 0; 83 + 84 + return *(unsigned long *)((unsigned long)regs + offset); 85 + } 86 + 87 + /** 88 + * regs_within_kernel_stack() - check the address in the stack 89 + * @regs: pt_regs which contains kernel stack pointer. 90 + * @addr: address which is checked. 91 + * 92 + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 93 + * If @addr is within the kernel stack, it returns true. If not, returns false. 94 + */ 95 + static inline int regs_within_kernel_stack(struct pt_regs *regs, 96 + unsigned long addr) 97 + { 98 + return ((addr & ~(THREAD_SIZE - 1)) == 99 + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); 100 + } 101 + 102 + /** 103 + * regs_get_kernel_stack_nth() - get Nth entry of the stack 104 + * @regs: pt_regs which contains kernel stack pointer. 105 + * @n: stack entry number. 106 + * 107 + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 108 + * is specified by @regs. If the @n th entry is NOT in the kernel stack, 109 + * this returns 0. 110 + */ 111 + static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, 112 + unsigned int n) 113 + { 114 + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 115 + 116 + addr += n; 117 + if (regs_within_kernel_stack(regs, (unsigned long)addr)) 118 + return *addr; 119 + else 120 + return 0; 121 + } 52 122 53 123 struct task_struct; 54 124
+4 -1
arch/mips/include/asm/thread_info.h
··· 99 99 #define TIF_SYSCALL_AUDIT 3 /* syscall auditing active */ 100 100 #define TIF_SECCOMP 4 /* secure computing */ 101 101 #define TIF_NOTIFY_RESUME 5 /* callback before returning to user */ 102 + #define TIF_UPROBE 6 /* breakpointed or singlestepping */ 102 103 #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ 103 104 #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ 104 105 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ ··· 123 122 #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) 124 123 #define _TIF_SECCOMP (1<<TIF_SECCOMP) 125 124 #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 125 + #define _TIF_UPROBE (1<<TIF_UPROBE) 126 126 #define _TIF_USEDFPU (1<<TIF_USEDFPU) 127 127 #define _TIF_NOHZ (1<<TIF_NOHZ) 128 128 #define _TIF_FIXADE (1<<TIF_FIXADE) ··· 148 146 149 147 /* work to do on interrupt/exception return */ 150 148 #define _TIF_WORK_MASK \ 151 - (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME) 149 + (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME | \ 150 + _TIF_UPROBE) 152 151 /* work to do on any return to u-space */ 153 152 #define _TIF_ALLWORK_MASK (_TIF_NOHZ | _TIF_WORK_MASK | \ 154 153 _TIF_WORK_SYSCALL_EXIT | \
+58
arch/mips/include/asm/uprobes.h
··· 1 + /* 2 + * This file is subject to the terms and conditions of the GNU General Public 3 + * License. See the file "COPYING" in the main directory of this archive 4 + * for more details. 5 + */ 6 + #ifndef __ASM_UPROBES_H 7 + #define __ASM_UPROBES_H 8 + 9 + #include <linux/notifier.h> 10 + #include <linux/types.h> 11 + 12 + #include <asm/break.h> 13 + #include <asm/inst.h> 14 + 15 + /* 16 + * We want this to be defined as union mips_instruction but that makes the 17 + * generic code blow up. 18 + */ 19 + typedef u32 uprobe_opcode_t; 20 + 21 + /* 22 + * Classic MIPS (note this implementation doesn't consider microMIPS yet) 23 + * instructions are always 4 bytes but in order to deal with branches and 24 + * their delay slots, we treat instructions as having 8 bytes maximum. 25 + */ 26 + #define MAX_UINSN_BYTES 8 27 + #define UPROBE_XOL_SLOT_BYTES 128 /* Max. cache line size */ 28 + 29 + #define UPROBE_BRK_UPROBE 0x000d000d /* break 13 */ 30 + #define UPROBE_BRK_UPROBE_XOL 0x000e000d /* break 14 */ 31 + 32 + #define UPROBE_SWBP_INSN UPROBE_BRK_UPROBE 33 + #define UPROBE_SWBP_INSN_SIZE 4 34 + 35 + struct arch_uprobe { 36 + unsigned long resume_epc; 37 + u32 insn[2]; 38 + u32 ixol[2]; 39 + union mips_instruction orig_inst[MAX_UINSN_BYTES / 4]; 40 + }; 41 + 42 + struct arch_uprobe_task { 43 + unsigned long saved_trap_nr; 44 + }; 45 + 46 + extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, 47 + struct mm_struct *mm, unsigned long addr); 48 + extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); 49 + extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); 50 + extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); 51 + extern int arch_uprobe_exception_notify(struct notifier_block *self, 52 + unsigned long val, void *data); 53 + extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, 54 + struct pt_regs *regs); 55 + extern unsigned long arch_uretprobe_hijack_return_addr( 56 + unsigned long trampoline_vaddr, struct pt_regs *regs); 57 + 58 + #endif /* __ASM_UPROBES_H */
+2
arch/mips/include/uapi/asm/break.h
··· 21 21 #define BRK_DIVZERO 7 /* Divide by zero check */ 22 22 #define BRK_RANGE 8 /* Range error check */ 23 23 #define BRK_BUG 12 /* Used by BUG() */ 24 + #define BRK_UPROBE 13 /* See <asm/uprobes.h> */ 25 + #define BRK_UPROBE_XOL 14 /* See <asm/uprobes.h> */ 24 26 #define BRK_MEMU 514 /* Used by FPU emulator */ 25 27 #define BRK_KPROBE_BP 515 /* Kprobe break */ 26 28 #define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */
+1
arch/mips/kernel/Makefile
··· 100 100 obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o 101 101 102 102 obj-$(CONFIG_JUMP_LABEL) += jump_label.o 103 + obj-$(CONFIG_UPROBES) += uprobes.o 103 104 104 105 obj-$(CONFIG_MIPS_CM) += mips-cm.o 105 106 obj-$(CONFIG_MIPS_CPC) += mips-cpc.o
+88
arch/mips/kernel/ptrace.c
··· 25 25 #include <linux/regset.h> 26 26 #include <linux/smp.h> 27 27 #include <linux/security.h> 28 + #include <linux/stddef.h> 28 29 #include <linux/tracehook.h> 29 30 #include <linux/audit.h> 30 31 #include <linux/seccomp.h> ··· 490 489 REGSET_GPR, 491 490 REGSET_FPR, 492 491 }; 492 + 493 + struct pt_regs_offset { 494 + const char *name; 495 + int offset; 496 + }; 497 + 498 + #define REG_OFFSET_NAME(reg, r) { \ 499 + .name = #reg, \ 500 + .offset = offsetof(struct pt_regs, r) \ 501 + } 502 + 503 + #define REG_OFFSET_END { \ 504 + .name = NULL, \ 505 + .offset = 0 \ 506 + } 507 + 508 + static const struct pt_regs_offset regoffset_table[] = { 509 + REG_OFFSET_NAME(r0, regs[0]), 510 + REG_OFFSET_NAME(r1, regs[1]), 511 + REG_OFFSET_NAME(r2, regs[2]), 512 + REG_OFFSET_NAME(r3, regs[3]), 513 + REG_OFFSET_NAME(r4, regs[4]), 514 + REG_OFFSET_NAME(r5, regs[5]), 515 + REG_OFFSET_NAME(r6, regs[6]), 516 + REG_OFFSET_NAME(r7, regs[7]), 517 + REG_OFFSET_NAME(r8, regs[8]), 518 + REG_OFFSET_NAME(r9, regs[9]), 519 + REG_OFFSET_NAME(r10, regs[10]), 520 + REG_OFFSET_NAME(r11, regs[11]), 521 + REG_OFFSET_NAME(r12, regs[12]), 522 + REG_OFFSET_NAME(r13, regs[13]), 523 + REG_OFFSET_NAME(r14, regs[14]), 524 + REG_OFFSET_NAME(r15, regs[15]), 525 + REG_OFFSET_NAME(r16, regs[16]), 526 + REG_OFFSET_NAME(r17, regs[17]), 527 + REG_OFFSET_NAME(r18, regs[18]), 528 + REG_OFFSET_NAME(r19, regs[19]), 529 + REG_OFFSET_NAME(r20, regs[20]), 530 + REG_OFFSET_NAME(r21, regs[21]), 531 + REG_OFFSET_NAME(r22, regs[22]), 532 + REG_OFFSET_NAME(r23, regs[23]), 533 + REG_OFFSET_NAME(r24, regs[24]), 534 + REG_OFFSET_NAME(r25, regs[25]), 535 + REG_OFFSET_NAME(r26, regs[26]), 536 + REG_OFFSET_NAME(r27, regs[27]), 537 + REG_OFFSET_NAME(r28, regs[28]), 538 + REG_OFFSET_NAME(r29, regs[29]), 539 + REG_OFFSET_NAME(r30, regs[30]), 540 + REG_OFFSET_NAME(r31, regs[31]), 541 + REG_OFFSET_NAME(c0_status, cp0_status), 542 + REG_OFFSET_NAME(hi, hi), 543 + REG_OFFSET_NAME(lo, lo), 544 + #ifdef CONFIG_CPU_HAS_SMARTMIPS 545 + REG_OFFSET_NAME(acx, acx), 546 + #endif 547 + REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr), 548 + REG_OFFSET_NAME(c0_cause, cp0_cause), 549 + REG_OFFSET_NAME(c0_epc, cp0_epc), 550 + #ifdef CONFIG_MIPS_MT_SMTC 551 + REG_OFFSET_NAME(c0_tcstatus, cp0_tcstatus), 552 + #endif 553 + #ifdef CONFIG_CPU_CAVIUM_OCTEON 554 + REG_OFFSET_NAME(mpl0, mpl[0]), 555 + REG_OFFSET_NAME(mpl1, mpl[1]), 556 + REG_OFFSET_NAME(mpl2, mpl[2]), 557 + REG_OFFSET_NAME(mtp0, mtp[0]), 558 + REG_OFFSET_NAME(mtp1, mtp[1]), 559 + REG_OFFSET_NAME(mtp2, mtp[2]), 560 + #endif 561 + REG_OFFSET_END, 562 + }; 563 + 564 + /** 565 + * regs_query_register_offset() - query register offset from its name 566 + * @name: the name of a register 567 + * 568 + * regs_query_register_offset() returns the offset of a register in struct 569 + * pt_regs from its name. If the name is invalid, this returns -EINVAL; 570 + */ 571 + int regs_query_register_offset(const char *name) 572 + { 573 + const struct pt_regs_offset *roff; 574 + for (roff = regoffset_table; roff->name != NULL; roff++) 575 + if (!strcmp(roff->name, name)) 576 + return roff->offset; 577 + return -EINVAL; 578 + } 493 579 494 580 #if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) 495 581
+4
arch/mips/kernel/signal.c
··· 21 21 #include <linux/wait.h> 22 22 #include <linux/ptrace.h> 23 23 #include <linux/unistd.h> 24 + #include <linux/uprobes.h> 24 25 #include <linux/compiler.h> 25 26 #include <linux/syscalls.h> 26 27 #include <linux/uaccess.h> ··· 856 855 local_irq_enable(); 857 856 858 857 user_exit(); 858 + 859 + if (thread_info_flags & _TIF_UPROBE) 860 + uprobe_notify_resume(regs); 859 861 860 862 /* deal with pending signal delivery */ 861 863 if (thread_info_flags & _TIF_SIGPENDING)
+12
arch/mips/kernel/traps.c
··· 984 984 * pertain to them. 985 985 */ 986 986 switch (bcode) { 987 + case BRK_UPROBE: 988 + if (notify_die(DIE_UPROBE, "uprobe", regs, bcode, 989 + current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) 990 + goto out; 991 + else 992 + break; 993 + case BRK_UPROBE_XOL: 994 + if (notify_die(DIE_UPROBE_XOL, "uprobe_xol", regs, bcode, 995 + current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) 996 + goto out; 997 + else 998 + break; 987 999 case BRK_KPROBE_BP: 988 1000 if (notify_die(DIE_BREAK, "debug", regs, bcode, 989 1001 current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
+341
arch/mips/kernel/uprobes.c
··· 1 + #include <linux/highmem.h> 2 + #include <linux/kdebug.h> 3 + #include <linux/types.h> 4 + #include <linux/notifier.h> 5 + #include <linux/sched.h> 6 + #include <linux/uprobes.h> 7 + 8 + #include <asm/branch.h> 9 + #include <asm/cpu-features.h> 10 + #include <asm/ptrace.h> 11 + #include <asm/inst.h> 12 + 13 + static inline int insn_has_delay_slot(const union mips_instruction insn) 14 + { 15 + switch (insn.i_format.opcode) { 16 + /* 17 + * jr and jalr are in r_format format. 18 + */ 19 + case spec_op: 20 + switch (insn.r_format.func) { 21 + case jalr_op: 22 + case jr_op: 23 + return 1; 24 + } 25 + break; 26 + 27 + /* 28 + * This group contains: 29 + * bltz_op, bgez_op, bltzl_op, bgezl_op, 30 + * bltzal_op, bgezal_op, bltzall_op, bgezall_op. 31 + */ 32 + case bcond_op: 33 + switch (insn.i_format.rt) { 34 + case bltz_op: 35 + case bltzl_op: 36 + case bgez_op: 37 + case bgezl_op: 38 + case bltzal_op: 39 + case bltzall_op: 40 + case bgezal_op: 41 + case bgezall_op: 42 + case bposge32_op: 43 + return 1; 44 + } 45 + break; 46 + 47 + /* 48 + * These are unconditional and in j_format. 49 + */ 50 + case jal_op: 51 + case j_op: 52 + case beq_op: 53 + case beql_op: 54 + case bne_op: 55 + case bnel_op: 56 + case blez_op: /* not really i_format */ 57 + case blezl_op: 58 + case bgtz_op: 59 + case bgtzl_op: 60 + return 1; 61 + 62 + /* 63 + * And now the FPA/cp1 branch instructions. 64 + */ 65 + case cop1_op: 66 + #ifdef CONFIG_CPU_CAVIUM_OCTEON 67 + case lwc2_op: /* This is bbit0 on Octeon */ 68 + case ldc2_op: /* This is bbit032 on Octeon */ 69 + case swc2_op: /* This is bbit1 on Octeon */ 70 + case sdc2_op: /* This is bbit132 on Octeon */ 71 + #endif 72 + return 1; 73 + } 74 + 75 + return 0; 76 + } 77 + 78 + /** 79 + * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. 80 + * @mm: the probed address space. 81 + * @arch_uprobe: the probepoint information. 82 + * @addr: virtual address at which to install the probepoint 83 + * Return 0 on success or a -ve number on error. 84 + */ 85 + int arch_uprobe_analyze_insn(struct arch_uprobe *aup, 86 + struct mm_struct *mm, unsigned long addr) 87 + { 88 + union mips_instruction inst; 89 + 90 + /* 91 + * For the time being this also blocks attempts to use uprobes with 92 + * MIPS16 and microMIPS. 93 + */ 94 + if (addr & 0x03) 95 + return -EINVAL; 96 + 97 + inst.word = aup->insn[0]; 98 + aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)]; 99 + aup->ixol[1] = UPROBE_BRK_UPROBE_XOL; /* NOP */ 100 + 101 + return 0; 102 + } 103 + 104 + /** 105 + * is_trap_insn - check if the instruction is a trap variant 106 + * @insn: instruction to be checked. 107 + * Returns true if @insn is a trap variant. 108 + * 109 + * This definition overrides the weak definition in kernel/events/uprobes.c. 110 + * and is needed for the case where an architecture has multiple trap 111 + * instructions (like PowerPC or MIPS). We treat BREAK just like the more 112 + * modern conditional trap instructions. 113 + */ 114 + bool is_trap_insn(uprobe_opcode_t *insn) 115 + { 116 + union mips_instruction inst; 117 + 118 + inst.word = *insn; 119 + 120 + switch (inst.i_format.opcode) { 121 + case spec_op: 122 + switch (inst.r_format.func) { 123 + case break_op: 124 + case teq_op: 125 + case tge_op: 126 + case tgeu_op: 127 + case tlt_op: 128 + case tltu_op: 129 + case tne_op: 130 + return 1; 131 + } 132 + break; 133 + 134 + case bcond_op: /* Yes, really ... */ 135 + switch (inst.u_format.rt) { 136 + case teqi_op: 137 + case tgei_op: 138 + case tgeiu_op: 139 + case tlti_op: 140 + case tltiu_op: 141 + case tnei_op: 142 + return 1; 143 + } 144 + break; 145 + } 146 + 147 + return 0; 148 + } 149 + 150 + #define UPROBE_TRAP_NR ULONG_MAX 151 + 152 + /* 153 + * arch_uprobe_pre_xol - prepare to execute out of line. 154 + * @auprobe: the probepoint information. 155 + * @regs: reflects the saved user state of current task. 156 + */ 157 + int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs) 158 + { 159 + struct uprobe_task *utask = current->utask; 160 + union mips_instruction insn; 161 + 162 + /* 163 + * Now find the EPC where to resume after the breakpoint has been 164 + * dealt with. This may require emulation of a branch. 165 + */ 166 + aup->resume_epc = regs->cp0_epc + 4; 167 + if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) { 168 + unsigned long epc; 169 + 170 + epc = regs->cp0_epc; 171 + __compute_return_epc_for_insn(regs, insn); 172 + aup->resume_epc = regs->cp0_epc; 173 + } 174 + 175 + utask->autask.saved_trap_nr = current->thread.trap_nr; 176 + current->thread.trap_nr = UPROBE_TRAP_NR; 177 + regs->cp0_epc = current->utask->xol_vaddr; 178 + 179 + return 0; 180 + } 181 + 182 + int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs) 183 + { 184 + struct uprobe_task *utask = current->utask; 185 + 186 + current->thread.trap_nr = utask->autask.saved_trap_nr; 187 + regs->cp0_epc = aup->resume_epc; 188 + 189 + return 0; 190 + } 191 + 192 + /* 193 + * If xol insn itself traps and generates a signal(Say, 194 + * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped 195 + * instruction jumps back to its own address. It is assumed that anything 196 + * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. 197 + * 198 + * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, 199 + * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to 200 + * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). 201 + */ 202 + bool arch_uprobe_xol_was_trapped(struct task_struct *tsk) 203 + { 204 + if (tsk->thread.trap_nr != UPROBE_TRAP_NR) 205 + return true; 206 + 207 + return false; 208 + } 209 + 210 + int arch_uprobe_exception_notify(struct notifier_block *self, 211 + unsigned long val, void *data) 212 + { 213 + struct die_args *args = data; 214 + struct pt_regs *regs = args->regs; 215 + 216 + /* regs == NULL is a kernel bug */ 217 + if (WARN_ON(!regs)) 218 + return NOTIFY_DONE; 219 + 220 + /* We are only interested in userspace traps */ 221 + if (!user_mode(regs)) 222 + return NOTIFY_DONE; 223 + 224 + switch (val) { 225 + case DIE_BREAK: 226 + if (uprobe_pre_sstep_notifier(regs)) 227 + return NOTIFY_STOP; 228 + break; 229 + case DIE_UPROBE_XOL: 230 + if (uprobe_post_sstep_notifier(regs)) 231 + return NOTIFY_STOP; 232 + default: 233 + break; 234 + } 235 + 236 + return 0; 237 + } 238 + 239 + /* 240 + * This function gets called when XOL instruction either gets trapped or 241 + * the thread has a fatal signal. Reset the instruction pointer to its 242 + * probed address for the potential restart or for post mortem analysis. 243 + */ 244 + void arch_uprobe_abort_xol(struct arch_uprobe *aup, 245 + struct pt_regs *regs) 246 + { 247 + struct uprobe_task *utask = current->utask; 248 + 249 + instruction_pointer_set(regs, utask->vaddr); 250 + } 251 + 252 + unsigned long arch_uretprobe_hijack_return_addr( 253 + unsigned long trampoline_vaddr, struct pt_regs *regs) 254 + { 255 + unsigned long ra; 256 + 257 + ra = regs->regs[31]; 258 + 259 + /* Replace the return address with the trampoline address */ 260 + regs->regs[31] = ra; 261 + 262 + return ra; 263 + } 264 + 265 + /** 266 + * set_swbp - store breakpoint at a given address. 267 + * @auprobe: arch specific probepoint information. 268 + * @mm: the probed process address space. 269 + * @vaddr: the virtual address to insert the opcode. 270 + * 271 + * For mm @mm, store the breakpoint instruction at @vaddr. 272 + * Return 0 (success) or a negative errno. 273 + * 274 + * This version overrides the weak version in kernel/events/uprobes.c. 275 + * It is required to handle MIPS16 and microMIPS. 276 + */ 277 + int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, 278 + unsigned long vaddr) 279 + { 280 + return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN); 281 + } 282 + 283 + /** 284 + * set_orig_insn - Restore the original instruction. 285 + * @mm: the probed process address space. 286 + * @auprobe: arch specific probepoint information. 287 + * @vaddr: the virtual address to insert the opcode. 288 + * 289 + * For mm @mm, restore the original opcode (opcode) at @vaddr. 290 + * Return 0 (success) or a negative errno. 291 + * 292 + * This overrides the weak version in kernel/events/uprobes.c. 293 + */ 294 + int set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, 295 + unsigned long vaddr) 296 + { 297 + return uprobe_write_opcode(mm, vaddr, 298 + *(uprobe_opcode_t *)&auprobe->orig_inst[0].word); 299 + } 300 + 301 + void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 302 + void *src, unsigned long len) 303 + { 304 + void *kaddr; 305 + 306 + /* Initialize the slot */ 307 + kaddr = kmap_atomic(page); 308 + memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len); 309 + kunmap_atomic(kaddr); 310 + 311 + /* 312 + * The MIPS version of flush_icache_range will operate safely on 313 + * user space addresses and more importantly, it doesn't require a 314 + * VMA argument. 315 + */ 316 + flush_icache_range(vaddr, vaddr + len); 317 + } 318 + 319 + /** 320 + * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs 321 + * @regs: Reflects the saved state of the task after it has hit a breakpoint 322 + * instruction. 323 + * Return the address of the breakpoint instruction. 324 + * 325 + * This overrides the weak version in kernel/events/uprobes.c. 326 + */ 327 + unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) 328 + { 329 + return instruction_pointer(regs); 330 + } 331 + 332 + /* 333 + * See if the instruction can be emulated. 334 + * Returns true if instruction was emulated, false otherwise. 335 + * 336 + * For now we always emulate so this function just returns 0. 337 + */ 338 + bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 339 + { 340 + return 0; 341 + }