Blame view

arch/ia64/kernel/kprobes.c 29.7 KB
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   *  Kernel Probes (KProbes)
   *  arch/ia64/kernel/kprobes.c
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
   * Copyright (C) IBM Corporation, 2002, 2004
   * Copyright (C) Intel Corporation, 2005
   *
   * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
   *              <anil.s.keshavamurthy@intel.com> adapted from i386
   */
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
25
26
  #include <linux/kprobes.h>
  #include <linux/ptrace.h>
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
27
28
29
30
  #include <linux/string.h>
  #include <linux/slab.h>
  #include <linux/preempt.h>
  #include <linux/moduleloader.h>
1eeb66a1b   Christoph Hellwig   move die notifier...
31
  #include <linux/kdebug.h>
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
32
33
  
  #include <asm/pgtable.h>
c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
34
  #include <asm/sections.h>
c04c1c81e   Prasanna S Panchamukhi   [PATCH] kprobes: ...
35
  #include <asm/uaccess.h>
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
36

b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
37
  extern void jprobe_inst_return(void);
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
38
39
  DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
  DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
40

f438d914b   Masami Hiramatsu   kprobes: support ...
41
  struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
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
  enum instruction_type {A, I, M, F, B, L, X, u};
  static enum instruction_type bundle_encoding[32][3] = {
    { M, I, I },				/* 00 */
    { M, I, I },				/* 01 */
    { M, I, I },				/* 02 */
    { M, I, I },				/* 03 */
    { M, L, X },				/* 04 */
    { M, L, X },				/* 05 */
    { u, u, u },  			/* 06 */
    { u, u, u },  			/* 07 */
    { M, M, I },				/* 08 */
    { M, M, I },				/* 09 */
    { M, M, I },				/* 0A */
    { M, M, I },				/* 0B */
    { M, F, I },				/* 0C */
    { M, F, I },				/* 0D */
    { M, M, F },				/* 0E */
    { M, M, F },				/* 0F */
    { M, I, B },				/* 10 */
    { M, I, B },				/* 11 */
    { M, B, B },				/* 12 */
    { M, B, B },				/* 13 */
    { u, u, u },  			/* 14 */
    { u, u, u },  			/* 15 */
    { B, B, B },				/* 16 */
    { B, B, B },				/* 17 */
    { M, M, B },				/* 18 */
    { M, M, B },				/* 19 */
    { u, u, u },  			/* 1A */
    { u, u, u },  			/* 1B */
    { M, F, B },				/* 1C */
    { M, F, B },				/* 1D */
    { u, u, u },  			/* 1E */
    { u, u, u },  			/* 1F */
  };
34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
77
78
79
80
81
82
83
84
85
86
87
88
89
  /* Insert a long branch code */
  static void __kprobes set_brl_inst(void *from, void *to)
  {
  	s64 rel = ((s64) to - (s64) from) >> 4;
  	bundle_t *brl;
  	brl = (bundle_t *) ((u64) from & ~0xf);
  	brl->quad0.template = 0x05;	/* [MLX](stop) */
  	brl->quad0.slot0 = NOP_M_INST;	/* nop.m 0x0 */
  	brl->quad0.slot1_p0 = ((rel >> 20) & 0x7fffffffff) << 2;
  	brl->quad1.slot1_p1 = (((rel >> 20) & 0x7fffffffff) << 2) >> (64 - 46);
  	/* brl.cond.sptk.many.clr rel<<4 (qp=0) */
  	brl->quad1.slot2 = BRL_INST(rel >> 59, rel & 0xfffff);
  }
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
90
91
92
93
94
  /*
   * In this function we check to see if the instruction
   * is IP relative instruction and update the kprobe
   * inst flag accordingly
   */
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
95
96
97
98
  static void __kprobes update_kprobe_inst_flag(uint template, uint  slot,
  					      uint major_opcode,
  					      unsigned long kprobe_inst,
  					      struct kprobe *p)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
99
  {
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
100
101
  	p->ainsn.inst_flag = 0;
  	p->ainsn.target_br_reg = 0;
08ed38b68   Tony Luck   [IA64] enable tra...
102
  	p->ainsn.slot = slot;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
103

deac66ae4   Keshavamurthy Anil S   [PATCH] kprobes: ...
104
  	/* Check for Break instruction
62c27be0d   bibo,mao   [PATCH] kprobe wh...
105
  	 * Bits 37:40 Major opcode to be zero
deac66ae4   Keshavamurthy Anil S   [PATCH] kprobes: ...
106
107
108
109
110
111
112
113
  	 * Bits 27:32 X6 to be zero
  	 * Bits 32:35 X3 to be zero
  	 */
  	if ((!major_opcode) && (!((kprobe_inst >> 27) & 0x1FF)) ) {
  		/* is a break instruction */
  	 	p->ainsn.inst_flag |= INST_FLAG_BREAK_INST;
  		return;
  	}
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
114
115
116
117
  	if (bundle_encoding[template][slot] == B) {
  		switch (major_opcode) {
  		  case INDIRECT_CALL_OPCODE:
  	 		p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
62c27be0d   bibo,mao   [PATCH] kprobe wh...
118
119
  			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
  			break;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
120
121
122
  		  case IP_RELATIVE_PREDICT_OPCODE:
  		  case IP_RELATIVE_BRANCH_OPCODE:
  			p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
62c27be0d   bibo,mao   [PATCH] kprobe wh...
123
  			break;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
124
  		  case IP_RELATIVE_CALL_OPCODE:
62c27be0d   bibo,mao   [PATCH] kprobe wh...
125
126
127
128
  			p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
  			p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
  			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
  			break;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
129
  		}
62c27be0d   bibo,mao   [PATCH] kprobe wh...
130
  	} else if (bundle_encoding[template][slot] == X) {
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
131
132
133
134
135
136
137
138
139
  		switch (major_opcode) {
  		  case LONG_CALL_OPCODE:
  			p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
  			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
  		  break;
  		}
  	}
  	return;
  }
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
140

