1 // SPDX-License-Identifier: GPL-2.0-or-later !! 1 // SPDX-License-Identifier: GPL-2.0 2 /* !! 2 #include <linux/highmem.h> 3 * User-space Probes (UProbes) for powerpc !! 3 #include <linux/kdebug.h> 4 * !! 4 #include <linux/types.h> 5 * Copyright IBM Corporation, 2007-2012 !! 5 #include <linux/notifier.h> 6 * << 7 * Adapted from the x86 port by Ananth N Mavin << 8 */ << 9 #include <linux/kernel.h> << 10 #include <linux/sched.h> 6 #include <linux/sched.h> 11 #include <linux/ptrace.h> << 12 #include <linux/uprobes.h> 7 #include <linux/uprobes.h> 13 #include <linux/uaccess.h> << 14 #include <linux/kdebug.h> << 15 8 16 #include <asm/sstep.h> !! 9 #include <asm/branch.h> 17 #include <asm/inst.h> !! 10 #include <asm/cpu-features.h> >> 11 #include <asm/ptrace.h> 18 12 19 #define UPROBE_TRAP_NR UINT_MAX !! 13 #include "probes-common.h" 20 14 21 /** !! 15 static inline int insn_has_delay_slot(const union mips_instruction insn) 22 * is_trap_insn - check if the instruction is << 23 * @insn: instruction to be checked. << 24 * Returns true if @insn is a trap variant. << 25 */ << 26 bool is_trap_insn(uprobe_opcode_t *insn) << 27 { 16 { 28 return (is_trap(*insn)); !! 17 return __insn_has_delay_slot(insn); 29 } 18 } 30 19 31 /** 20 /** 32 * arch_uprobe_analyze_insn !! 21 * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. 33 * @mm: the probed address space. 22 * @mm: the probed address space. 34 * @arch_uprobe: the probepoint information. 23 * @arch_uprobe: the probepoint information. 35 * @addr: vaddr to probe. !! 24 * @addr: virtual address at which to install the probepoint 36 * Return 0 on success or a -ve number on erro 25 * Return 0 on success or a -ve number on error. 37 */ 26 */ 38 int arch_uprobe_analyze_insn(struct arch_uprob !! 27 int arch_uprobe_analyze_insn(struct arch_uprobe *aup, 39 struct mm_struct *mm, unsigned !! 28 struct mm_struct *mm, unsigned long addr) 40 { 29 { >> 30 union mips_instruction inst; >> 31 >> 32 /* >> 33 * For the time being this also blocks attempts to use uprobes with >> 34 * MIPS16 and microMIPS. >> 35 */ 41 if (addr & 0x03) 36 if (addr & 0x03) 42 return -EINVAL; 37 return -EINVAL; 43 38 44 if (cpu_has_feature(CPU_FTR_ARCH_31) & !! 39 inst.word = aup->insn[0]; 45 ppc_inst_prefixed(ppc_inst_read(au !! 40 46 (addr & 0x3f) == 60) { !! 41 if (__insn_is_compact_branch(inst)) { 47 pr_info_ratelimited("Cannot re !! 42 pr_notice("Uprobes for compact branches are not supported\n"); 48 return -EINVAL; 43 return -EINVAL; 49 } 44 } 50 45 51 if (!can_single_step(ppc_inst_val(ppc_ !! 46 aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)]; 52 pr_info_ratelimited("Cannot re !! 47 aup->ixol[1] = UPROBE_BRK_UPROBE_XOL; /* NOP */ 53 return -ENOTSUPP; << 54 } << 55 48 56 return 0; 49 return 0; 57 } 50 } 58 51 >> 52 /** >> 53 * is_trap_insn - check if the instruction is a trap variant >> 54 * @insn: instruction to be checked. >> 55 * Returns true if @insn is a trap variant. >> 56 * >> 57 * This definition overrides the weak definition in kernel/events/uprobes.c. >> 58 * and is needed for the case where an architecture has multiple trap >> 59 * instructions (like PowerPC or MIPS). We treat BREAK just like the more >> 60 * modern conditional trap instructions. >> 61 */ >> 62 bool is_trap_insn(uprobe_opcode_t *insn) >> 63 { >> 64 union mips_instruction inst; >> 65 >> 66 inst.word = *insn; >> 67 >> 68 switch (inst.i_format.opcode) { >> 69 case spec_op: >> 70 switch (inst.r_format.func) { >> 71 case break_op: >> 72 case teq_op: >> 73 case tge_op: >> 74 case tgeu_op: >> 75 case tlt_op: >> 76 case tltu_op: >> 77 case tne_op: >> 78 return true; >> 79 } >> 80 break; >> 81 >> 82 case bcond_op: /* Yes, really ... */ >> 83 switch (inst.u_format.rt) { >> 84 case teqi_op: >> 85 case tgei_op: >> 86 case tgeiu_op: >> 87 case tlti_op: >> 88 case tltiu_op: >> 89 case tnei_op: >> 90 return true; >> 91 } >> 92 break; >> 93 } >> 94 >> 95 return false; >> 96 } >> 97 >> 98 #define UPROBE_TRAP_NR ULONG_MAX >> 99 59 /* 100 /* 60 * arch_uprobe_pre_xol - prepare to execute ou 101 * arch_uprobe_pre_xol - prepare to execute out of line. 61 * @auprobe: the probepoint information. 102 * @auprobe: the probepoint information. 62 * @regs: reflects the saved user state of cur 103 * @regs: reflects the saved user state of current task. 63 */ 104 */ 64 int arch_uprobe_pre_xol(struct arch_uprobe *au !! 105 int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs) 65 { 106 { 66 struct arch_uprobe_task *autask = &cur !! 107 struct uprobe_task *utask = current->utask; 67 108 68 autask->saved_trap_nr = current->threa !! 109 /* >> 110 * Now find the EPC where to resume after the breakpoint has been >> 111 * dealt with. This may require emulation of a branch. >> 112 */ >> 113 aup->resume_epc = regs->cp0_epc + 4; >> 114 if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) { >> 115 __compute_return_epc_for_insn(regs, >> 116 (union mips_instruction) aup->insn[0]); >> 117 aup->resume_epc = regs->cp0_epc; >> 118 } >> 119 utask->autask.saved_trap_nr = current->thread.trap_nr; 69 current->thread.trap_nr = UPROBE_TRAP_ 120 current->thread.trap_nr = UPROBE_TRAP_NR; 70 regs_set_return_ip(regs, current->utas !! 121 regs->cp0_epc = current->utask->xol_vaddr; 71 122 72 user_enable_single_step(current); << 73 return 0; 123 return 0; 74 } 124 } 75 125 76 /** !! 126 int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs) 77 * uprobe_get_swbp_addr - compute address of s << 78 * @regs: Reflects the saved state of the task << 79 * instruction. << 80 * Return the address of the breakpoint instru << 81 */ << 82 unsigned long uprobe_get_swbp_addr(struct pt_r << 83 { 127 { 84 return instruction_pointer(regs); !! 128 struct uprobe_task *utask = current->utask; >> 129 >> 130 current->thread.trap_nr = utask->autask.saved_trap_nr; >> 131 regs->cp0_epc = aup->resume_epc; >> 132 >> 133 return 0; 85 } 134 } 86 135 87 /* 136 /* 88 * If xol insn itself traps and generates a si !! 137 * If xol insn itself traps and generates a signal(Say, 89 * then detect the case where a singlestepped !! 138 * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped 90 * own address. It is assumed that anything li !! 139 * instruction jumps back to its own address. It is assumed that anything 91 * sets thread.trap_nr != UINT_MAX. !! 140 * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. 92 * 141 * 93 * arch_uprobe_pre_xol/arch_uprobe_post_xol sa 142 * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, 94 * arch_uprobe_xol_was_trapped() simply checks 143 * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to 95 * UPROBE_TRAP_NR == UINT_MAX set by arch_upro !! 144 * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). 96 */ 145 */ 97 bool arch_uprobe_xol_was_trapped(struct task_s !! 146 bool arch_uprobe_xol_was_trapped(struct task_struct *tsk) 98 { 147 { 99 if (t->thread.trap_nr != UPROBE_TRAP_N !! 148 if (tsk->thread.trap_nr != UPROBE_TRAP_NR) 100 return true; 149 return true; 101 150 102 return false; 151 return false; 103 } 152 } 104 153 105 /* << 106 * Called after single-stepping. To avoid the << 107 * occur when we temporarily put back the orig << 108 * single-step, we single-stepped a copy of th << 109 * << 110 * This function prepares to resume execution << 111 */ << 112 int arch_uprobe_post_xol(struct arch_uprobe *a << 113 { << 114 struct uprobe_task *utask = current->u << 115 << 116 WARN_ON_ONCE(current->thread.trap_nr ! << 117 << 118 current->thread.trap_nr = utask->autas << 119 << 120 /* << 121 * On powerpc, except for loads and st << 122 * including ones that alter code flow << 123 * are emulated in the kernel. We get << 124 * support doesn't exist and have to f << 125 * to be executed. << 126 */ << 127 regs_set_return_ip(regs, (unsigned lon << 128 << 129 user_disable_single_step(current); << 130 return 0; << 131 } << 132 << 133 /* callback routine for handling exceptions. * << 134 int arch_uprobe_exception_notify(struct notifi 154 int arch_uprobe_exception_notify(struct notifier_block *self, 135 unsigned long !! 155 unsigned long val, void *data) 136 { 156 { 137 struct die_args *args = data; 157 struct die_args *args = data; 138 struct pt_regs *regs = args->regs; 158 struct pt_regs *regs = args->regs; 139 159 140 /* regs == NULL is a kernel bug */ 160 /* regs == NULL is a kernel bug */ 141 if (WARN_ON(!regs)) 161 if (WARN_ON(!regs)) 142 return NOTIFY_DONE; 162 return NOTIFY_DONE; 143 163 144 /* We are only interested in userspace 164 /* We are only interested in userspace traps */ 145 if (!user_mode(regs)) 165 if (!user_mode(regs)) 146 return NOTIFY_DONE; 166 return NOTIFY_DONE; 147 167 148 switch (val) { 168 switch (val) { 149 case DIE_BPT: !! 169 case DIE_UPROBE: 150 if (uprobe_pre_sstep_notifier( 170 if (uprobe_pre_sstep_notifier(regs)) 151 return NOTIFY_STOP; 171 return NOTIFY_STOP; 152 break; 172 break; 153 case DIE_SSTEP: !! 173 case DIE_UPROBE_XOL: 154 if (uprobe_post_sstep_notifier 174 if (uprobe_post_sstep_notifier(regs)) 155 return NOTIFY_STOP; 175 return NOTIFY_STOP; 156 break; 176 break; 157 default: 177 default: 158 break; 178 break; 159 } 179 } 160 return NOTIFY_DONE; !! 180 >> 181 return 0; 161 } 182 } 162 183 163 /* 184 /* 164 * This function gets called when XOL instruct 185 * This function gets called when XOL instruction either gets trapped or 165 * the thread has a fatal signal, so reset the !! 186 * the thread has a fatal signal. Reset the instruction pointer to its 166 * probed address. !! 187 * probed address for the potential restart or for post mortem analysis. 167 */ 188 */ 168 void arch_uprobe_abort_xol(struct arch_uprobe !! 189 void arch_uprobe_abort_xol(struct arch_uprobe *aup, >> 190 struct pt_regs *regs) 169 { 191 { 170 struct uprobe_task *utask = current->u 192 struct uprobe_task *utask = current->utask; 171 193 172 current->thread.trap_nr = utask->autas 194 current->thread.trap_nr = utask->autask.saved_trap_nr; 173 instruction_pointer_set(regs, utask->v 195 instruction_pointer_set(regs, utask->vaddr); 174 << 175 user_disable_single_step(current); << 176 } 196 } 177 197 178 /* !! 198 unsigned long arch_uretprobe_hijack_return_addr( 179 * See if the instruction can be emulated. !! 199 unsigned long trampoline_vaddr, struct pt_regs *regs) 180 * Returns true if instruction was emulated, f << 181 */ << 182 bool arch_uprobe_skip_sstep(struct arch_uprobe << 183 { 200 { 184 int ret; !! 201 unsigned long ra; 185 202 186 /* !! 203 ra = regs->regs[31]; 187 * emulate_step() returns 1 if the ins << 188 * For all other cases, we need to sin << 189 */ << 190 ret = emulate_step(regs, ppc_inst_read << 191 if (ret > 0) << 192 return true; << 193 204 194 return false; !! 205 /* Replace the return address with the trampoline address */ >> 206 regs->regs[31] = trampoline_vaddr; >> 207 >> 208 return ra; 195 } 209 } 196 210 197 unsigned long !! 211 void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 198 arch_uretprobe_hijack_return_addr(unsigned lon !! 212 void *src, unsigned long len) 199 { 213 { 200 unsigned long orig_ret_vaddr; !! 214 unsigned long kaddr, kstart; 201 << 202 orig_ret_vaddr = regs->link; << 203 215 204 /* Replace the return addr with trampo !! 216 /* Initialize the slot */ 205 regs->link = trampoline_vaddr; !! 217 kaddr = (unsigned long)kmap_atomic(page); >> 218 kstart = kaddr + (vaddr & ~PAGE_MASK); >> 219 memcpy((void *)kstart, src, len); >> 220 flush_icache_range(kstart, kstart + len); >> 221 kunmap_atomic((void *)kaddr); >> 222 } 206 223 207 return orig_ret_vaddr; !! 224 /** >> 225 * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs >> 226 * @regs: Reflects the saved state of the task after it has hit a breakpoint >> 227 * instruction. >> 228 * Return the address of the breakpoint instruction. >> 229 * >> 230 * This overrides the weak version in kernel/events/uprobes.c. >> 231 */ >> 232 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) >> 233 { >> 234 return instruction_pointer(regs); 208 } 235 } 209 236 210 bool arch_uretprobe_is_alive(struct return_ins !! 237 /* 211 struct pt_regs !! 238 * See if the instruction can be emulated. >> 239 * Returns true if instruction was emulated, false otherwise. >> 240 * >> 241 * For now we always emulate so this function just returns false. >> 242 */ >> 243 bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 212 { 244 { 213 if (ctx == RP_CHECK_CHAIN_CALL) !! 245 return false; 214 return regs->gpr[1] <= ret->st << 215 else << 216 return regs->gpr[1] < ret->sta << 217 } 246 } 218 247
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.