Blame view

arch/sh/kernel/kprobes.c 14.9 KB
d39f54501   Chris Smith   sh: Add kprobes s...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Kernel probes (kprobes) for SuperH
   *
   * Copyright (C) 2007 Chris Smith <chris.smith@st.com>
   * Copyright (C) 2006 Lineo Solutions, Inc.
   *
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   */
  #include <linux/kprobes.h>
  #include <linux/module.h>
  #include <linux/ptrace.h>
  #include <linux/preempt.h>
  #include <linux/kdebug.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
d39f54501   Chris Smith   sh: Add kprobes s...
17
18
19
20
21
  #include <asm/cacheflush.h>
  #include <asm/uaccess.h>
  
  DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
  DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
22
23
24
  static DEFINE_PER_CPU(struct kprobe, saved_current_opcode);
  static DEFINE_PER_CPU(struct kprobe, saved_next_opcode);
  static DEFINE_PER_CPU(struct kprobe, saved_next_opcode2);
d39f54501   Chris Smith   sh: Add kprobes s...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  
  #define OPCODE_JMP(x)	(((x) & 0xF0FF) == 0x402b)
  #define OPCODE_JSR(x)	(((x) & 0xF0FF) == 0x400b)
  #define OPCODE_BRA(x)	(((x) & 0xF000) == 0xa000)
  #define OPCODE_BRAF(x)	(((x) & 0xF0FF) == 0x0023)
  #define OPCODE_BSR(x)	(((x) & 0xF000) == 0xb000)
  #define OPCODE_BSRF(x)	(((x) & 0xF0FF) == 0x0003)
  
  #define OPCODE_BF_S(x)	(((x) & 0xFF00) == 0x8f00)
  #define OPCODE_BT_S(x)	(((x) & 0xFF00) == 0x8d00)
  
  #define OPCODE_BF(x)	(((x) & 0xFF00) == 0x8b00)
  #define OPCODE_BT(x)	(((x) & 0xFF00) == 0x8900)
  
  #define OPCODE_RTS(x)	(((x) & 0x000F) == 0x000b)
  #define OPCODE_RTE(x)	(((x) & 0xFFFF) == 0x002b)
  
  int __kprobes arch_prepare_kprobe(struct kprobe *p)
  {
  	kprobe_opcode_t opcode = *(kprobe_opcode_t *) (p->addr);
  
  	if (OPCODE_RTE(opcode))
  		return -EFAULT;	/* Bad breakpoint */
  
  	p->opcode = opcode;
  
  	return 0;
  }
  
  void __kprobes arch_copy_kprobe(struct kprobe *p)
  {
  	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
  	p->opcode = *p->addr;
  }
  
  void __kprobes arch_arm_kprobe(struct kprobe *p)
  {
  	*p->addr = BREAKPOINT_INSTRUCTION;
  	flush_icache_range((unsigned long)p->addr,
  			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
  }
  
  void __kprobes arch_disarm_kprobe(struct kprobe *p)
  {
  	*p->addr = p->opcode;
  	flush_icache_range((unsigned long)p->addr,
  			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
  }
  
  int __kprobes arch_trampoline_kprobe(struct kprobe *p)
  {
  	if (*p->addr == BREAKPOINT_INSTRUCTION)
  		return 1;
  
  	return 0;
  }
  
  /**
   * If an illegal slot instruction exception occurs for an address
   * containing a kprobe, remove the probe.
   *
   * Returns 0 if the exception was handled successfully, 1 otherwise.
   */
  int __kprobes kprobe_handle_illslot(unsigned long pc)
  {
  	struct kprobe *p = get_kprobe((kprobe_opcode_t *) pc + 1);
  
  	if (p != NULL) {
  		printk("Warning: removing kprobe from delay slot: 0x%.8x
  ",
  		       (unsigned int)pc + 2);
  		unregister_kprobe(p);
  		return 0;
  	}
  
  	return 1;
  }
  
  void __kprobes arch_remove_kprobe(struct kprobe *p)
  {
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
105
106
107
  	struct kprobe *saved = &__get_cpu_var(saved_next_opcode);
  
  	if (saved->addr) {
d39f54501   Chris Smith   sh: Add kprobes s...
108
  		arch_disarm_kprobe(p);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
109
110
111
112
113
114
115
116
117
118
119
  		arch_disarm_kprobe(saved);
  
  		saved->addr = NULL;
  		saved->opcode = 0;
  
  		saved = &__get_cpu_var(saved_next_opcode2);
  		if (saved->addr) {
  			arch_disarm_kprobe(saved);
  
  			saved->addr = NULL;
  			saved->opcode = 0;
d39f54501   Chris Smith   sh: Add kprobes s...
120
121
122
  		}
  	}
  }
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
123
  static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
d39f54501   Chris Smith   sh: Add kprobes s...
124
125
126
127
  {
  	kcb->prev_kprobe.kp = kprobe_running();
  	kcb->prev_kprobe.status = kcb->kprobe_status;
  }
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
128
  static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
d39f54501   Chris Smith   sh: Add kprobes s...
129
130
131
132
  {
  	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
  	kcb->kprobe_status = kcb->prev_kprobe.status;
  }
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
133
134
  static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
  					 struct kprobe_ctlblk *kcb)
d39f54501   Chris Smith   sh: Add kprobes s...
135
136
137
138
139
140
141
142
143
  {
  	__get_cpu_var(current_kprobe) = p;
  }
  
  /*
   * Singlestep is implemented by disabling the current kprobe and setting one
   * on the next instruction, following branches. Two probes are set if the
   * branch is conditional.
   */
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
144
  static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
d39f54501   Chris Smith   sh: Add kprobes s...
145
  {
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
146
  	__get_cpu_var(saved_current_opcode).addr = (kprobe_opcode_t *)regs->pc;
d39f54501   Chris Smith   sh: Add kprobes s...
147
148
  
  	if (p != NULL) {
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
149
  		struct kprobe *op1, *op2;
d39f54501   Chris Smith   sh: Add kprobes s...
150
  		arch_disarm_kprobe(p);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
151
152
  		op1 = &__get_cpu_var(saved_next_opcode);
  		op2 = &__get_cpu_var(saved_next_opcode2);
d39f54501   Chris Smith   sh: Add kprobes s...
153
154
  		if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) {
  			unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
155
  			op1->addr = (kprobe_opcode_t *) regs->regs[reg_nr];
d39f54501   Chris Smith   sh: Add kprobes s...
156
157
  		} else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
  			unsigned long disp = (p->opcode & 0x0FFF);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
158
  			op1->addr =
d39f54501   Chris Smith   sh: Add kprobes s...
159
160
161
162
  			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
  
  		} else if (OPCODE_BRAF(p->opcode) || OPCODE_BSRF(p->opcode)) {
  			unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
163
  			op1->addr =
d39f54501   Chris Smith   sh: Add kprobes s...
164
165
166
167
  			    (kprobe_opcode_t *) (regs->pc + 4 +
  						 regs->regs[reg_nr]);
  
  		} else if (OPCODE_RTS(p->opcode)) {
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
168
  			op1->addr = (kprobe_opcode_t *) regs->pr;
d39f54501   Chris Smith   sh: Add kprobes s...
169
170
171
172
  
  		} else if (OPCODE_BF(p->opcode) || OPCODE_BT(p->opcode)) {
  			unsigned long disp = (p->opcode & 0x00FF);
  			/* case 1 */
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
173
  			op1->addr = p->addr + 1;
d39f54501   Chris Smith   sh: Add kprobes s...
174
  			/* case 2 */
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
175
  			op2->addr =
d39f54501   Chris Smith   sh: Add kprobes s...
176
  			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
177
178
  			op2->opcode = *(op2->addr);
  			arch_arm_kprobe(op2);
d39f54501   Chris Smith   sh: Add kprobes s...
179
180
181
182
  
  		} else if (OPCODE_BF_S(p->opcode) || OPCODE_BT_S(p->opcode)) {
  			unsigned long disp = (p->opcode & 0x00FF);
  			/* case 1 */
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
183
  			op1->addr = p->addr + 2;
d39f54501   Chris Smith   sh: Add kprobes s...
184
  			/* case 2 */
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
185
  			op2->addr =
d39f54501   Chris Smith   sh: Add kprobes s...
186
  			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
187
188
  			op2->opcode = *(op2->addr);
  			arch_arm_kprobe(op2);
d39f54501   Chris Smith   sh: Add kprobes s...
189
190
  
  		} else {
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
191
  			op1->addr = p->addr + 1;
d39f54501   Chris Smith   sh: Add kprobes s...
192
  		}
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
193
194
  		op1->opcode = *(op1->addr);
  		arch_arm_kprobe(op1);
d39f54501   Chris Smith   sh: Add kprobes s...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  	}
  }
  
  /* Called with kretprobe_lock held */
  void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
  				      struct pt_regs *regs)
  {
  	ri->ret_addr = (kprobe_opcode_t *) regs->pr;
  
  	/* Replace the return addr with trampoline addr */
  	regs->pr = (unsigned long)kretprobe_trampoline;
  }
  
  static int __kprobes kprobe_handler(struct pt_regs *regs)
  {
  	struct kprobe *p;
  	int ret = 0;
  	kprobe_opcode_t *addr = NULL;
  	struct kprobe_ctlblk *kcb;
  
  	/*
  	 * We don't want to be preempted for the entire
  	 * duration of kprobe processing
  	 */
  	preempt_disable();
  	kcb = get_kprobe_ctlblk();
  
  	addr = (kprobe_opcode_t *) (regs->pc);
  
  	/* Check we're not actually recursing */
  	if (kprobe_running()) {
  		p = get_kprobe(addr);
  		if (p) {
  			if (kcb->kprobe_status == KPROBE_HIT_SS &&
  			    *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
  				goto no_kprobe;
  			}
  			/* We have reentered the kprobe_handler(), since
  			 * another probe was hit while within the handler.
  			 * We here save the original kprobes variables and
  			 * just single step on the instruction of the new probe
  			 * without calling any user handlers.
  			 */
  			save_previous_kprobe(kcb);
  			set_current_kprobe(p, regs, kcb);
  			kprobes_inc_nmissed_count(p);
  			prepare_singlestep(p, regs);
  			kcb->kprobe_status = KPROBE_REENTER;
  			return 1;
  		} else {
  			p = __get_cpu_var(current_kprobe);
  			if (p->break_handler && p->break_handler(p, regs)) {
  				goto ss_probe;
  			}
  		}
  		goto no_kprobe;
  	}
  
  	p = get_kprobe(addr);
  	if (!p) {
  		/* Not one of ours: let kernel handle it */
734db3770   Paul Mundt   sh: kprobes: Fix ...
256
257
258
259
260
261
262
263
264
265
  		if (*(kprobe_opcode_t *)addr != BREAKPOINT_INSTRUCTION) {
  			/*
  			 * The breakpoint instruction was removed right
  			 * after we hit it. Another cpu has removed
  			 * either a probepoint or a debugger breakpoint
  			 * at this address. In either case, no further
  			 * handling of this interrupt is appropriate.
  			 */
  			ret = 1;
  		}
d39f54501   Chris Smith   sh: Add kprobes s...
266
267
268
269
270
271
272
273
274
  		goto no_kprobe;
  	}
  
  	set_current_kprobe(p, regs, kcb);
  	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
  
  	if (p->pre_handler && p->pre_handler(p, regs))
  		/* handler has already set things up, so skip ss setup */
  		return 1;
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
275
  ss_probe:
d39f54501   Chris Smith   sh: Add kprobes s...
276
277
278
  	prepare_singlestep(p, regs);
  	kcb->kprobe_status = KPROBE_HIT_SS;
  	return 1;
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
279
  no_kprobe:
d39f54501   Chris Smith   sh: Add kprobes s...
280
281
282
283
284
285
286
287
288
  	preempt_enable_no_resched();
  	return ret;
  }
  
  /*
   * For function-return probes, init_kprobes() establishes a probepoint
   * here. When a retprobed function returns, this probe is hit and
   * trampoline_probe_handler() runs, calling the kretprobe's handler.
   */
