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