a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
141
  /*
1674eafcb   Anil S Keshavamurthy   [PATCH] Kprobes I...
142
143
144
145
146
   * In this function we check to see if the instruction
   * (qp) cmpx.crel.ctype p1,p2=r2,r3
   * on which we are inserting kprobe is cmp instruction
   * with ctype as unc.
   */
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
147
148
149
  static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
  					    uint major_opcode,
  					    unsigned long kprobe_inst)
1674eafcb   Anil S Keshavamurthy   [PATCH] Kprobes I...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  {
  	cmp_inst_t cmp_inst;
  	uint ctype_unc = 0;
  
  	if (!((bundle_encoding[template][slot] == I) ||
  		(bundle_encoding[template][slot] == M)))
  		goto out;
  
  	if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
  		(major_opcode == 0xE)))
  		goto out;
  
  	cmp_inst.l = kprobe_inst;
  	if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
72fdbdce3   Simon Arlott   [IA64] spelling f...
164
  		/* Integer compare - Register Register (A6 type)*/
1674eafcb   Anil S Keshavamurthy   [PATCH] Kprobes I...
165
166
167
168
  		if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
  				&&(cmp_inst.f.c == 1))
  			ctype_unc = 1;
  	} else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
72fdbdce3   Simon Arlott   [IA64] spelling f...
169
  		/* Integer compare - Immediate Register (A8 type)*/
1674eafcb   Anil S Keshavamurthy   [PATCH] Kprobes I...
170
171
172
173
174
175
176
177
  		if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
  			ctype_unc = 1;
  	}
  out:
  	return ctype_unc;
  }
  
  /*
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
   * In this function we check to see if the instruction
   * on which we are inserting kprobe is supported.
   * Returns qp value if supported
   * Returns -EINVAL if unsupported
   */
  static int __kprobes unsupported_inst(uint template, uint  slot,
  				      uint major_opcode,
  				      unsigned long kprobe_inst,
  				      unsigned long addr)
  {
  	int qp;
  
  	qp = kprobe_inst & 0x3f;
  	if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
  		if (slot == 1 && qp)  {
c2eeb321a   Joe Perches   [IA64] Add missin...
193
194
  			printk(KERN_WARNING "Kprobes on cmp unc "
  					"instruction on slot 1 at <0x%lx> "
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
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
  					"is not supported
  ", addr);
  			return -EINVAL;
  
  		}
  		qp = 0;
  	}
  	else if (bundle_encoding[template][slot] == I) {
  		if (major_opcode == 0) {
  			/*
  			 * Check for Integer speculation instruction
  			 * - Bit 33-35 to be equal to 0x1
  			 */
  			if (((kprobe_inst >> 33) & 0x7) == 1) {
  				printk(KERN_WARNING
  					"Kprobes on speculation inst at <0x%lx> not supported
  ",
  						addr);
  				return -EINVAL;
  			}
  			/*
  			 * IP relative mov instruction
  			 *  - Bit 27-35 to be equal to 0x30
  			 */
  			if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
  				printk(KERN_WARNING
  					"Kprobes on \"mov r1=ip\" at <0x%lx> not supported
  ",
  						addr);
  				return -EINVAL;
  
  			}
  		}
  		else if ((major_opcode == 5) &&	!(kprobe_inst & (0xFUl << 33)) &&
  				(kprobe_inst & (0x1UL << 12))) {
  			/* test bit instructions, tbit,tnat,tf
  			 * bit 33-36 to be equal to 0
  			 * bit 12 to be equal to 1
  			 */
  			if (slot == 1 && qp) {
c2eeb321a   Joe Perches   [IA64] Add missin...
235
236
  				printk(KERN_WARNING "Kprobes on test bit "
  						"instruction on slot at <0x%lx> "
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  						"is not supported
  ", addr);
  				return -EINVAL;
  			}
  			qp = 0;
  		}
  	}
  	else if (bundle_encoding[template][slot] == B) {
  		if (major_opcode == 7) {
  			/* IP-Relative Predict major code is 7 */
  			printk(KERN_WARNING "Kprobes on IP-Relative"
  					"Predict is not supported
  ");
  			return -EINVAL;
  		}
  		else if (major_opcode == 2) {
  			/* Indirect Predict, major code is 2
  			 * bit 27-32 to be equal to 10 or 11
  			 */
  			int x6=(kprobe_inst >> 27) & 0x3F;
  			if ((x6 == 0x10) || (x6 == 0x11)) {
c2eeb321a   Joe Perches   [IA64] Add missin...
258
  				printk(KERN_WARNING "Kprobes on "
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  					"Indirect Predict is not supported
  ");
  				return -EINVAL;
  			}
  		}
  	}
  	/* kernel does not use float instruction, here for safety kprobe
  	 * will judge whether it is fcmp/flass/float approximation instruction
  	 */
  	else if (unlikely(bundle_encoding[template][slot] == F)) {
  		if ((major_opcode == 4 || major_opcode == 5) &&
  				(kprobe_inst  & (0x1 << 12))) {
  			/* fcmp/fclass unc instruction */
  			if (slot == 1 && qp) {
  				printk(KERN_WARNING "Kprobes on fcmp/fclass "
  					"instruction on slot at <0x%lx> "
  					"is not supported
  ", addr);
  				return -EINVAL;
  
  			}
  			qp = 0;
  		}
  		if ((major_opcode == 0 || major_opcode == 1) &&
  			(kprobe_inst & (0x1UL << 33))) {
  			/* float Approximation instruction */
  			if (slot == 1 && qp) {
  				printk(KERN_WARNING "Kprobes on float Approx "
  					"instr at <0x%lx> is not supported
  ",
  						addr);
  				return -EINVAL;
  			}
  			qp = 0;
  		}
  	}
  	return qp;
  }
  
  /*
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
299
300
301
   * In this function we override the bundle with
   * the break instruction at the given slot.
   */
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
302
303
304
  static void __kprobes prepare_break_inst(uint template, uint  slot,
  					 uint major_opcode,
  					 unsigned long kprobe_inst,
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
305
306
  					 struct kprobe *p,
  					 int qp)
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
307
308
  {
  	unsigned long break_inst = BREAK_INST;
214ddde2f   bibo mao   [IA64] kprobe opc...
309
  	bundle_t *bundle = &p->opcode.bundle;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
310
311
312
  
  	/*
  	 * Copy the original kprobe_inst qualifying predicate(qp)
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
313
  	 * to the break instruction
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
314
  	 */
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
315
  	break_inst |= qp;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
316
317
318
319
320
321
322
323
324
325
326
327
  
  	switch (slot) {
  	  case 0:
  		bundle->quad0.slot0 = break_inst;
  		break;
  	  case 1:
  		bundle->quad0.slot1_p0 = break_inst;
  		bundle->quad1.slot1_p1 = break_inst >> (64-46);
  		break;
  	  case 2:
  		bundle->quad1.slot2 = break_inst;
  		break;
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
328
  	}
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
329

a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
330
331
332
333
334
335
336
  	/*
  	 * Update the instruction flag, so that we can
  	 * emulate the instruction properly after we
  	 * single step on original instruction
  	 */
  	update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
  }
3ca269d8b   Prasanna S Panchamukhi   [PATCH] Switch Kp...
337
  static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
338
339
340
341
342
343
  	       	unsigned long *kprobe_inst, uint *major_opcode)
  {
  	unsigned long kprobe_inst_p0, kprobe_inst_p1;
  	unsigned int template;
  
  	template = bundle->quad0.template;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
344

fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
345
  	switch (slot) {
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
346
  	  case 0:
62c27be0d   bibo,mao   [PATCH] kprobe wh...
347
348
349
  		*major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT);
  		*kprobe_inst = bundle->quad0.slot0;
  		  break;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
350
  	  case 1:
62c27be0d   bibo,mao   [PATCH] kprobe wh...
351
352
353
354
  		*major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT);
  		kprobe_inst_p0 = bundle->quad0.slot1_p0;
  		kprobe_inst_p1 = bundle->quad1.slot1_p1;
  		*kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46));
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
355
  		break;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