e7cb016e5   Paul Mundt   sh: Mark kretprob...
289
  static void __used kretprobe_trampoline_holder(void)
d39f54501   Chris Smith   sh: Add kprobes s...
290
  {
6eb2139b3   Paul Mundt   sh: kprobes: kret...
291
292
293
294
295
296
  	asm volatile (".globl kretprobe_trampoline
  "
  		      "kretprobe_trampoline:
  \t"
  		      "nop
  ");
d39f54501   Chris Smith   sh: Add kprobes s...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  }
  
  /*
   * Called when we hit the probe point at kretprobe_trampoline
   */
  int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  {
  	struct kretprobe_instance *ri = NULL;
  	struct hlist_head *head, empty_rp;
  	struct hlist_node *node, *tmp;
  	unsigned long flags, orig_ret_address = 0;
  	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
  
  	INIT_HLIST_HEAD(&empty_rp);
  	kretprobe_hash_lock(current, &head, &flags);
  
  	/*
  	 * It is possible to have multiple instances associated with a given
  	 * task either because an multiple functions in the call path
  	 * have a return probe installed on them, and/or more then one return
  	 * return probe was registered for a target function.
  	 *
  	 * We can handle this because:
  	 *     - instances are always inserted at the head of the list
  	 *     - when multiple return probes are registered for the same
  	 *       function, the first instance's ret_addr will point to the
  	 *       real return address, and all the rest will point to
  	 *       kretprobe_trampoline
  	 */
  	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
  		if (ri->task != current)
  			/* another task is sharing our hash bucket */
  			continue;
  
  		if (ri->rp && ri->rp->handler) {
  			__get_cpu_var(current_kprobe) = &ri->rp->kp;
  			ri->rp->handler(ri, regs);
  			__get_cpu_var(current_kprobe) = NULL;
  		}
  
  		orig_ret_address = (unsigned long)ri->ret_addr;
  		recycle_rp_inst(ri, &empty_rp);
  
  		if (orig_ret_address != trampoline_address)
  			/*
  			 * This is the real return address. Any other
  			 * instances associated with this task are for
  			 * other calls deeper on the call stack
  			 */
  			break;
  	}
  
  	kretprobe_assert(ri, orig_ret_address, trampoline_address);
  
  	regs->pc = orig_ret_address;
  	kretprobe_hash_unlock(current, &flags);
  
  	preempt_enable_no_resched();
  
  	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
  		hlist_del(&ri->hlist);
  		kfree(ri);
  	}
  
  	return orig_ret_address;
  }
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
363
  static int __kprobes post_kprobe_handler(struct pt_regs *regs)
