pf_in.c (10068B)
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 */ 19static unsigned char prefix_codes[] = { 20 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64, 21 0x65, 0x66, 0x67 22}; 23/* IA32 Manual 3, 3-432*/ 24static unsigned int reg_rop[] = { 25 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F 26}; 27static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; 28static unsigned int imm_wop[] = { 0xC6, 0xC7 }; 29/* IA32 Manual 3, 3-432*/ 30static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA }; 31static unsigned int rw32[] = { 32 0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB 33}; 34static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA }; 35static unsigned int mw16[] = { 0xB70F, 0xBF0F }; 36static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB }; 37static unsigned int mw64[] = {}; 38#else /* not __i386__ */ 39static 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*/ 47static unsigned int reg_rop[] = { 48 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F 49}; 50static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; 51static unsigned int imm_wop[] = { 0xC6, 0xC7 }; 52static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA }; 53static unsigned int rw32[] = { 54 0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB 55}; 56/* 8 bit only */ 57static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA }; 58/* 16 bit only */ 59static unsigned int mw16[] = { 0xB70F, 0xBF0F }; 60/* 16 or 32 bit */ 61static unsigned int mw32[] = { 0xC7 }; 62/* 16, 32 or 64 bit */ 63static unsigned int mw64[] = { 0x89, 0x8B, 0xAB }; 64#endif /* not __i386__ */ 65 66struct prefix_bits { 67 unsigned shorted:1; 68 unsigned enlarged:1; 69 unsigned rexr:1; 70 unsigned rex:1; 71}; 72 73static 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 82restart: 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 103static 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 127enum 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 143exit: 144 return rv; 145} 146#undef CHECK_OP_TYPE 147 148static 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 171unsigned 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 */ 206enum { 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 236static 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 332static 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 394unsigned 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 417do_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 444err: 445 return 0; 446} 447 448unsigned 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 468do_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 514err: 515 return 0; 516}