1/* 2 * arch/arm/probes/kprobes/actions-arm.c 3 * 4 * Copyright (C) 2006, 2007 Motorola Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 */ 15 16/* 17 * We do not have hardware single-stepping on ARM, This 18 * effort is further complicated by the ARM not having a 19 * "next PC" register. Instructions that change the PC 20 * can't be safely single-stepped in a MP environment, so 21 * we have a lot of work to do: 22 * 23 * In the prepare phase: 24 * *) If it is an instruction that does anything 25 * with the CPU mode, we reject it for a kprobe. 26 * (This is out of laziness rather than need. The 27 * instructions could be simulated.) 28 * 29 * *) Otherwise, decode the instruction rewriting its 30 * registers to take fixed, ordered registers and 31 * setting a handler for it to run the instruction. 32 * 33 * In the execution phase by an instruction's handler: 34 * 35 * *) If the PC is written to by the instruction, the 36 * instruction must be fully simulated in software. 37 * 38 * *) Otherwise, a modified form of the instruction is 39 * directly executed. Its handler calls the 40 * instruction in insn[0]. In insn[1] is a 41 * "mov pc, lr" to return. 42 * 43 * Before calling, load up the reordered registers 44 * from the original instruction's registers. If one 45 * of the original input registers is the PC, compute 46 * and adjust the appropriate input register. 47 * 48 * After call completes, copy the output registers to 49 * the original instruction's original registers. 50 * 51 * We don't use a real breakpoint instruction since that 52 * would have us in the kernel go from SVC mode to SVC 53 * mode losing the link register. Instead we use an 54 * undefined instruction. To simplify processing, the 55 * undefined instruction used for kprobes must be reserved 56 * exclusively for kprobes use. 57 * 58 * TODO: ifdef out some instruction decoding based on architecture. 59 */ 60 61#include <linux/kernel.h> 62#include <linux/kprobes.h> 63#include <linux/ptrace.h> 64 65#include "../decode-arm.h" 66#include "core.h" 67#include "checkers.h" 68 69#if __LINUX_ARM_ARCH__ >= 6 70#define BLX(reg) "blx "reg" \n\t" 71#else 72#define BLX(reg) "mov lr, pc \n\t" \ 73 "mov pc, "reg" \n\t" 74#endif 75 76static void __kprobes 77emulate_ldrdstrd(probes_opcode_t insn, 78 struct arch_probes_insn *asi, struct pt_regs *regs) 79{ 80 unsigned long pc = regs->ARM_pc + 4; 81 int rt = (insn >> 12) & 0xf; 82 int rn = (insn >> 16) & 0xf; 83 int rm = insn & 0xf; 84 85 register unsigned long rtv asm("r0") = regs->uregs[rt]; 86 register unsigned long rt2v asm("r1") = regs->uregs[rt+1]; 87 register unsigned long rnv asm("r2") = (rn == 15) ? pc 88 : regs->uregs[rn]; 89 register unsigned long rmv asm("r3") = regs->uregs[rm]; 90 91 __asm__ __volatile__ ( 92 BLX("%[fn]") 93 : "=r" (rtv), "=r" (rt2v), "=r" (rnv) 94 : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), 95 [fn] "r" (asi->insn_fn) 96 : "lr", "memory", "cc" 97 ); 98 99 regs->uregs[rt] = rtv; 100 regs->uregs[rt+1] = rt2v; 101 if (is_writeback(insn)) 102 regs->uregs[rn] = rnv; 103} 104 105static void __kprobes 106emulate_ldr(probes_opcode_t insn, 107 struct arch_probes_insn *asi, struct pt_regs *regs) 108{ 109 unsigned long pc = regs->ARM_pc + 4; 110 int rt = (insn >> 12) & 0xf; 111 int rn = (insn >> 16) & 0xf; 112 int rm = insn & 0xf; 113 114 register unsigned long rtv asm("r0"); 115 register unsigned long rnv asm("r2") = (rn == 15) ? pc 116 : regs->uregs[rn]; 117 register unsigned long rmv asm("r3") = regs->uregs[rm]; 118 119 __asm__ __volatile__ ( 120 BLX("%[fn]") 121 : "=r" (rtv), "=r" (rnv) 122 : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 123 : "lr", "memory", "cc" 124 ); 125 126 if (rt == 15) 127 load_write_pc(rtv, regs); 128 else 129 regs->uregs[rt] = rtv; 130 131 if (is_writeback(insn)) 132 regs->uregs[rn] = rnv; 133} 134 135static void __kprobes 136emulate_str(probes_opcode_t insn, 137 struct arch_probes_insn *asi, struct pt_regs *regs) 138{ 139 unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; 140 unsigned long rnpc = regs->ARM_pc + 4; 141 int rt = (insn >> 12) & 0xf; 142 int rn = (insn >> 16) & 0xf; 143 int rm = insn & 0xf; 144 145 register unsigned long rtv asm("r0") = (rt == 15) ? rtpc 146 : regs->uregs[rt]; 147 register unsigned long rnv asm("r2") = (rn == 15) ? rnpc 148 : regs->uregs[rn]; 149 register unsigned long rmv asm("r3") = regs->uregs[rm]; 150 151 __asm__ __volatile__ ( 152 BLX("%[fn]") 153 : "=r" (rnv) 154 : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 155 : "lr", "memory", "cc" 156 ); 157 158 if (is_writeback(insn)) 159 regs->uregs[rn] = rnv; 160} 161 162static void __kprobes 163emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, 164 struct arch_probes_insn *asi, struct pt_regs *regs) 165{ 166 unsigned long pc = regs->ARM_pc + 4; 167 int rd = (insn >> 12) & 0xf; 168 int rn = (insn >> 16) & 0xf; 169 int rm = insn & 0xf; 170 int rs = (insn >> 8) & 0xf; 171 172 register unsigned long rdv asm("r0") = regs->uregs[rd]; 173 register unsigned long rnv asm("r2") = (rn == 15) ? pc 174 : regs->uregs[rn]; 175 register unsigned long rmv asm("r3") = (rm == 15) ? pc 176 : regs->uregs[rm]; 177 register unsigned long rsv asm("r1") = regs->uregs[rs]; 178 unsigned long cpsr = regs->ARM_cpsr; 179 180 __asm__ __volatile__ ( 181 "msr cpsr_fs, %[cpsr] \n\t" 182 BLX("%[fn]") 183 "mrs %[cpsr], cpsr \n\t" 184 : "=r" (rdv), [cpsr] "=r" (cpsr) 185 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 186 "1" (cpsr), [fn] "r" (asi->insn_fn) 187 : "lr", "memory", "cc" 188 ); 189 190 if (rd == 15) 191 alu_write_pc(rdv, regs); 192 else 193 regs->uregs[rd] = rdv; 194 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 195} 196 197static void __kprobes 198emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn, 199 struct arch_probes_insn *asi, struct pt_regs *regs) 200{ 201 int rd = (insn >> 12) & 0xf; 202 int rn = (insn >> 16) & 0xf; 203 int rm = insn & 0xf; 204 205 register unsigned long rdv asm("r0") = regs->uregs[rd]; 206 register unsigned long rnv asm("r2") = regs->uregs[rn]; 207 register unsigned long rmv asm("r3") = regs->uregs[rm]; 208 unsigned long cpsr = regs->ARM_cpsr; 209 210 __asm__ __volatile__ ( 211 "msr cpsr_fs, %[cpsr] \n\t" 212 BLX("%[fn]") 213 "mrs %[cpsr], cpsr \n\t" 214 : "=r" (rdv), [cpsr] "=r" (cpsr) 215 : "0" (rdv), "r" (rnv), "r" (rmv), 216 "1" (cpsr), [fn] "r" (asi->insn_fn) 217 : "lr", "memory", "cc" 218 ); 219 220 regs->uregs[rd] = rdv; 221 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 222} 223 224static void __kprobes 225emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn, 226 struct arch_probes_insn *asi, 227 struct pt_regs *regs) 228{ 229 int rd = (insn >> 16) & 0xf; 230 int rn = (insn >> 12) & 0xf; 231 int rm = insn & 0xf; 232 int rs = (insn >> 8) & 0xf; 233 234 register unsigned long rdv asm("r2") = regs->uregs[rd]; 235 register unsigned long rnv asm("r0") = regs->uregs[rn]; 236 register unsigned long rmv asm("r3") = regs->uregs[rm]; 237 register unsigned long rsv asm("r1") = regs->uregs[rs]; 238 unsigned long cpsr = regs->ARM_cpsr; 239 240 __asm__ __volatile__ ( 241 "msr cpsr_fs, %[cpsr] \n\t" 242 BLX("%[fn]") 243 "mrs %[cpsr], cpsr \n\t" 244 : "=r" (rdv), [cpsr] "=r" (cpsr) 245 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 246 "1" (cpsr), [fn] "r" (asi->insn_fn) 247 : "lr", "memory", "cc" 248 ); 249 250 regs->uregs[rd] = rdv; 251 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 252} 253 254static void __kprobes 255emulate_rd12rm0_noflags_nopc(probes_opcode_t insn, 256 struct arch_probes_insn *asi, struct pt_regs *regs) 257{ 258 int rd = (insn >> 12) & 0xf; 259 int rm = insn & 0xf; 260 261 register unsigned long rdv asm("r0") = regs->uregs[rd]; 262 register unsigned long rmv asm("r3") = regs->uregs[rm]; 263 264 __asm__ __volatile__ ( 265 BLX("%[fn]") 266 : "=r" (rdv) 267 : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn) 268 : "lr", "memory", "cc" 269 ); 270 271 regs->uregs[rd] = rdv; 272} 273 274static void __kprobes 275emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, 276 struct arch_probes_insn *asi, 277 struct pt_regs *regs) 278{ 279 int rdlo = (insn >> 12) & 0xf; 280 int rdhi = (insn >> 16) & 0xf; 281 int rn = insn & 0xf; 282 int rm = (insn >> 8) & 0xf; 283 284 register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; 285 register unsigned long rdhiv asm("r2") = regs->uregs[rdhi]; 286 register unsigned long rnv asm("r3") = regs->uregs[rn]; 287 register unsigned long rmv asm("r1") = regs->uregs[rm]; 288 unsigned long cpsr = regs->ARM_cpsr; 289 290 __asm__ __volatile__ ( 291 "msr cpsr_fs, %[cpsr] \n\t" 292 BLX("%[fn]") 293 "mrs %[cpsr], cpsr \n\t" 294 : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) 295 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 296 "2" (cpsr), [fn] "r" (asi->insn_fn) 297 : "lr", "memory", "cc" 298 ); 299 300 regs->uregs[rdlo] = rdlov; 301 regs->uregs[rdhi] = rdhiv; 302 regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 303} 304 305const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { 306 [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, 307 [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, 308 [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, 309 [PROBES_MRS] = {.handler = simulate_mrs}, 310 [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, 311 [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, 312 [PROBES_SATURATING_ARITHMETIC] = { 313 .handler = emulate_rd12rn16rm0_rwflags_nopc}, 314 [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 315 [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 316 [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 317 [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, 318 [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, 319 [PROBES_LOAD] = {.handler = emulate_ldr}, 320 [PROBES_STORE_EXTRA] = {.handler = emulate_str}, 321 [PROBES_STORE] = {.handler = emulate_str}, 322 [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, 323 [PROBES_DATA_PROCESSING_REG] = { 324 .handler = emulate_rd12rn16rm0rs8_rwflags}, 325 [PROBES_DATA_PROCESSING_IMM] = { 326 .handler = emulate_rd12rn16rm0rs8_rwflags}, 327 [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, 328 [PROBES_SEV] = {.handler = probes_emulate_none}, 329 [PROBES_WFE] = {.handler = probes_simulate_nop}, 330 [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 331 [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, 332 [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 333 [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 334 [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, 335 [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 336 [PROBES_MUL_ADD_LONG] = { 337 .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 338 [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 339 [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, 340 [PROBES_BRANCH] = {.handler = simulate_bbl}, 341 [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} 342}; 343 344const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; 345