xref: /openbmc/linux/arch/x86/mm/pf_in.c (revision 82003e04)
1 /*
2  *  Fault Injection Test harness (FI)
3  *  Copyright (C) Intel Crop.
4  *
5  *  This program is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU General Public License
7  *  as published by the Free Software Foundation; either version 2
8  *  of the License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18  *  USA.
19  *
20  */
21 
22 /*  Id: pf_in.c,v 1.1.1.1 2002/11/12 05:56:32 brlock Exp
23  *  Copyright by Intel Crop., 2002
24  *  Louis Zhuang (louis.zhuang@intel.com)
25  *
26  *  Bjorn Steinbrink (B.Steinbrink@gmx.de), 2007
27  */
28 
29 #include <linux/ptrace.h> /* struct pt_regs */
30 #include "pf_in.h"
31 
32 #ifdef __i386__
33 /* IA32 Manual 3, 2-1 */
34 static unsigned char prefix_codes[] = {
35 	0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64,
36 	0x65, 0x66, 0x67
37 };
38 /* IA32 Manual 3, 3-432*/
39 static unsigned int reg_rop[] = {
40 	0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
41 };
42 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
43 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
44 /* IA32 Manual 3, 3-432*/
45 static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA };
46 static unsigned int rw32[] = {
47 	0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
48 };
49 static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA };
50 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
51 static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB };
52 static unsigned int mw64[] = {};
53 #else /* not __i386__ */
54 static unsigned char prefix_codes[] = {
55 	0x66, 0x67, 0x2E, 0x3E, 0x26, 0x64, 0x65, 0x36,
56 	0xF0, 0xF3, 0xF2,
57 	/* REX Prefixes */
58 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
59 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
60 };
61 /* AMD64 Manual 3, Appendix A*/
62 static unsigned int reg_rop[] = {
63 	0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
64 };
65 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
66 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
67 static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA };
68 static unsigned int rw32[] = {
69 	0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
70 };
71 /* 8 bit only */
72 static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA };
73 /* 16 bit only */
74 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
75 /* 16 or 32 bit */
76 static unsigned int mw32[] = { 0xC7 };
77 /* 16, 32 or 64 bit */
78 static unsigned int mw64[] = { 0x89, 0x8B, 0xAB };
79 #endif /* not __i386__ */
80 
81 struct prefix_bits {
82 	unsigned shorted:1;
83 	unsigned enlarged:1;
84 	unsigned rexr:1;
85 	unsigned rex:1;
86 };
87 
88 static int skip_prefix(unsigned char *addr, struct prefix_bits *prf)
89 {
90 	int i;
91 	unsigned char *p = addr;
92 	prf->shorted = 0;
93 	prf->enlarged = 0;
94 	prf->rexr = 0;
95 	prf->rex = 0;
96 
97 restart:
98 	for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) {
99 		if (*p == prefix_codes[i]) {
100 			if (*p == 0x66)
101 				prf->shorted = 1;
102 #ifdef __amd64__
103 			if ((*p & 0xf8) == 0x48)
104 				prf->enlarged = 1;
105 			if ((*p & 0xf4) == 0x44)
106 				prf->rexr = 1;
107 			if ((*p & 0xf0) == 0x40)
108 				prf->rex = 1;
109 #endif
110 			p++;
111 			goto restart;
112 		}
113 	}
114 
115 	return (p - addr);
116 }
117 
118 static int get_opcode(unsigned char *addr, unsigned int *opcode)
119 {
120 	int len;
121 
122 	if (*addr == 0x0F) {
123 		/* 0x0F is extension instruction */
124 		*opcode = *(unsigned short *)addr;
125 		len = 2;
126 	} else {
127 		*opcode = *addr;
128 		len = 1;
129 	}
130 
131 	return len;
132 }
133 
134 #define CHECK_OP_TYPE(opcode, array, type) \
135 	for (i = 0; i < ARRAY_SIZE(array); i++) { \
136 		if (array[i] == opcode) { \
137 			rv = type; \
138 			goto exit; \
139 		} \
140 	}
141 
142 enum reason_type get_ins_type(unsigned long ins_addr)
143 {
144 	unsigned int opcode;
145 	unsigned char *p;
146 	struct prefix_bits prf;
147 	int i;
148 	enum reason_type rv = OTHERS;
149 
150 	p = (unsigned char *)ins_addr;
151 	p += skip_prefix(p, &prf);
152 	p += get_opcode(p, &opcode);
153 
154 	CHECK_OP_TYPE(opcode, reg_rop, REG_READ);
155 	CHECK_OP_TYPE(opcode, reg_wop, REG_WRITE);
156 	CHECK_OP_TYPE(opcode, imm_wop, IMM_WRITE);
157 
158 exit:
159 	return rv;
160 }
161 #undef CHECK_OP_TYPE
162 
163 static unsigned int get_ins_reg_width(unsigned long ins_addr)
164 {
165 	unsigned int opcode;
166 	unsigned char *p;
167 	struct prefix_bits prf;
168 	int i;
169 
170 	p = (unsigned char *)ins_addr;
171 	p += skip_prefix(p, &prf);
172 	p += get_opcode(p, &opcode);
173 
174 	for (i = 0; i < ARRAY_SIZE(rw8); i++)
175 		if (rw8[i] == opcode)
176 			return 1;
177 
178 	for (i = 0; i < ARRAY_SIZE(rw32); i++)
179 		if (rw32[i] == opcode)
180 			return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
181 
182 	printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
183 	return 0;
184 }
185 
186 unsigned int get_ins_mem_width(unsigned long ins_addr)
187 {
188 	unsigned int opcode;
189 	unsigned char *p;
190 	struct prefix_bits prf;
191 	int i;
192 
193 	p = (unsigned char *)ins_addr;
194 	p += skip_prefix(p, &prf);
195 	p += get_opcode(p, &opcode);
196 
197 	for (i = 0; i < ARRAY_SIZE(mw8); i++)
198 		if (mw8[i] == opcode)
199 			return 1;
200 
201 	for (i = 0; i < ARRAY_SIZE(mw16); i++)
202 		if (mw16[i] == opcode)
203 			return 2;
204 
205 	for (i = 0; i < ARRAY_SIZE(mw32); i++)
206 		if (mw32[i] == opcode)
207 			return prf.shorted ? 2 : 4;
208 
209 	for (i = 0; i < ARRAY_SIZE(mw64); i++)
210 		if (mw64[i] == opcode)
211 			return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
212 
213 	printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
214 	return 0;
215 }
216 
217 /*
218  * Define register ident in mod/rm byte.
219  * Note: these are NOT the same as in ptrace-abi.h.
220  */
221 enum {
222 	arg_AL = 0,
223 	arg_CL = 1,
224 	arg_DL = 2,
225 	arg_BL = 3,
226 	arg_AH = 4,
227 	arg_CH = 5,
228 	arg_DH = 6,
229 	arg_BH = 7,
230 
231 	arg_AX = 0,
232 	arg_CX = 1,
233 	arg_DX = 2,
234 	arg_BX = 3,
235 	arg_SP = 4,
236 	arg_BP = 5,
237 	arg_SI = 6,
238 	arg_DI = 7,
239 #ifdef __amd64__
240 	arg_R8  = 8,
241 	arg_R9  = 9,
242 	arg_R10 = 10,
243 	arg_R11 = 11,
244 	arg_R12 = 12,
245 	arg_R13 = 13,
246 	arg_R14 = 14,
247 	arg_R15 = 15
248 #endif
249 };
250 
251 static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs)
252 {
253 	unsigned char *rv = NULL;
254 
255 	switch (no) {
256 	case arg_AL:
257 		rv = (unsigned char *)&regs->ax;
258 		break;
259 	case arg_BL:
260 		rv = (unsigned char *)&regs->bx;
261 		break;
262 	case arg_CL:
263 		rv = (unsigned char *)&regs->cx;
264 		break;
265 	case arg_DL:
266 		rv = (unsigned char *)&regs->dx;
267 		break;
268 #ifdef __amd64__
269 	case arg_R8:
270 		rv = (unsigned char *)&regs->r8;
271 		break;
272 	case arg_R9:
273 		rv = (unsigned char *)&regs->r9;
274 		break;
275 	case arg_R10:
276 		rv = (unsigned char *)&regs->r10;
277 		break;
278 	case arg_R11:
279 		rv = (unsigned char *)&regs->r11;
280 		break;
281 	case arg_R12:
282 		rv = (unsigned char *)&regs->r12;
283 		break;
284 	case arg_R13:
285 		rv = (unsigned char *)&regs->r13;
286 		break;
287 	case arg_R14:
288 		rv = (unsigned char *)&regs->r14;
289 		break;
290 	case arg_R15:
291 		rv = (unsigned char *)&regs->r15;
292 		break;
293 #endif
294 	default:
295 		break;
296 	}
297 
298 	if (rv)
299 		return rv;
300 
301 	if (rex) {
302 		/*
303 		 * If REX prefix exists, access low bytes of SI etc.
304 		 * instead of AH etc.
305 		 */
306 		switch (no) {
307 		case arg_SI:
308 			rv = (unsigned char *)&regs->si;
309 			break;
310 		case arg_DI:
311 			rv = (unsigned char *)&regs->di;
312 			break;
313 		case arg_BP:
314 			rv = (unsigned char *)&regs->bp;
315 			break;
316 		case arg_SP:
317 			rv = (unsigned char *)&regs->sp;
318 			break;
319 		default:
320 			break;
321 		}
322 	} else {
323 		switch (no) {
324 		case arg_AH:
325 			rv = 1 + (unsigned char *)&regs->ax;
326 			break;
327 		case arg_BH:
328 			rv = 1 + (unsigned char *)&regs->bx;
329 			break;
330 		case arg_CH:
331 			rv = 1 + (unsigned char *)&regs->cx;
332 			break;
333 		case arg_DH:
334 			rv = 1 + (unsigned char *)&regs->dx;
335 			break;
336 		default:
337 			break;
338 		}
339 	}
340 
341 	if (!rv)
342 		printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
343 
344 	return rv;
345 }
346 
347 static unsigned long *get_reg_w32(int no, struct pt_regs *regs)
348 {
349 	unsigned long *rv = NULL;
350 
351 	switch (no) {
352 	case arg_AX:
353 		rv = &regs->ax;
354 		break;
355 	case arg_BX:
356 		rv = &regs->bx;
357 		break;
358 	case arg_CX:
359 		rv = &regs->cx;
360 		break;
361 	case arg_DX:
362 		rv = &regs->dx;
363 		break;
364 	case arg_SP:
365 		rv = &regs->sp;
366 		break;
367 	case arg_BP:
368 		rv = &regs->bp;
369 		break;
370 	case arg_SI:
371 		rv = &regs->si;
372 		break;
373 	case arg_DI:
374 		rv = &regs->di;
375 		break;
376 #ifdef __amd64__
377 	case arg_R8:
378 		rv = &regs->r8;
379 		break;
380 	case arg_R9:
381 		rv = &regs->r9;
382 		break;
383 	case arg_R10:
384 		rv = &regs->r10;
385 		break;
386 	case arg_R11:
387 		rv = &regs->r11;
388 		break;
389 	case arg_R12:
390 		rv = &regs->r12;
391 		break;
392 	case arg_R13:
393 		rv = &regs->r13;
394 		break;
395 	case arg_R14:
396 		rv = &regs->r14;
397 		break;
398 	case arg_R15:
399 		rv = &regs->r15;
400 		break;
401 #endif
402 	default:
403 		printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
404 	}
405 
406 	return rv;
407 }
408 
409 unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
410 {
411 	unsigned int opcode;
412 	int reg;
413 	unsigned char *p;
414 	struct prefix_bits prf;
415 	int i;
416 
417 	p = (unsigned char *)ins_addr;
418 	p += skip_prefix(p, &prf);
419 	p += get_opcode(p, &opcode);
420 	for (i = 0; i < ARRAY_SIZE(reg_rop); i++)
421 		if (reg_rop[i] == opcode)
422 			goto do_work;
423 
424 	for (i = 0; i < ARRAY_SIZE(reg_wop); i++)
425 		if (reg_wop[i] == opcode)
426 			goto do_work;
427 
428 	printk(KERN_ERR "mmiotrace: Not a register instruction, opcode "
429 							"0x%02x\n", opcode);
430 	goto err;
431 
432 do_work:
433 	/* for STOS, source register is fixed */
434 	if (opcode == 0xAA || opcode == 0xAB) {
435 		reg = arg_AX;
436 	} else {
437 		unsigned char mod_rm = *p;
438 		reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3);
439 	}
440 	switch (get_ins_reg_width(ins_addr)) {
441 	case 1:
442 		return *get_reg_w8(reg, prf.rex, regs);
443 
444 	case 2:
445 		return *(unsigned short *)get_reg_w32(reg, regs);
446 
447 	case 4:
448 		return *(unsigned int *)get_reg_w32(reg, regs);
449 
450 #ifdef __amd64__
451 	case 8:
452 		return *(unsigned long *)get_reg_w32(reg, regs);
453 #endif
454 
455 	default:
456 		printk(KERN_ERR "mmiotrace: Error width# %d\n", reg);
457 	}
458 
459 err:
460 	return 0;
461 }
462 
463 unsigned long get_ins_imm_val(unsigned long ins_addr)
464 {
465 	unsigned int opcode;
466 	unsigned char mod_rm;
467 	unsigned char mod;
468 	unsigned char *p;
469 	struct prefix_bits prf;
470 	int i;
471 
472 	p = (unsigned char *)ins_addr;
473 	p += skip_prefix(p, &prf);
474 	p += get_opcode(p, &opcode);
475 	for (i = 0; i < ARRAY_SIZE(imm_wop); i++)
476 		if (imm_wop[i] == opcode)
477 			goto do_work;
478 
479 	printk(KERN_ERR "mmiotrace: Not an immediate instruction, opcode "
480 							"0x%02x\n", opcode);
481 	goto err;
482 
483 do_work:
484 	mod_rm = *p;
485 	mod = mod_rm >> 6;
486 	p++;
487 	switch (mod) {
488 	case 0:
489 		/* if r/m is 5 we have a 32 disp (IA32 Manual 3, Table 2-2)  */
490 		/* AMD64: XXX Check for address size prefix? */
491 		if ((mod_rm & 0x7) == 0x5)
492 			p += 4;
493 		break;
494 
495 	case 1:
496 		p += 1;
497 		break;
498 
499 	case 2:
500 		p += 4;
501 		break;
502 
503 	case 3:
504 	default:
505 		printk(KERN_ERR "mmiotrace: not a memory access instruction "
506 						"at 0x%lx, rm_mod=0x%02x\n",
507 						ins_addr, mod_rm);
508 	}
509 
510 	switch (get_ins_reg_width(ins_addr)) {
511 	case 1:
512 		return *(unsigned char *)p;
513 
514 	case 2:
515 		return *(unsigned short *)p;
516 
517 	case 4:
518 		return *(unsigned int *)p;
519 
520 #ifdef __amd64__
521 	case 8:
522 		return *(unsigned long *)p;
523 #endif
524 
525 	default:
526 		printk(KERN_ERR "mmiotrace: Error: width.\n");
527 	}
528 
529 err:
530 	return 0;
531 }
532