d39f54501   Chris Smith   sh: Add kprobes s...
364
365
366
367
368
369
370
371
372
373
374
375
376
  {
  	struct kprobe *cur = kprobe_running();
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
  	kprobe_opcode_t *addr = NULL;
  	struct kprobe *p = NULL;
  
  	if (!cur)
  		return 0;
  
  	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
  		kcb->kprobe_status = KPROBE_HIT_SSDONE;
  		cur->post_handler(cur, regs, 0);
  	}
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
377
378
379
380
381
  	p = &__get_cpu_var(saved_next_opcode);
  	if (p->addr) {
  		arch_disarm_kprobe(p);
  		p->addr = NULL;
  		p->opcode = 0;
d39f54501   Chris Smith   sh: Add kprobes s...
382

57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
383
384
  		addr = __get_cpu_var(saved_current_opcode).addr;
  		__get_cpu_var(saved_current_opcode).addr = NULL;
d39f54501   Chris Smith   sh: Add kprobes s...
385
386
387
  
  		p = get_kprobe(addr);
  		arch_arm_kprobe(p);
57fcfdf9b   Paul Mundt   sh: kprobes SMP s...
388
389
390
391
392
  		p = &__get_cpu_var(saved_next_opcode2);
  		if (p->addr) {
  			arch_disarm_kprobe(p);
  			p->addr = NULL;
  			p->opcode = 0;
d39f54501   Chris Smith   sh: Add kprobes s...
393
394
  		}
  	}
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
395
  	/* Restore back the original saved kprobes variables and continue. */