356
  	  case 2:
62c27be0d   bibo,mao   [PATCH] kprobe wh...
357
358
  		*major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT);
  		*kprobe_inst = bundle->quad1.slot2;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
359
360
  		break;
  	}
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
361
  }
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
362

c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
363
  /* Returns non-zero if the addr is in the Interrupt Vector Table */
3ca269d8b   Prasanna S Panchamukhi   [PATCH] Switch Kp...
364
  static int __kprobes in_ivt_functions(unsigned long addr)
c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
365
366
367
368
  {
  	return (addr >= (unsigned long)__start_ivt_text
  		&& addr < (unsigned long)__end_ivt_text);
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
369
370
  static int __kprobes valid_kprobe_addr(int template, int slot,
  				       unsigned long addr)
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
371
372
  {
  	if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
373
374
375
  		printk(KERN_WARNING "Attempting to insert unaligned kprobe "
  				"at 0x%lx
  ", addr);
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
376
  		return -EINVAL;
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
377
  	}
a528e21c2   Rusty Lynch   [PATCH] kprobes/i...
378

62c27be0d   bibo,mao   [PATCH] kprobe wh...
379
380
  	if (in_ivt_functions(addr)) {
  		printk(KERN_WARNING "Kprobes can't be inserted inside "
c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
381
382
  				"IVT functions at 0x%lx
  ", addr);
62c27be0d   bibo,mao   [PATCH] kprobe wh...
383
384
  		return -EINVAL;
  	}
c7b645f93   Keshavamurthy Anil S   [PATCH] kprobes/i...
385

a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
386
387
  	return 0;
  }
3ca269d8b   Prasanna S Panchamukhi   [PATCH] Switch Kp...
388
  static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
389
  {
cdc7dbdfe   Anil S Keshavamurthy   [IA64] fix Kprobe...
390
391
392
393
  	unsigned int i;
  	i = atomic_add_return(1, &kcb->prev_kprobe_index);
  	kcb->prev_kprobe[i-1].kp = kprobe_running();
  	kcb->prev_kprobe[i-1].status = kcb->kprobe_status;
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
394
  }
3ca269d8b   Prasanna S Panchamukhi   [PATCH] Switch Kp...
395
  static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
396
  {
cdc7dbdfe   Anil S Keshavamurthy   [IA64] fix Kprobe...
397
  	unsigned int i;
97075c4b3   Masami Hiramatsu   [IA64] Fix the or...
398
399
400
401
  	i = atomic_read(&kcb->prev_kprobe_index);
  	__get_cpu_var(current_kprobe) = kcb->prev_kprobe[i-1].kp;
  	kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
  	atomic_sub(1, &kcb->prev_kprobe_index);
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
402
  }
3ca269d8b   Prasanna S Panchamukhi   [PATCH] Switch Kp...
403
  static void __kprobes set_current_kprobe(struct kprobe *p,
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
404
  			struct kprobe_ctlblk *kcb)
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
405
  {
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
406
  	__get_cpu_var(current_kprobe) = p;
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
407
  }
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
408
409
410
411
412
413
414
415
416
417
418
419
  static void kretprobe_trampoline(void)
  {
  }
  
  /*
   * At this point the target function has been tricked into
   * returning into our trampoline.  Lookup the associated instance
   * and then:
   *    - call the handler function
   *    - cleanup by marking the instance as unused
   *    - long jump back to the original return address
   */
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
420
  int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
421
422
  {
  	struct kretprobe_instance *ri = NULL;
99219a3fb   bibo,mao   [PATCH] kretprobe...
423
  	struct hlist_head *head, empty_rp;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
424
  	struct hlist_node *node, *tmp;
991a51d83   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
425
  	unsigned long flags, orig_ret_address = 0;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
426
427
  	unsigned long trampoline_address =
  		((struct fnptr *)kretprobe_trampoline)->ip;
99219a3fb   bibo,mao   [PATCH] kretprobe...
428
  	INIT_HLIST_HEAD(&empty_rp);
ef53d9c5e   Srinivasa D S   kprobes: improve ...
429
  	kretprobe_hash_lock(current, &head, &flags);
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
430
431
432
433
  
  	/*
  	 * It is possible to have multiple instances associated with a given
  	 * task either because an multiple functions in the call path
025dfdafe   Frederik Schwarzer   trivial: fix then...
434
  	 * have a return probe installed on them, and/or more than one return
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
435
436
437
438
439
440
441
442
443
444
  	 * 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) {
9138d581b   Keith Owens   [IA64] Extend not...
445
  		if (ri->task != current)
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
446
  			/* another task is sharing our hash bucket */
9138d581b   Keith Owens   [IA64] Extend not...
447
  			continue;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
448

3661999a1   Shaohua Li   [IA64] kprobe: ma...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  		orig_ret_address = (unsigned long)ri->ret_addr;
  		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;
  	}
  
  	regs->cr_iip = orig_ret_address;
  
  	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
  		if (ri->task != current)
  			/* another task is sharing our hash bucket */
  			continue;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
465
466
467
468
  		if (ri->rp && ri->rp->handler)
  			ri->rp->handler(ri, regs);
  
  		orig_ret_address = (unsigned long)ri->ret_addr;
99219a3fb   bibo,mao   [PATCH] kretprobe...
469
  		recycle_rp_inst(ri, &empty_rp);
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
470
471
472
473
474
475
476
477
478
  
  		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;
  	}
0f95b7fc8   Ananth N Mavinakayanahalli   Kprobes: print de...
479
  	kretprobe_assert(ri, orig_ret_address, trampoline_address);
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
480
  	reset_current_kprobe();
ef53d9c5e   Srinivasa D S   kprobes: improve ...
481
  	kretprobe_hash_unlock(current, &flags);
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
482
  	preempt_enable_no_resched();
99219a3fb   bibo,mao   [PATCH] kretprobe...
483
484
485
486
  	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
  		hlist_del(&ri->hlist);
  		kfree(ri);
  	}
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
487
488
489
490
491
  	/*
  	 * By returning a non-zero value, we are telling
  	 * kprobe_handler() that we don't want the post_handler
  	 * to run (and have re-enabled preemption)
  	 */
