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