d39f54501   Chris Smith   sh: Add kprobes s...
396
397
398
399
  	if (kcb->kprobe_status == KPROBE_REENTER) {
  		restore_previous_kprobe(kcb);
  		goto out;
  	}
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
400

d39f54501   Chris Smith   sh: Add kprobes s...
401
  	reset_current_kprobe();
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
402
  out:
d39f54501   Chris Smith   sh: Add kprobes s...
403
404
405
406
  	preempt_enable_no_resched();
  
  	return 1;
  }
037c10a61   Paul Mundt   sh: kprobes: Hook...
407
  int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
d39f54501   Chris Smith   sh: Add kprobes s...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
  {
  	struct kprobe *cur = kprobe_running();
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
  	const struct exception_table_entry *entry;
  
  	switch (kcb->kprobe_status) {
  	case KPROBE_HIT_SS:
  	case KPROBE_REENTER:
  		/*
  		 * We are here because the instruction being single
  		 * stepped caused a page fault. We reset the current
  		 * kprobe, point the pc back to the probe address
  		 * and allow the page fault handler to continue as a
  		 * normal page fault.
  		 */
  		regs->pc = (unsigned long)cur->addr;
  		if (kcb->kprobe_status == KPROBE_REENTER)
  			restore_previous_kprobe(kcb);
  		else
  			reset_current_kprobe();
  		preempt_enable_no_resched();
  		break;
  	case KPROBE_HIT_ACTIVE:
  	case KPROBE_HIT_SSDONE:
  		/*
  		 * We increment the nmissed count for accounting,
  		 * we can also use npre/npostfault count for accounting
  		 * these specific fault cases.
  		 */
  		kprobes_inc_nmissed_count(cur);
  
  		/*
  		 * We come here because instructions in the pre/post
  		 * handler caused the page_fault, this could happen
  		 * if handler tries to access user space by
  		 * copy_from_user(), get_user() etc. Let the
  		 * user-specified handler try to fix it first.
  		 */
  		if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
  			return 1;
  
  		/*
  		 * In case the user-specified fault handler returned
  		 * zero, try to fix up.
  		 */
  		if ((entry = search_exception_tables(regs->pc)) != NULL) {
  			regs->pc = entry->fixup;
  			return 1;
  		}
  
  		/*
  		 * fixup_exception() could not handle it,
  		 * Let do_page_fault() fix it.
  		 */
  		break;
  	default:
  		break;
  	}
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
466

d39f54501   Chris Smith   sh: Add kprobes s...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  	return 0;
  }
  
  /*
   * Wrapper routine to for handling exceptions.
   */
  int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
  				       unsigned long val, void *data)
  {
  	struct kprobe *p = NULL;
  	struct die_args *args = (struct die_args *)data;
  	int ret = NOTIFY_DONE;
  	kprobe_opcode_t *addr = NULL;
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
  
  	addr = (kprobe_opcode_t *) (args->regs->pc);
  	if (val == DIE_TRAP) {
  		if (!kprobe_running()) {
  			if (kprobe_handler(args->regs)) {
  				ret = NOTIFY_STOP;
  			} else {
  				/* Not a kprobe trap */
ee386de77   Paul Mundt   sh: kprobes: Defa...
489
  				ret = NOTIFY_DONE;
d39f54501   Chris Smith   sh: Add kprobes s...
490
491
492
493
494
495
496
497
498
499
500
501
  			}
  		} else {
  			p = get_kprobe(addr);
  			if ((kcb->kprobe_status == KPROBE_HIT_SS) ||
  			    (kcb->kprobe_status == KPROBE_REENTER)) {
  				if (post_kprobe_handler(args->regs))
  					ret = NOTIFY_STOP;
  			} else {
  				if (kprobe_handler(args->regs)) {
  					ret = NOTIFY_STOP;
  				} else {
  					p = __get_cpu_var(current_kprobe);
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
502
503
  					if (p->break_handler &&
  					    p->break_handler(p, args->regs))
d39f54501   Chris Smith   sh: Add kprobes s...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  						ret = NOTIFY_STOP;
  				}
  			}
  		}
  	}
  
  	return ret;
  }
  
  int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  {
  	struct jprobe *jp = container_of(p, struct jprobe, kp);
  	unsigned long addr;
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
  
  	kcb->jprobe_saved_regs = *regs;
  	kcb->jprobe_saved_r15 = regs->regs[15];
  	addr = kcb->jprobe_saved_r15;
  
  	/*
  	 * TBD: As Linus pointed out, gcc assumes that the callee
  	 * owns the argument space and could overwrite it, e.g.
  	 * tailcall optimization. So, to be absolutely safe
  	 * we also save and restore enough stack bytes to cover
  	 * the argument area.
  	 */
  	memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
  	       MIN_STACK_SIZE(addr));
  
  	regs->pc = (unsigned long)(jp->entry);
  
  	return 1;
  }
  
  void __kprobes jprobe_return(void)
  {
174b5c992   Paul Mundt   sh: kprobes: Use ...
540
541
542
543
  	asm volatile ("trapa #0x3a
  \t" "jprobe_return_end:
  \t" "nop
  \t");
d39f54501   Chris Smith   sh: Add kprobes s...
544
545
546
547
548
  }
  
  int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
  {
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
d39f54501   Chris Smith   sh: Add kprobes s...
549
  	unsigned long stack_addr = kcb->jprobe_saved_r15;
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
550
  	u8 *addr = (u8 *)regs->pc;
d39f54501   Chris Smith   sh: Add kprobes s...
551

4eb5845d6   Paul Mundt   sh: kprobes: __kp...
552
553
  	if ((addr >= (u8 *)jprobe_return) &&
  	    (addr <= (u8 *)jprobe_return_end)) {
d39f54501   Chris Smith   sh: Add kprobes s...
554
  		*regs = kcb->jprobe_saved_regs;
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
555
  		memcpy((kprobe_opcode_t *)stack_addr, kcb->jprobes_stack,
d39f54501   Chris Smith   sh: Add kprobes s...
556
557
558
  		       MIN_STACK_SIZE(stack_addr));
  
  		kcb->kprobe_status = KPROBE_HIT_SS;
247bc6d2a   Paul Mundt   sh: kprobes: Fix ...
559
  		preempt_enable_no_resched();
d39f54501   Chris Smith   sh: Add kprobes s...
560
561
  		return 1;
  	}
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
562

d39f54501   Chris Smith   sh: Add kprobes s...
563
564
565
566
  	return 0;
  }
  
  static struct kprobe trampoline_p = {
4eb5845d6   Paul Mundt   sh: kprobes: __kp...
567
  	.addr = (kprobe_opcode_t *)&kretprobe_trampoline,
d39f54501   Chris Smith   sh: Add kprobes s...
568
569
570
571
572
  	.pre_handler = trampoline_probe_handler
  };
  
  int __init arch_init_kprobes(void)
  {
d39f54501   Chris Smith   sh: Add kprobes s...
573
574
  	return register_kprobe(&trampoline_p);
  }