linux/arch/x86/mm/pf_in.c
<<
>>
Prefs
   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 *)&regs->ax;
 243                break;
 244        case arg_BL:
 245                rv = (unsigned char *)&regs->bx;
 246                break;
 247        case arg_CL:
 248                rv = (unsigned char *)&regs->cx;
 249                break;
 250        case arg_DL:
 251                rv = (unsigned char *)&regs->dx;
 252                break;
 253#ifdef __amd64__
 254        case arg_R8:
 255                rv = (unsigned char *)&regs->r8;
 256                break;
 257        case arg_R9:
 258                rv = (unsigned char *)&regs->r9;
 259                break;
 260        case arg_R10:
 261                rv = (unsigned char *)&regs->r10;
 262                break;
 263        case arg_R11:
 264                rv = (unsigned char *)&regs->r11;
 265                break;
 266        case arg_R12:
 267                rv = (unsigned char *)&regs->r12;
 268                break;
 269        case arg_R13:
 270                rv = (unsigned char *)&regs->r13;
 271                break;
 272        case arg_R14:
 273                rv = (unsigned char *)&regs->r14;
 274                break;
 275        case arg_R15:
 276                rv = (unsigned char *)&regs->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 *)&regs->si;
 294                        break;
 295                case arg_DI:
 296                        rv = (unsigned char *)&regs->di;
 297                        break;
 298                case arg_BP:
 299                        rv = (unsigned char *)&regs->bp;
 300                        break;
 301                case arg_SP:
 302                        rv = (unsigned char *)&regs->sp;
 303                        break;
 304                default:
 305                        break;
 306                }
 307        } else {
 308                switch (no) {
 309                case arg_AH:
 310                        rv = 1 + (unsigned char *)&regs->ax;
 311                        break;
 312                case arg_BH:
 313                        rv = 1 + (unsigned char *)&regs->bx;
 314                        break;
 315                case arg_CH:
 316                        rv = 1 + (unsigned char *)&regs->cx;
 317                        break;
 318                case arg_DH:
 319                        rv = 1 + (unsigned char *)&regs->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 = &regs->ax;
 339                break;
 340        case arg_BX:
 341                rv = &regs->bx;
 342                break;
 343        case arg_CX:
 344                rv = &regs->cx;
 345                break;
 346        case arg_DX:
 347                rv = &regs->dx;
 348                break;
 349        case arg_SP:
 350                rv = &regs->sp;
 351                break;
 352        case arg_BP:
 353                rv = &regs->bp;
 354                break;
 355        case arg_SI:
 356                rv = &regs->si;
 357                break;
 358        case arg_DI:
 359                rv = &regs->di;
 360                break;
 361#ifdef __amd64__
 362        case arg_R8:
 363                rv = &regs->r8;
 364                break;
 365        case arg_R9:
 366                rv = &regs->r9;
 367                break;
 368        case arg_R10:
 369                rv = &regs->r10;
 370                break;
 371        case arg_R11:
 372                rv = &regs->r11;
 373                break;
 374        case arg_R12:
 375                rv = &regs->r12;
 376                break;
 377        case arg_R13:
 378                rv = &regs->r13;
 379                break;
 380        case arg_R14:
 381                rv = &regs->r14;
 382                break;
 383        case arg_R15:
 384                rv = &regs->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}
 517