9138d581b   Keith Owens   [IA64] Extend not...
492
  	return 1;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
493
  }
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
494
  void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
495
  				      struct pt_regs *regs)
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
496
  {
4c4308cb9   Christoph Hellwig   kprobes: kretprob...
497
  	ri->ret_addr = (kprobe_opcode_t *)regs->b0;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
498

4c4308cb9   Christoph Hellwig   kprobes: kretprob...
499
500
  	/* Replace the return addr with trampoline addr */
  	regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
501
  }
34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
502
503
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
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
  /* Check the instruction in the slot is break */
  static int __kprobes __is_ia64_break_inst(bundle_t *bundle, uint slot)
  {
  	unsigned int major_opcode;
  	unsigned int template = bundle->quad0.template;
  	unsigned long kprobe_inst;
  
  	/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
  	if (slot == 1 && bundle_encoding[template][1] == L)
  		slot++;
  
  	/* Get Kprobe probe instruction at given slot*/
  	get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
  
  	/* For break instruction,
  	 * Bits 37:40 Major opcode to be zero
  	 * Bits 27:32 X6 to be zero
  	 * Bits 32:35 X3 to be zero
  	 */
  	if (major_opcode || ((kprobe_inst >> 27) & 0x1FF)) {
  		/* Not a break instruction */
  		return 0;
  	}
  
  	/* Is a break instruction */
  	return 1;
  }
  
  /*
   * In this function, we check whether the target bundle modifies IP or
   * it triggers an exception. If so, it cannot be boostable.
   */
  static int __kprobes can_boost(bundle_t *bundle, uint slot,
  			       unsigned long bundle_addr)
  {
  	unsigned int template = bundle->quad0.template;
  
  	do {
  		if (search_exception_tables(bundle_addr + slot) ||
  		    __is_ia64_break_inst(bundle, slot))
  			return 0;	/* exception may occur in this bundle*/
  	} while ((++slot) < 3);
  	template &= 0x1e;
  	if (template >= 0x10 /* including B unit */ ||
  	    template == 0x04 /* including X unit */ ||
  	    template == 0x06) /* undefined */
  		return 0;
  
  	return 1;
  }
  
  /* Prepare long jump bundle and disables other boosters if need */
  static void __kprobes prepare_booster(struct kprobe *p)
  {
  	unsigned long addr = (unsigned long)p->addr & ~0xFULL;
  	unsigned int slot = (unsigned long)p->addr & 0xf;
  	struct kprobe *other_kp;
  
  	if (can_boost(&p->ainsn.insn[0].bundle, slot, addr)) {
  		set_brl_inst(&p->ainsn.insn[1].bundle, (bundle_t *)addr + 1);
  		p->ainsn.inst_flag |= INST_FLAG_BOOSTABLE;
  	}
  
  	/* disables boosters in previous slots */
  	for (; addr < (unsigned long)p->addr; addr++) {
  		other_kp = get_kprobe((void *)addr);
  		if (other_kp)
  			other_kp->ainsn.inst_flag &= ~INST_FLAG_BOOSTABLE;
  	}
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
572
  int __kprobes arch_prepare_kprobe(struct kprobe *p)
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
573
574
575
576
577
  {
  	unsigned long addr = (unsigned long) p->addr;
  	unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
  	unsigned long kprobe_inst=0;
  	unsigned int slot = addr & 0xf, template, major_opcode = 0;
214ddde2f   bibo mao   [IA64] kprobe opc...
578
  	bundle_t *bundle;
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
579
  	int qp;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
580

214ddde2f   bibo mao   [IA64] kprobe opc...
581
  	bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
62c27be0d   bibo,mao   [PATCH] kprobe wh...
582
  	template = bundle->quad0.template;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
583
584
585
586
587
  
  	if(valid_kprobe_addr(template, slot, addr))
  		return -EINVAL;
  
  	/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
62c27be0d   bibo,mao   [PATCH] kprobe wh...
588
589
  	if (slot == 1 && bundle_encoding[template][1] == L)
  		slot++;
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
590
591
592
  
  	/* Get kprobe_inst and major_opcode from the bundle */
  	get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
df3e0d1c6   bibo,mao   [IA64] kprobe cle...
593
594
595
  	qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
  	if (qp < 0)
  		return -EINVAL;
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
596

214ddde2f   bibo mao   [IA64] kprobe opc...
597
598
599
600
601
  	p->ainsn.insn = get_insn_slot();
  	if (!p->ainsn.insn)
  		return -ENOMEM;
  	memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
  	memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
602

df3e0d1c6   bibo,mao   [IA64] kprobe cle...
603
  	prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
a9ad965ea   bibo, mao   [PATCH] IA64: kpr...
604

34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
605
  	prepare_booster(p);
214ddde2f   bibo mao   [IA64] kprobe opc...
606
  	return 0;
a9ad965ea   bibo, mao   [PATCH] IA64: kpr...
607
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
608
  void __kprobes arch_arm_kprobe(struct kprobe *p)
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
609
  {
08ed38b68   Tony Luck   [IA64] enable tra...
610
611
612
613
614
615
  	unsigned long arm_addr;
  	bundle_t *src, *dest;
  
  	arm_addr = ((unsigned long)p->addr) & ~0xFUL;
  	dest = &((kprobe_opcode_t *)arm_addr)->bundle;
  	src = &p->opcode.bundle;
8bc76772a   Rusty Lynch   [PATCH] Kprobes i...
616

214ddde2f   bibo mao   [IA64] kprobe opc...
617
  	flush_icache_range((unsigned long)p->ainsn.insn,
34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
618
619
  			   (unsigned long)p->ainsn.insn +
  			   sizeof(kprobe_opcode_t) * MAX_INSN_SIZE);
08ed38b68   Tony Luck   [IA64] enable tra...
620
621
622
623
624
625
626
627
628
629
630
  	switch (p->ainsn.slot) {
  		case 0:
  			dest->quad0.slot0 = src->quad0.slot0;
  			break;
  		case 1:
  			dest->quad1.slot1_p1 = src->quad1.slot1_p1;
  			break;
  		case 2:
  			dest->quad1.slot2 = src->quad1.slot2;
  			break;
  	}
214ddde2f   bibo mao   [IA64] kprobe opc...
631
  	flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
632
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
633
  void __kprobes arch_disarm_kprobe(struct kprobe *p)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
634
  {
08ed38b68   Tony Luck   [IA64] enable tra...
635
636
  	unsigned long arm_addr;
  	bundle_t *src, *dest;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
637

08ed38b68   Tony Luck   [IA64] enable tra...
638
639
  	arm_addr = ((unsigned long)p->addr) & ~0xFUL;
  	dest = &((kprobe_opcode_t *)arm_addr)->bundle;
214ddde2f   bibo mao   [IA64] kprobe opc...
640
  	/* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
08ed38b68   Tony Luck   [IA64] enable tra...
641
642
643
644
645
646
647
648
649
650
651
652
  	src = &p->ainsn.insn->bundle;
  	switch (p->ainsn.slot) {
  		case 0:
  			dest->quad0.slot0 = src->quad0.slot0;
  			break;
  		case 1:
  			dest->quad1.slot1_p1 = src->quad1.slot1_p1;
  			break;
  		case 2:
  			dest->quad1.slot2 = src->quad1.slot2;
  			break;
  	}
214ddde2f   bibo mao   [IA64] kprobe opc...
653
  	flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
654
  }
214ddde2f   bibo mao   [IA64] kprobe opc...
655
656
  void __kprobes arch_remove_kprobe(struct kprobe *p)
  {
129415607   Masami Hiramatsu   kprobes: add kpro...
657
658
659
660
661
  	if (p->ainsn.insn) {
  		free_insn_slot(p->ainsn.insn,
  			       p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
  		p->ainsn.insn = NULL;
  	}
214ddde2f   bibo mao   [IA64] kprobe opc...
662
  }
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
663
664
665
  /*
   * We are resuming execution after a single step fault, so the pt_regs
   * structure reflects the register state after we executed the instruction
34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
666
   * located in the kprobe (p->ainsn.insn->bundle).  We still need to adjust
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
667
668
669
   * the ip to point back to the original stack address. To set the IP address
   * to original stack address, handle the case where we need to fixup the
   * relative IP address and/or fixup branch register.
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
670
   */
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
671
  static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
672
  {
62c27be0d   bibo,mao   [PATCH] kprobe wh...
673
674
675
676
  	unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
  	unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
  	unsigned long template;
  	int slot = ((unsigned long)p->addr & 0xf);
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
677

214ddde2f   bibo mao   [IA64] kprobe opc...
678
  	template = p->ainsn.insn->bundle.quad0.template;
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
679

62c27be0d   bibo,mao   [PATCH] kprobe wh...
680
681
  	if (slot == 1 && bundle_encoding[template][1] == L)
  		slot = 2;
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
682

34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
683
  	if (p->ainsn.inst_flag & ~INST_FLAG_BOOSTABLE) {
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
684
685
686
  
  		if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
  			/* Fix relative IP address */
62c27be0d   bibo,mao   [PATCH] kprobe wh...
687
688
  			regs->cr_iip = (regs->cr_iip - bundle_addr) +
  					resume_addr;
cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
  		}
  
  		if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) {
  		/*
  		 * Fix target branch register, software convention is
  		 * to use either b0 or b6 or b7, so just checking
  		 * only those registers
  		 */
  			switch (p->ainsn.target_br_reg) {
  			case 0:
  				if ((regs->b0 == bundle_addr) ||
  					(regs->b0 == bundle_addr + 0x10)) {
  					regs->b0 = (regs->b0 - bundle_addr) +
  						resume_addr;
  				}
  				break;
  			case 6:
  				if ((regs->b6 == bundle_addr) ||
  					(regs->b6 == bundle_addr + 0x10)) {
  					regs->b6 = (regs->b6 - bundle_addr) +
  						resume_addr;
  				}
  				break;
  			case 7:
  				if ((regs->b7 == bundle_addr) ||
  					(regs->b7 == bundle_addr + 0x10)) {
  					regs->b7 = (regs->b7 - bundle_addr) +
  						resume_addr;
  				}
  				break;
  			} /* end switch */
  		}
  		goto turn_ss_off;
  	}
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
723

cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
724
  	if (slot == 2) {
62c27be0d   bibo,mao   [PATCH] kprobe wh...
725
726
727
728
729
730
731
  		if (regs->cr_iip == bundle_addr + 0x10) {
  			regs->cr_iip = resume_addr + 0x10;
  		}
  	} else {
  		if (regs->cr_iip == bundle_addr) {
  			regs->cr_iip = resume_addr;
  		}
a5403183d   Anil S Keshavamurthy   [PATCH] Kprobes I...
732
  	}
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
733

cd2675bf6   Anil S Keshavamurthy   [PATCH] Kprobes/I...
734
  turn_ss_off:
62c27be0d   bibo,mao   [PATCH] kprobe wh...
735
736
  	/* Turn off Single Step bit */
  	ia64_psr(regs)->ss = 0;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
737
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
738
  static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
739
  {
214ddde2f   bibo mao   [IA64] kprobe opc...
740
  	unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
741
  	unsigned long slot = (unsigned long)p->addr & 0xf;
deac66ae4   Keshavamurthy Anil S   [PATCH] kprobes: ...
742
743
744
745
746
  	/* single step inline if break instruction */
  	if (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)
  		regs->cr_iip = (unsigned long)p->addr & ~0xFULL;
  	else
  		regs->cr_iip = bundle_addr & ~0xFULL;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
747
748
749
750
751
752
753
754
755
  
  	if (slot > 2)
  		slot = 0;
  
  	ia64_psr(regs)->ri = slot;
  
  	/* turn on single stepping */
  	ia64_psr(regs)->ss = 1;
  }
661e5a3d9   Keshavamurthy Anil S   [PATCH] Kprobes/I...
756
757
758
  static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
  {
  	unsigned int slot = ia64_psr(regs)->ri;
661e5a3d9   Keshavamurthy Anil S   [PATCH] Kprobes/I...
759
760
761
762
  	unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
  	bundle_t bundle;
  
  	memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
661e5a3d9   Keshavamurthy Anil S   [PATCH] Kprobes/I...
763

34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
764
  	return __is_ia64_break_inst(&bundle, slot);
661e5a3d9   Keshavamurthy Anil S   [PATCH] Kprobes/I...
765
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
766
  static int __kprobes pre_kprobes_handler(struct die_args *args)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
767
768
769
  {
  	struct kprobe *p;
  	int ret = 0;
89cb14c0d   Keshavamurthy Anil S   [PATCH] Kprobes/I...
770
  	struct pt_regs *regs = args->regs;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
771
  	kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
772
773
774
775
776
777
778
779
  	struct kprobe_ctlblk *kcb;
  
  	/*
  	 * We don't want to be preempted for the entire
  	 * duration of kprobe processing
  	 */
  	preempt_disable();
  	kcb = get_kprobe_ctlblk();
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
780

fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
781
782
783
784
  	/* Handle recursion cases */
  	if (kprobe_running()) {
  		p = get_kprobe(addr);
  		if (p) {
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
785
  			if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
deac66ae4   Keshavamurthy Anil S   [PATCH] kprobes: ...
786
  	 		     (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
62c27be0d   bibo,mao   [PATCH] kprobe wh...
787
  				ia64_psr(regs)->ss = 0;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
788
789
  				goto no_kprobe;
  			}
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
790
791
792
793
794
795
  			/* We have reentered the pre_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.
  			 */
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
796
797
  			save_previous_kprobe(kcb);
  			set_current_kprobe(p, kcb);
bf8d5c52c   Keshavamurthy Anil S   [PATCH] kprobes: ...
798
  			kprobes_inc_nmissed_count(p);
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
799
  			prepare_ss(p, regs);
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
800
  			kcb->kprobe_status = KPROBE_REENTER;
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
801
  			return 1;
89cb14c0d   Keshavamurthy Anil S   [PATCH] Kprobes/I...
802
  		} else if (args->err == __IA64_BREAK_JPROBE) {
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
803
804
805
  			/*
  			 * jprobe instrumented function just completed
  			 */
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
806
  			p = __get_cpu_var(current_kprobe);
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
807
808
809
  			if (p->break_handler && p->break_handler(p, regs)) {
  				goto ss_probe;
  			}
eb3a72921   Keshavamurthy Anil S   [PATCH] kprobes: ...
810
811
812
813
814
815
816
  		} else if (!is_ia64_break_inst(regs)) {
  			/* The breakpoint instruction was removed by
  			 * another cpu right after we hit, no further
  			 * handling of this interrupt is appropriate
  			 */
  			ret = 1;
  			goto no_kprobe;
89cb14c0d   Keshavamurthy Anil S   [PATCH] Kprobes/I...
817
818
819
  		} else {
  			/* Not our break */
  			goto no_kprobe;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
820
821
  		}
  	}
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
822
823
  	p = get_kprobe(addr);
  	if (!p) {
661e5a3d9   Keshavamurthy Anil S   [PATCH] Kprobes/I...
824
825
826
827
828
829
830
831
832
833
834
835
836
  		if (!is_ia64_break_inst(regs)) {
  			/*
  			 * 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;
  
  		}
  
  		/* Not one of our break, let kernel handle it */
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
837
838
  		goto no_kprobe;
  	}
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
839
840
  	set_current_kprobe(p, kcb);
  	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
841
842
843
844
  
  	if (p->pre_handler && p->pre_handler(p, regs))
  		/*
  		 * Our pre-handler is specifically requesting that we just
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
845
846
  		 * do a return.  This is used for both the jprobe pre-handler
  		 * and the kretprobe trampoline
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
847
848
849
850
  		 */
  		return 1;
  
  ss_probe:
615d0ebbc   Masami Hiramatsu   kprobes: Disable ...
851
  #if !defined(CONFIG_PREEMPT)
34e1ceb18   Masami Hiramatsu   [IA64] kprobes: k...
852
853
854
855
856
857
858
859
860
861
862
863
  	if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
  		/* Boost up -- we can execute copied instructions directly */
  		ia64_psr(regs)->ri = p->ainsn.slot;
  		regs->cr_iip = (unsigned long)&p->ainsn.insn->bundle & ~0xFULL;
  		/* turn single stepping off */
  		ia64_psr(regs)->ss = 0;
  
  		reset_current_kprobe();
  		preempt_enable_no_resched();
  		return 1;
  	}
  #endif
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
864
  	prepare_ss(p, regs);
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
865
  	kcb->kprobe_status = KPROBE_HIT_SS;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
866
867
868
  	return 1;
  
  no_kprobe:
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
869
  	preempt_enable_no_resched();
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
870
871
  	return ret;
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
872
  static int __kprobes post_kprobes_handler(struct pt_regs *regs)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
873
  {
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
874
875
876
877
  	struct kprobe *cur = kprobe_running();
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
  
  	if (!cur)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
878
  		return 0;
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
879
880
881
  	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
  		kcb->kprobe_status = KPROBE_HIT_SSDONE;
  		cur->post_handler(cur, regs, 0);
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
882
  	}
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
883

8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
884
  	resume_execution(cur, regs);
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
885

852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
886
  	/*Restore back the original saved kprobes variables and continue. */
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
887
888
  	if (kcb->kprobe_status == KPROBE_REENTER) {
  		restore_previous_kprobe(kcb);
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
889
890
  		goto out;
  	}
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
891
  	reset_current_kprobe();
852caccc8   Anil S Keshavamurthy   [PATCH] Kprobes/i...
892
893
  
  out:
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
894
895
896
  	preempt_enable_no_resched();
  	return 1;
  }
45e18c228   Harvey Harrison   [IA64] kprobes ar...
897
  int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
898
  {
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
899
900
  	struct kprobe *cur = kprobe_running();
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
901

c04c1c81e   Prasanna S Panchamukhi   [PATCH] kprobes: ...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  	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 and the instruction pointer points back to
  		 * the probe address and allow the page fault handler
  		 * to continue as a normal page fault.
  		 */
  		regs->cr_iip = ((unsigned long)cur->addr) & ~0xFULL;
  		ia64_psr(regs)->ri = ((unsigned long)cur->addr) & 0xf;
  		if (kcb->kprobe_status == KPROBE_REENTER)
  			restore_previous_kprobe(kcb);
  		else
  			reset_current_kprobe();
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
918
  		preempt_enable_no_resched();
c04c1c81e   Prasanna S Panchamukhi   [PATCH] kprobes: ...
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
  		break;
  	case KPROBE_HIT_ACTIVE:
  	case KPROBE_HIT_SSDONE:
  		/*
  		 * We increment the nmissed count for accounting,
  		 * we can also use npre/npostfault count for accouting
  		 * 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;
fd32cb3a9   Keshavamurthy Anil S   [IA64] kprobes: f...
938
939
940
941
942
943
  		/*
  		 * In case the user-specified fault handler returned
  		 * zero, try to fix up.
  		 */
  		if (ia64_done_with_exception(regs))
  			return 1;
c04c1c81e   Prasanna S Panchamukhi   [PATCH] kprobes: ...
944
945
946
947
948
949
950
  
  		/*
  		 * Let ia64_do_page_fault() fix it.
  		 */
  		break;
  	default:
  		break;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
951
952
953
954
  	}
  
  	return 0;
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
955
956
  int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
  				       unsigned long val, void *data)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
957
958
  {
  	struct die_args *args = (struct die_args *)data;
66ff2d069   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
959
  	int ret = NOTIFY_DONE;
2326c7701   bibo,mao   [PATCH] kprobe ha...
960
961
  	if (args->regs && user_mode(args->regs))
  		return ret;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
962
963
  	switch(val) {
  	case DIE_BREAK:
9138d581b   Keith Owens   [IA64] Extend not...
964
  		/* err is break number from ia64_bad_break() */
08ed38b68   Tony Luck   [IA64] enable tra...
965
966
967
  		if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12)
  			|| args->err == __IA64_BREAK_JPROBE
  			|| args->err == 0)
9138d581b   Keith Owens   [IA64] Extend not...
968
969
  			if (pre_kprobes_handler(args))
  				ret = NOTIFY_STOP;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
970
  		break;
9138d581b   Keith Owens   [IA64] Extend not...
971
972
973
974
975
  	case DIE_FAULT:
  		/* err is vector number from ia64_fault() */
  		if (args->err == 36)
  			if (post_kprobes_handler(args->regs))
  				ret = NOTIFY_STOP;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
976
  		break;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
977
978
979
  	default:
  		break;
  	}
66ff2d069   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
980
  	return ret;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
981
  }
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
  struct param_bsp_cfm {
  	unsigned long ip;
  	unsigned long *bsp;
  	unsigned long cfm;
  };
  
  static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
  {
  	unsigned long ip;
  	struct param_bsp_cfm *lp = arg;
  
  	do {
  		unw_get_ip(info, &ip);
  		if (ip == 0)
  			break;
  		if (ip == lp->ip) {
  			unw_get_bsp(info, (unsigned long*)&lp->bsp);
  			unw_get_cfm(info, (unsigned long*)&lp->cfm);
  			return;
  		}
  	} while (unw_unwind(info) >= 0);
d61b49c1a   Matthew Wilcox   [IA64] sparse cle...
1003
  	lp->bsp = NULL;
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1004
1005
1006
  	lp->cfm = 0;
  	return;
  }
3d7e33825   Michael Ellerman   jprobes: make jpr...
1007
1008
1009
1010
  unsigned long arch_deref_entry_point(void *entry)
  {
  	return ((struct fnptr *)entry)->ip;
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
1011
  int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1012
  {
b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1013
  	struct jprobe *jp = container_of(p, struct jprobe, kp);
3d7e33825   Michael Ellerman   jprobes: make jpr...
1014
  	unsigned long addr = arch_deref_entry_point(jp->entry);
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1015
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1016
1017
1018
1019
1020
1021
  	struct param_bsp_cfm pa;
  	int bytes;
  
  	/*
  	 * Callee owns the argument space and could overwrite it, eg
  	 * tail call optimization. So to be absolutely safe
72fdbdce3   Simon Arlott   [IA64] spelling f...
1022
  	 * we save the argument space before transferring the control
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
  	 * to instrumented jprobe function which runs in
  	 * the process context
  	 */
  	pa.ip = regs->cr_iip;
  	unw_init_running(ia64_get_bsp_cfm, &pa);
  	bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
  				- (char *)pa.bsp;
  	memcpy( kcb->jprobes_saved_stacked_regs,
  		pa.bsp,
  		bytes );
  	kcb->bsp = pa.bsp;
  	kcb->cfm = pa.cfm;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1035

b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1036
  	/* save architectural state */
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1037
  	kcb->jprobe_saved_regs = *regs;
b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  
  	/* after rfi, execute the jprobe instrumented function */
  	regs->cr_iip = addr & ~0xFULL;
  	ia64_psr(regs)->ri = addr & 0xf;
  	regs->r1 = ((struct fnptr *)(jp->entry))->gp;
  
  	/*
  	 * fix the return address to our jprobe_inst_return() function
  	 * in the jprobes.S file
  	 */
62c27be0d   bibo,mao   [PATCH] kprobe wh...
1048
  	regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip;
b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1049
1050
  
  	return 1;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1051
  }
9dad6f578   Adrian Bunk   [IA64] fix ia64 k...
1052
1053
1054
1055
  /* ia64 does not need this */
  void __kprobes jprobe_return(void)
  {
  }
1f7ad57b7   Prasanna S Panchamukhi   [PATCH] Kprobes: ...
1056
  int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1057
  {
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1058
  	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1059
  	int bytes;
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1060

d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1061
  	/* restoring architectural state */
8a5c4dc5e   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1062
  	*regs = kcb->jprobe_saved_regs;
d3ef1f5aa   Zhang Yanmin   [IA64] prevent ac...
1063
1064
1065
1066
1067
1068
1069
1070
1071
  
  	/* restoring the original argument space */
  	flush_register_stack();
  	bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f)
  				- (char *)kcb->bsp;
  	memcpy( kcb->bsp,
  		kcb->jprobes_saved_stacked_regs,
  		bytes );
  	invalidate_stacked_regs();
d217d5450   Ananth N Mavinakayanahalli   [PATCH] Kprobes: ...
1072
  	preempt_enable_no_resched();
b2761dc26   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1073
  	return 1;
fd7b231ff   Anil S Keshavamurthy   [PATCH] Kprobes/I...
1074
  }
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
1075
1076
1077
1078
  
  static struct kprobe trampoline_p = {
  	.pre_handler = trampoline_probe_handler
  };
6772926be   Rusty Lynch   [PATCH] kprobes: ...
1079
  int __init arch_init_kprobes(void)
9508dbfe3   Rusty Lynch   [PATCH] Return pr...
1080
1081
1082
1083
1084
  {
  	trampoline_p.addr =
  		(kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip;
  	return register_kprobe(&trampoline_p);
  }
bf8f6e5b3   Ananth N Mavinakayanahalli   Kprobes: The ON/O...
1085
1086
1087
1088
1089
1090
1091
1092
1093
  
  int __kprobes arch_trampoline_kprobe(struct kprobe *p)
  {
  	if (p->addr ==
  		(kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip)
  		return 1;
  
  	return 0;
  }