1
2
3
4
5
6#include <linux/config.h>
7#include <linux/kernel.h>
8#include <linux/kprobes.h>
9
10#include <asm/kdebug.h>
11#include <asm/signal.h>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41int arch_prepare_kprobe(struct kprobe *p)
42{
43 return 0;
44}
45
46void arch_copy_kprobe(struct kprobe *p)
47{
48 p->ainsn.insn[0] = *p->addr;
49 p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
50}
51
52void arch_remove_kprobe(struct kprobe *p)
53{
54}
55
56
57#define KPROBE_HIT_ACTIVE 0x00000001
58#define KPROBE_HIT_SS 0x00000002
59
60static struct kprobe *current_kprobe;
61static unsigned long current_kprobe_orig_tnpc;
62static unsigned long current_kprobe_orig_tstate_pil;
63static unsigned int kprobe_status;
64
65static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
66{
67 current_kprobe_orig_tnpc = regs->tnpc;
68 current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
69 regs->tstate |= TSTATE_PIL;
70
71 regs->tpc = (unsigned long) &p->ainsn.insn[0];
72 regs->tnpc = (unsigned long) &p->ainsn.insn[1];
73}
74
75static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
76{
77 *p->addr = p->opcode;
78 flushi(p->addr);
79
80 regs->tpc = (unsigned long) p->addr;
81 regs->tnpc = current_kprobe_orig_tnpc;
82 regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
83 current_kprobe_orig_tstate_pil);
84}
85
86static int kprobe_handler(struct pt_regs *regs)
87{
88 struct kprobe *p;
89 void *addr = (void *) regs->tpc;
90 int ret = 0;
91
92 preempt_disable();
93
94 if (kprobe_running()) {
95
96
97
98 p = get_kprobe(addr);
99 if (p) {
100 disarm_kprobe(p, regs);
101 ret = 1;
102 } else {
103 p = current_kprobe;
104 if (p->break_handler && p->break_handler(p, regs))
105 goto ss_probe;
106 }
107
108 goto no_kprobe;
109 }
110
111 lock_kprobes();
112 p = get_kprobe(addr);
113 if (!p) {
114 unlock_kprobes();
115 if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
116
117
118
119
120
121
122
123 ret = 1;
124 }
125
126 goto no_kprobe;
127 }
128
129 kprobe_status = KPROBE_HIT_ACTIVE;
130 current_kprobe = p;
131 if (p->pre_handler(p, regs))
132 return 1;
133
134ss_probe:
135 prepare_singlestep(p, regs);
136 kprobe_status = KPROBE_HIT_SS;
137 return 1;
138
139no_kprobe:
140 preempt_enable_no_resched();
141 return ret;
142}
143
144
145
146
147
148
149
150static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
151 unsigned long pc, unsigned long npc)
152{
153
154 if (npc == pc + 0x4UL)
155 return real_pc + 0x4UL;
156
157
158
159
160 if ((insn & 0xc0000000) == 0x40000000 ||
161 (insn & 0xc1c00000) == 0x00400000 ||
162 (insn & 0xc1c00000) == 0x00800000) {
163
164
165
166
167 return (real_pc + (npc - pc));
168 }
169
170 return real_pc + 0x4UL;
171}
172
173
174
175
176static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
177{
178 unsigned long *slot = NULL;
179
180
181 if ((insn & 0xc0000000) == 0x40000000) {
182 slot = ®s->u_regs[UREG_I7];
183 }
184
185
186 if ((insn & 0xc1f80000) == 0x81c00000) {
187 unsigned long rd = ((insn >> 25) & 0x1f);
188
189 if (rd <= 15) {
190 slot = ®s->u_regs[rd];
191 } else {
192
193 flushw_all();
194
195 rd -= 16;
196 slot = (unsigned long *)
197 (regs->u_regs[UREG_FP] + STACK_BIAS);
198 slot += rd;
199 }
200 }
201 if (slot != NULL)
202 *slot = real_pc;
203}
204
205
206
207
208
209
210
211
212
213
214
215
216static void resume_execution(struct kprobe *p, struct pt_regs *regs)
217{
218 u32 insn = p->ainsn.insn[0];
219
220 regs->tpc = current_kprobe_orig_tnpc;
221 regs->tnpc = relbranch_fixup(insn,
222 (unsigned long) p->addr,
223 (unsigned long) &p->ainsn.insn[0],
224 regs->tnpc);
225 retpc_fixup(regs, insn, (unsigned long) p->addr);
226
227 regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
228 current_kprobe_orig_tstate_pil);
229}
230
231static inline int post_kprobe_handler(struct pt_regs *regs)
232{
233 if (!kprobe_running())
234 return 0;
235
236 if (current_kprobe->post_handler)
237 current_kprobe->post_handler(current_kprobe, regs, 0);
238
239 resume_execution(current_kprobe, regs);
240
241 unlock_kprobes();
242 preempt_enable_no_resched();
243
244 return 1;
245}
246
247
248static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
249{
250 if (current_kprobe->fault_handler
251 && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
252 return 1;
253
254 if (kprobe_status & KPROBE_HIT_SS) {
255 resume_execution(current_kprobe, regs);
256
257 unlock_kprobes();
258 preempt_enable_no_resched();
259 }
260 return 0;
261}
262
263
264
265
266int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
267 void *data)
268{
269 struct die_args *args = (struct die_args *)data;
270 switch (val) {
271 case DIE_DEBUG:
272 if (kprobe_handler(args->regs))
273 return NOTIFY_STOP;
274 break;
275 case DIE_DEBUG_2:
276 if (post_kprobe_handler(args->regs))
277 return NOTIFY_STOP;
278 break;
279 case DIE_GPF:
280 if (kprobe_running() &&
281 kprobe_fault_handler(args->regs, args->trapnr))
282 return NOTIFY_STOP;
283 break;
284 case DIE_PAGE_FAULT:
285 if (kprobe_running() &&
286 kprobe_fault_handler(args->regs, args->trapnr))
287 return NOTIFY_STOP;
288 break;
289 default:
290 break;
291 }
292 return NOTIFY_DONE;
293}
294
295asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
296{
297 BUG_ON(trap_level != 0x170 && trap_level != 0x171);
298
299 if (user_mode(regs)) {
300 local_irq_enable();
301 bad_trap(regs, trap_level);
302 return;
303 }
304
305
306
307
308 if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2,
309 (trap_level == 0x170) ? "debug" : "debug_2",
310 regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
311 bad_trap(regs, trap_level);
312}
313
314
315static struct pt_regs jprobe_saved_regs;
316static struct pt_regs *jprobe_saved_regs_location;
317static struct sparc_stackf jprobe_saved_stack;
318
319int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
320{
321 struct jprobe *jp = container_of(p, struct jprobe, kp);
322
323 jprobe_saved_regs_location = regs;
324 memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
325
326
327
328
329
330 memcpy(&jprobe_saved_stack,
331 (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
332 sizeof(jprobe_saved_stack));
333
334 regs->tpc = (unsigned long) jp->entry;
335 regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
336 regs->tstate |= TSTATE_PIL;
337
338 return 1;
339}
340
341void jprobe_return(void)
342{
343 preempt_enable_no_resched();
344 __asm__ __volatile__(
345 ".globl jprobe_return_trap_instruction\n"
346"jprobe_return_trap_instruction:\n\t"
347 "ta 0x70");
348}
349
350extern void jprobe_return_trap_instruction(void);
351
352extern void __show_regs(struct pt_regs * regs);
353
354int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
355{
356 u32 *addr = (u32 *) regs->tpc;
357
358 if (addr == (u32 *) jprobe_return_trap_instruction) {
359 if (jprobe_saved_regs_location != regs) {
360 printk("JPROBE: Current regs (%p) does not match "
361 "saved regs (%p).\n",
362 regs, jprobe_saved_regs_location);
363 printk("JPROBE: Saved registers\n");
364 __show_regs(jprobe_saved_regs_location);
365 printk("JPROBE: Current registers\n");
366 __show_regs(regs);
367 BUG();
368 }
369
370
371
372
373 memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
374
375 memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
376 &jprobe_saved_stack,
377 sizeof(jprobe_saved_stack));
378
379 return 1;
380 }
381 return 0;
382}
383