| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 1 | /* | 
|  | 2 | * arch/arm/kernel/kprobes.c | 
|  | 3 | * | 
|  | 4 | * Kprobes on ARM | 
|  | 5 | * | 
|  | 6 | * Abhishek Sagar <sagar.abhishek@gmail.com> | 
|  | 7 | * Copyright (C) 2006, 2007 Motorola Inc. | 
|  | 8 | * | 
|  | 9 | * Nicolas Pitre <nico@marvell.com> | 
|  | 10 | * Copyright (C) 2007 Marvell Ltd. | 
|  | 11 | * | 
|  | 12 | * This program is free software; you can redistribute it and/or modify | 
|  | 13 | * it under the terms of the GNU General Public License version 2 as | 
|  | 14 | * published by the Free Software Foundation. | 
|  | 15 | * | 
|  | 16 | * This program is distributed in the hope that it will be useful, | 
|  | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 19 | * General Public License for more details. | 
|  | 20 | */ | 
|  | 21 |  | 
|  | 22 | #include <linux/kernel.h> | 
|  | 23 | #include <linux/kprobes.h> | 
|  | 24 | #include <linux/module.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 25 | #include <linux/slab.h> | 
| Frederic Riss | 2003b7a | 2009-09-21 08:43:30 +0100 | [diff] [blame] | 26 | #include <linux/stop_machine.h> | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 27 | #include <linux/stringify.h> | 
|  | 28 | #include <asm/traps.h> | 
|  | 29 | #include <asm/cacheflush.h> | 
|  | 30 |  | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 31 | #define MIN_STACK_SIZE(addr) 				\ | 
|  | 32 | min((unsigned long)MAX_STACK_SIZE,		\ | 
|  | 33 | (unsigned long)current_thread_info() + THREAD_START_SP - (addr)) | 
|  | 34 |  | 
|  | 35 | #define flush_insns(addr, cnt) 				\ | 
|  | 36 | flush_icache_range((unsigned long)(addr),	\ | 
|  | 37 | (unsigned long)(addr) +	\ | 
|  | 38 | sizeof(kprobe_opcode_t) * (cnt)) | 
|  | 39 |  | 
|  | 40 | /* Used as a marker in ARM_pc to note when we're in a jprobe. */ | 
|  | 41 | #define JPROBE_MAGIC_ADDR		0xffffffff | 
|  | 42 |  | 
|  | 43 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 
|  | 44 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 
|  | 45 |  | 
|  | 46 |  | 
|  | 47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 
|  | 48 | { | 
|  | 49 | kprobe_opcode_t insn; | 
|  | 50 | kprobe_opcode_t tmp_insn[MAX_INSN_SIZE]; | 
|  | 51 | unsigned long addr = (unsigned long)p->addr; | 
|  | 52 | int is; | 
|  | 53 |  | 
| Nicolas Pitre | 785d3cd | 2007-12-03 15:27:56 -0500 | [diff] [blame] | 54 | if (addr & 0x3 || in_exception_text(addr)) | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 55 | return -EINVAL; | 
|  | 56 |  | 
|  | 57 | insn = *p->addr; | 
|  | 58 | p->opcode = insn; | 
|  | 59 | p->ainsn.insn = tmp_insn; | 
|  | 60 |  | 
|  | 61 | switch (arm_kprobe_decode_insn(insn, &p->ainsn)) { | 
|  | 62 | case INSN_REJECTED:	/* not supported */ | 
|  | 63 | return -EINVAL; | 
|  | 64 |  | 
|  | 65 | case INSN_GOOD:		/* instruction uses slot */ | 
|  | 66 | p->ainsn.insn = get_insn_slot(); | 
|  | 67 | if (!p->ainsn.insn) | 
|  | 68 | return -ENOMEM; | 
|  | 69 | for (is = 0; is < MAX_INSN_SIZE; ++is) | 
|  | 70 | p->ainsn.insn[is] = tmp_insn[is]; | 
| Nicolas Pitre | 8f79ff0 | 2008-04-23 18:44:15 -0400 | [diff] [blame] | 71 | flush_insns(p->ainsn.insn, MAX_INSN_SIZE); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 72 | break; | 
|  | 73 |  | 
|  | 74 | case INSN_GOOD_NO_SLOT:	/* instruction doesn't need insn slot */ | 
|  | 75 | p->ainsn.insn = NULL; | 
|  | 76 | break; | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | return 0; | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 
|  | 83 | { | 
|  | 84 | *p->addr = KPROBE_BREAKPOINT_INSTRUCTION; | 
|  | 85 | flush_insns(p->addr, 1); | 
|  | 86 | } | 
|  | 87 |  | 
| Frederic Riss | 2003b7a | 2009-09-21 08:43:30 +0100 | [diff] [blame] | 88 | /* | 
|  | 89 | * The actual disarming is done here on each CPU and synchronized using | 
|  | 90 | * stop_machine. This synchronization is necessary on SMP to avoid removing | 
|  | 91 | * a probe between the moment the 'Undefined Instruction' exception is raised | 
|  | 92 | * and the moment the exception handler reads the faulting instruction from | 
|  | 93 | * memory. | 
|  | 94 | */ | 
|  | 95 | int __kprobes __arch_disarm_kprobe(void *p) | 
|  | 96 | { | 
|  | 97 | struct kprobe *kp = p; | 
|  | 98 | *kp->addr = kp->opcode; | 
|  | 99 | flush_insns(kp->addr, 1); | 
|  | 100 | return 0; | 
|  | 101 | } | 
|  | 102 |  | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 103 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 
|  | 104 | { | 
| Frederic Riss | 2003b7a | 2009-09-21 08:43:30 +0100 | [diff] [blame] | 105 | stop_machine(__arch_disarm_kprobe, p, &cpu_online_map); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 106 | } | 
|  | 107 |  | 
|  | 108 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 
|  | 109 | { | 
|  | 110 | if (p->ainsn.insn) { | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 111 | free_insn_slot(p->ainsn.insn, 0); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 112 | p->ainsn.insn = NULL; | 
|  | 113 | } | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | 
|  | 117 | { | 
|  | 118 | kcb->prev_kprobe.kp = kprobe_running(); | 
|  | 119 | kcb->prev_kprobe.status = kcb->kprobe_status; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | 
|  | 123 | { | 
|  | 124 | __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; | 
|  | 125 | kcb->kprobe_status = kcb->prev_kprobe.status; | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | static void __kprobes set_current_kprobe(struct kprobe *p) | 
|  | 129 | { | 
|  | 130 | __get_cpu_var(current_kprobe) = p; | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, | 
|  | 134 | struct kprobe_ctlblk *kcb) | 
|  | 135 | { | 
|  | 136 | regs->ARM_pc += 4; | 
| Jon Medhurst | 073090c | 2011-04-06 11:17:09 +0100 | [diff] [blame] | 137 | if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) | 
|  | 138 | p->ainsn.insn_handler(p, regs); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 139 | } | 
|  | 140 |  | 
|  | 141 | /* | 
|  | 142 | * Called with IRQs disabled. IRQs must remain disabled from that point | 
|  | 143 | * all the way until processing this kprobe is complete.  The current | 
|  | 144 | * kprobes implementation cannot process more than one nested level of | 
|  | 145 | * kprobe, and that level is reserved for user kprobe handlers, so we can't | 
|  | 146 | * risk encountering a new kprobe in an interrupt handler. | 
|  | 147 | */ | 
|  | 148 | void __kprobes kprobe_handler(struct pt_regs *regs) | 
|  | 149 | { | 
|  | 150 | struct kprobe *p, *cur; | 
|  | 151 | struct kprobe_ctlblk *kcb; | 
|  | 152 | kprobe_opcode_t	*addr = (kprobe_opcode_t *)regs->ARM_pc; | 
|  | 153 |  | 
|  | 154 | kcb = get_kprobe_ctlblk(); | 
|  | 155 | cur = kprobe_running(); | 
|  | 156 | p = get_kprobe(addr); | 
|  | 157 |  | 
|  | 158 | if (p) { | 
|  | 159 | if (cur) { | 
|  | 160 | /* Kprobe is pending, so we're recursing. */ | 
|  | 161 | switch (kcb->kprobe_status) { | 
|  | 162 | case KPROBE_HIT_ACTIVE: | 
|  | 163 | case KPROBE_HIT_SSDONE: | 
|  | 164 | /* A pre- or post-handler probe got us here. */ | 
|  | 165 | kprobes_inc_nmissed_count(p); | 
|  | 166 | save_previous_kprobe(kcb); | 
|  | 167 | set_current_kprobe(p); | 
|  | 168 | kcb->kprobe_status = KPROBE_REENTER; | 
|  | 169 | singlestep(p, regs, kcb); | 
|  | 170 | restore_previous_kprobe(kcb); | 
|  | 171 | break; | 
|  | 172 | default: | 
|  | 173 | /* impossible cases */ | 
|  | 174 | BUG(); | 
|  | 175 | } | 
|  | 176 | } else { | 
|  | 177 | set_current_kprobe(p); | 
|  | 178 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | 
|  | 179 |  | 
|  | 180 | /* | 
|  | 181 | * If we have no pre-handler or it returned 0, we | 
|  | 182 | * continue with normal processing.  If we have a | 
|  | 183 | * pre-handler and it returned non-zero, it prepped | 
|  | 184 | * for calling the break_handler below on re-entry, | 
|  | 185 | * so get out doing nothing more here. | 
|  | 186 | */ | 
|  | 187 | if (!p->pre_handler || !p->pre_handler(p, regs)) { | 
|  | 188 | kcb->kprobe_status = KPROBE_HIT_SS; | 
|  | 189 | singlestep(p, regs, kcb); | 
|  | 190 | if (p->post_handler) { | 
|  | 191 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | 
|  | 192 | p->post_handler(p, regs, 0); | 
|  | 193 | } | 
|  | 194 | reset_current_kprobe(); | 
|  | 195 | } | 
|  | 196 | } | 
|  | 197 | } else if (cur) { | 
|  | 198 | /* We probably hit a jprobe.  Call its break handler. */ | 
|  | 199 | if (cur->break_handler && cur->break_handler(cur, regs)) { | 
|  | 200 | kcb->kprobe_status = KPROBE_HIT_SS; | 
|  | 201 | singlestep(cur, regs, kcb); | 
|  | 202 | if (cur->post_handler) { | 
|  | 203 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | 
|  | 204 | cur->post_handler(cur, regs, 0); | 
|  | 205 | } | 
|  | 206 | } | 
|  | 207 | reset_current_kprobe(); | 
|  | 208 | } else { | 
|  | 209 | /* | 
|  | 210 | * The probe was removed and a race is in progress. | 
|  | 211 | * There is nothing we can do about it.  Let's restart | 
|  | 212 | * the instruction.  By the time we can restart, the | 
|  | 213 | * real instruction will be there. | 
|  | 214 | */ | 
|  | 215 | } | 
|  | 216 | } | 
|  | 217 |  | 
| Nicolas Pitre | 3305a60 | 2008-08-19 04:15:23 +0100 | [diff] [blame] | 218 | static int __kprobes kprobe_trap_handler(struct pt_regs *regs, unsigned int instr) | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 219 | { | 
| Nicolas Pitre | 3305a60 | 2008-08-19 04:15:23 +0100 | [diff] [blame] | 220 | unsigned long flags; | 
|  | 221 | local_irq_save(flags); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 222 | kprobe_handler(regs); | 
| Nicolas Pitre | 3305a60 | 2008-08-19 04:15:23 +0100 | [diff] [blame] | 223 | local_irq_restore(flags); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 224 | return 0; | 
|  | 225 | } | 
|  | 226 |  | 
|  | 227 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr) | 
|  | 228 | { | 
|  | 229 | struct kprobe *cur = kprobe_running(); | 
|  | 230 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 
|  | 231 |  | 
|  | 232 | switch (kcb->kprobe_status) { | 
|  | 233 | case KPROBE_HIT_SS: | 
|  | 234 | case KPROBE_REENTER: | 
|  | 235 | /* | 
|  | 236 | * We are here because the instruction being single | 
|  | 237 | * stepped caused a page fault. We reset the current | 
|  | 238 | * kprobe and the PC to point back to the probe address | 
|  | 239 | * and allow the page fault handler to continue as a | 
|  | 240 | * normal page fault. | 
|  | 241 | */ | 
|  | 242 | regs->ARM_pc = (long)cur->addr; | 
|  | 243 | if (kcb->kprobe_status == KPROBE_REENTER) { | 
|  | 244 | restore_previous_kprobe(kcb); | 
|  | 245 | } else { | 
|  | 246 | reset_current_kprobe(); | 
|  | 247 | } | 
|  | 248 | break; | 
|  | 249 |  | 
|  | 250 | case KPROBE_HIT_ACTIVE: | 
|  | 251 | case KPROBE_HIT_SSDONE: | 
|  | 252 | /* | 
|  | 253 | * We increment the nmissed count for accounting, | 
|  | 254 | * we can also use npre/npostfault count for accounting | 
|  | 255 | * these specific fault cases. | 
|  | 256 | */ | 
|  | 257 | kprobes_inc_nmissed_count(cur); | 
|  | 258 |  | 
|  | 259 | /* | 
|  | 260 | * We come here because instructions in the pre/post | 
|  | 261 | * handler caused the page_fault, this could happen | 
|  | 262 | * if handler tries to access user space by | 
|  | 263 | * copy_from_user(), get_user() etc. Let the | 
|  | 264 | * user-specified handler try to fix it. | 
|  | 265 | */ | 
|  | 266 | if (cur->fault_handler && cur->fault_handler(cur, regs, fsr)) | 
|  | 267 | return 1; | 
|  | 268 | break; | 
|  | 269 |  | 
|  | 270 | default: | 
|  | 271 | break; | 
|  | 272 | } | 
|  | 273 |  | 
|  | 274 | return 0; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | 
|  | 278 | unsigned long val, void *data) | 
|  | 279 | { | 
|  | 280 | /* | 
|  | 281 | * notify_die() is currently never called on ARM, | 
|  | 282 | * so this callback is currently empty. | 
|  | 283 | */ | 
|  | 284 | return NOTIFY_DONE; | 
|  | 285 | } | 
|  | 286 |  | 
|  | 287 | /* | 
|  | 288 | * When a retprobed function returns, trampoline_handler() is called, | 
|  | 289 | * calling the kretprobe's handler. We construct a struct pt_regs to | 
|  | 290 | * give a view of registers r0-r11 to the user return-handler.  This is | 
|  | 291 | * not a complete pt_regs structure, but that should be plenty sufficient | 
|  | 292 | * for kretprobe handlers which should normally be interested in r0 only | 
|  | 293 | * anyway. | 
|  | 294 | */ | 
| Abhishek Sagar | e077341 | 2008-05-31 14:24:02 +0530 | [diff] [blame] | 295 | void __naked __kprobes kretprobe_trampoline(void) | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 296 | { | 
|  | 297 | __asm__ __volatile__ ( | 
|  | 298 | "stmdb	sp!, {r0 - r11}		\n\t" | 
|  | 299 | "mov	r0, sp			\n\t" | 
|  | 300 | "bl	trampoline_handler	\n\t" | 
|  | 301 | "mov	lr, r0			\n\t" | 
|  | 302 | "ldmia	sp!, {r0 - r11}		\n\t" | 
|  | 303 | "mov	pc, lr			\n\t" | 
|  | 304 | : : : "memory"); | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | /* Called from kretprobe_trampoline */ | 
|  | 308 | static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | 
|  | 309 | { | 
|  | 310 | struct kretprobe_instance *ri = NULL; | 
|  | 311 | struct hlist_head *head, empty_rp; | 
|  | 312 | struct hlist_node *node, *tmp; | 
|  | 313 | unsigned long flags, orig_ret_address = 0; | 
|  | 314 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 
|  | 315 |  | 
|  | 316 | INIT_HLIST_HEAD(&empty_rp); | 
| Srinivasa D S | ef53d9c | 2008-07-25 01:46:04 -0700 | [diff] [blame] | 317 | kretprobe_hash_lock(current, &head, &flags); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 318 |  | 
|  | 319 | /* | 
|  | 320 | * It is possible to have multiple instances associated with a given | 
|  | 321 | * task either because multiple functions in the call path have | 
|  | 322 | * a return probe installed on them, and/or more than one return | 
|  | 323 | * probe was registered for a target function. | 
|  | 324 | * | 
|  | 325 | * We can handle this because: | 
|  | 326 | *     - instances are always inserted at the head of the list | 
|  | 327 | *     - when multiple return probes are registered for the same | 
|  | 328 | *       function, the first instance's ret_addr will point to the | 
|  | 329 | *       real return address, and all the rest will point to | 
|  | 330 | *       kretprobe_trampoline | 
|  | 331 | */ | 
|  | 332 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 
|  | 333 | if (ri->task != current) | 
|  | 334 | /* another task is sharing our hash bucket */ | 
|  | 335 | continue; | 
|  | 336 |  | 
|  | 337 | if (ri->rp && ri->rp->handler) { | 
|  | 338 | __get_cpu_var(current_kprobe) = &ri->rp->kp; | 
|  | 339 | get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; | 
|  | 340 | ri->rp->handler(ri, regs); | 
|  | 341 | __get_cpu_var(current_kprobe) = NULL; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | orig_ret_address = (unsigned long)ri->ret_addr; | 
|  | 345 | recycle_rp_inst(ri, &empty_rp); | 
|  | 346 |  | 
|  | 347 | if (orig_ret_address != trampoline_address) | 
|  | 348 | /* | 
|  | 349 | * This is the real return address. Any other | 
|  | 350 | * instances associated with this task are for | 
|  | 351 | * other calls deeper on the call stack | 
|  | 352 | */ | 
|  | 353 | break; | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 
| Srinivasa D S | ef53d9c | 2008-07-25 01:46:04 -0700 | [diff] [blame] | 357 | kretprobe_hash_unlock(current, &flags); | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 358 |  | 
|  | 359 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 
|  | 360 | hlist_del(&ri->hlist); | 
|  | 361 | kfree(ri); | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | return (void *)orig_ret_address; | 
|  | 365 | } | 
|  | 366 |  | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 367 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 
|  | 368 | struct pt_regs *regs) | 
|  | 369 | { | 
|  | 370 | ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr; | 
|  | 371 |  | 
|  | 372 | /* Replace the return addr with trampoline addr. */ | 
|  | 373 | regs->ARM_lr = (unsigned long)&kretprobe_trampoline; | 
|  | 374 | } | 
|  | 375 |  | 
|  | 376 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 
|  | 377 | { | 
|  | 378 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 
|  | 379 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 
|  | 380 | long sp_addr = regs->ARM_sp; | 
|  | 381 |  | 
|  | 382 | kcb->jprobe_saved_regs = *regs; | 
|  | 383 | memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr)); | 
|  | 384 | regs->ARM_pc = (long)jp->entry; | 
|  | 385 | regs->ARM_cpsr |= PSR_I_BIT; | 
|  | 386 | preempt_disable(); | 
|  | 387 | return 1; | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | void __kprobes jprobe_return(void) | 
|  | 391 | { | 
|  | 392 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 
|  | 393 |  | 
|  | 394 | __asm__ __volatile__ ( | 
|  | 395 | /* | 
|  | 396 | * Setup an empty pt_regs. Fill SP and PC fields as | 
|  | 397 | * they're needed by longjmp_break_handler. | 
| Mika Westerberg | 782a0fd | 2010-03-29 06:59:16 +0100 | [diff] [blame] | 398 | * | 
|  | 399 | * We allocate some slack between the original SP and start of | 
|  | 400 | * our fabricated regs. To be precise we want to have worst case | 
|  | 401 | * covered which is STMFD with all 16 regs so we allocate 2 * | 
|  | 402 | * sizeof(struct_pt_regs)). | 
|  | 403 | * | 
|  | 404 | * This is to prevent any simulated instruction from writing | 
|  | 405 | * over the regs when they are accessing the stack. | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 406 | */ | 
|  | 407 | "sub    sp, %0, %1		\n\t" | 
|  | 408 | "ldr    r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t" | 
|  | 409 | "str    %0, [sp, %2]		\n\t" | 
|  | 410 | "str    r0, [sp, %3]		\n\t" | 
|  | 411 | "mov    r0, sp			\n\t" | 
|  | 412 | "bl     kprobe_handler		\n\t" | 
|  | 413 |  | 
|  | 414 | /* | 
|  | 415 | * Return to the context saved by setjmp_pre_handler | 
|  | 416 | * and restored by longjmp_break_handler. | 
|  | 417 | */ | 
|  | 418 | "ldr	r0, [sp, %4]		\n\t" | 
|  | 419 | "msr	cpsr_cxsf, r0		\n\t" | 
|  | 420 | "ldmia	sp, {r0 - pc}		\n\t" | 
|  | 421 | : | 
|  | 422 | : "r" (kcb->jprobe_saved_regs.ARM_sp), | 
| Mika Westerberg | 782a0fd | 2010-03-29 06:59:16 +0100 | [diff] [blame] | 423 | "I" (sizeof(struct pt_regs) * 2), | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 424 | "J" (offsetof(struct pt_regs, ARM_sp)), | 
|  | 425 | "J" (offsetof(struct pt_regs, ARM_pc)), | 
|  | 426 | "J" (offsetof(struct pt_regs, ARM_cpsr)) | 
|  | 427 | : "memory", "cc"); | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 
|  | 431 | { | 
|  | 432 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 
|  | 433 | long stack_addr = kcb->jprobe_saved_regs.ARM_sp; | 
|  | 434 | long orig_sp = regs->ARM_sp; | 
|  | 435 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 
|  | 436 |  | 
|  | 437 | if (regs->ARM_pc == JPROBE_MAGIC_ADDR) { | 
|  | 438 | if (orig_sp != stack_addr) { | 
|  | 439 | struct pt_regs *saved_regs = | 
|  | 440 | (struct pt_regs *)kcb->jprobe_saved_regs.ARM_sp; | 
|  | 441 | printk("current sp %lx does not match saved sp %lx\n", | 
|  | 442 | orig_sp, stack_addr); | 
|  | 443 | printk("Saved registers for jprobe %p\n", jp); | 
|  | 444 | show_regs(saved_regs); | 
|  | 445 | printk("Current registers\n"); | 
|  | 446 | show_regs(regs); | 
|  | 447 | BUG(); | 
|  | 448 | } | 
|  | 449 | *regs = kcb->jprobe_saved_regs; | 
|  | 450 | memcpy((void *)stack_addr, kcb->jprobes_stack, | 
|  | 451 | MIN_STACK_SIZE(stack_addr)); | 
|  | 452 | preempt_enable_no_resched(); | 
|  | 453 | return 1; | 
|  | 454 | } | 
|  | 455 | return 0; | 
|  | 456 | } | 
|  | 457 |  | 
| Nicolas Pitre | b24061f | 2008-03-04 21:56:21 +0100 | [diff] [blame] | 458 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | 
|  | 459 | { | 
|  | 460 | return 0; | 
|  | 461 | } | 
|  | 462 |  | 
| Abhishek Sagar | 24ba613 | 2007-06-11 22:20:10 +0000 | [diff] [blame] | 463 | static struct undef_hook kprobes_break_hook = { | 
|  | 464 | .instr_mask	= 0xffffffff, | 
|  | 465 | .instr_val	= KPROBE_BREAKPOINT_INSTRUCTION, | 
|  | 466 | .cpsr_mask	= MODE_MASK, | 
|  | 467 | .cpsr_val	= SVC_MODE, | 
|  | 468 | .fn		= kprobe_trap_handler, | 
|  | 469 | }; | 
|  | 470 |  | 
|  | 471 | int __init arch_init_kprobes() | 
|  | 472 | { | 
|  | 473 | arm_kprobe_decode_init(); | 
|  | 474 | register_undef_hook(&kprobes_break_hook); | 
|  | 475 | return 0; | 
|  | 476 | } |