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