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