Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 116570
b: refs/heads/master
c: 611b159
h: refs/heads/master
v: v3
  • Loading branch information
Pekka Paalanen authored and Ingo Molnar committed Oct 14, 2008
1 parent 604e31d commit 66d35f4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5f87f1121895dc09d2d1c1db5f14af6aa4ce3e94
refs/heads/master: 611b1597680dd4a57896bcca1af0484be463c55e
121 changes: 84 additions & 37 deletions trunk/arch/x86/mm/pf_in.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,34 @@ static unsigned int mw32[] = { 0xC7 };
static unsigned int mw64[] = { 0x89, 0x8B };
#endif /* not __i386__ */

static int skip_prefix(unsigned char *addr, int *shorted, int *enlarged,
int *rexr)
struct prefix_bits {
unsigned shorted:1;
unsigned enlarged:1;
unsigned rexr:1;
unsigned rex:1;
};

static int skip_prefix(unsigned char *addr, struct prefix_bits *prf)
{
int i;
unsigned char *p = addr;
*shorted = 0;
*enlarged = 0;
*rexr = 0;
prf->shorted = 0;
prf->enlarged = 0;
prf->rexr = 0;
prf->rex = 0;

restart:
for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) {
if (*p == prefix_codes[i]) {
if (*p == 0x66)
*shorted = 1;
prf->shorted = 1;
#ifdef __amd64__
if ((*p & 0xf8) == 0x48)
*enlarged = 1;
prf->enlarged = 1;
if ((*p & 0xf4) == 0x44)
*rexr = 1;
prf->rexr = 1;
if ((*p & 0xf0) == 0x40)
prf->rex = 1;
#endif
p++;
goto restart;
Expand Down Expand Up @@ -135,12 +144,12 @@ enum reason_type get_ins_type(unsigned long ins_addr)
{
unsigned int opcode;
unsigned char *p;
int shorted, enlarged, rexr;
struct prefix_bits prf;
int i;
enum reason_type rv = OTHERS;

p = (unsigned char *)ins_addr;
p += skip_prefix(p, &shorted, &enlarged, &rexr);
p += skip_prefix(p, &prf);
p += get_opcode(p, &opcode);

CHECK_OP_TYPE(opcode, reg_rop, REG_READ);
Expand All @@ -156,10 +165,11 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr)
{
unsigned int opcode;
unsigned char *p;
int i, shorted, enlarged, rexr;
struct prefix_bits prf;
int i;

p = (unsigned char *)ins_addr;
p += skip_prefix(p, &shorted, &enlarged, &rexr);
p += skip_prefix(p, &prf);
p += get_opcode(p, &opcode);

for (i = 0; i < ARRAY_SIZE(rw8); i++)
Expand All @@ -168,7 +178,7 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr)

for (i = 0; i < ARRAY_SIZE(rw32); i++)
if (rw32[i] == opcode)
return (shorted ? 2 : (enlarged ? 8 : 4));
return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);

printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
return 0;
Expand All @@ -178,10 +188,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr)
{
unsigned int opcode;
unsigned char *p;
int i, shorted, enlarged, rexr;
struct prefix_bits prf;
int i;

p = (unsigned char *)ins_addr;
p += skip_prefix(p, &shorted, &enlarged, &rexr);
p += skip_prefix(p, &prf);
p += get_opcode(p, &opcode);

for (i = 0; i < ARRAY_SIZE(mw8); i++)
Expand All @@ -194,11 +205,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr)

for (i = 0; i < ARRAY_SIZE(mw32); i++)
if (mw32[i] == opcode)
return shorted ? 2 : 4;
return prf.shorted ? 2 : 4;

for (i = 0; i < ARRAY_SIZE(mw64); i++)
if (mw64[i] == opcode)
return shorted ? 2 : (enlarged ? 8 : 4);
return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);

printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
return 0;
Expand Down Expand Up @@ -238,7 +249,7 @@ enum {
#endif
};

static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs)
{
unsigned char *rv = NULL;

Expand All @@ -255,18 +266,6 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
case arg_DL:
rv = (unsigned char *)&regs->dx;
break;
case arg_AH:
rv = 1 + (unsigned char *)&regs->ax;
break;
case arg_BH:
rv = 1 + (unsigned char *)&regs->bx;
break;
case arg_CH:
rv = 1 + (unsigned char *)&regs->cx;
break;
case arg_DH:
rv = 1 + (unsigned char *)&regs->dx;
break;
#ifdef __amd64__
case arg_R8:
rv = (unsigned char *)&regs->r8;
Expand Down Expand Up @@ -294,9 +293,55 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
break;
#endif
default:
printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
break;
}

if (rv)
return rv;

if (rex) {
/*
* If REX prefix exists, access low bytes of SI etc.
* instead of AH etc.
*/
switch (no) {
case arg_SI:
rv = (unsigned char *)&regs->si;
break;
case arg_DI:
rv = (unsigned char *)&regs->di;
break;
case arg_BP:
rv = (unsigned char *)&regs->bp;
break;
case arg_SP:
rv = (unsigned char *)&regs->sp;
break;
default:
break;
}
} else {
switch (no) {
case arg_AH:
rv = 1 + (unsigned char *)&regs->ax;
break;
case arg_BH:
rv = 1 + (unsigned char *)&regs->bx;
break;
case arg_CH:
rv = 1 + (unsigned char *)&regs->cx;
break;
case arg_DH:
rv = 1 + (unsigned char *)&regs->dx;
break;
default:
break;
}
}

if (!rv)
printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);

return rv;
}

Expand Down Expand Up @@ -368,11 +413,12 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
unsigned char mod_rm;
int reg;
unsigned char *p;
int i, shorted, enlarged, rexr;
struct prefix_bits prf;
int i;
unsigned long rv;

p = (unsigned char *)ins_addr;
p += skip_prefix(p, &shorted, &enlarged, &rexr);
p += skip_prefix(p, &prf);
p += get_opcode(p, &opcode);
for (i = 0; i < ARRAY_SIZE(reg_rop); i++)
if (reg_rop[i] == opcode) {
Expand All @@ -392,10 +438,10 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)

do_work:
mod_rm = *p;
reg = ((mod_rm >> 3) & 0x7) | (rexr << 3);
reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3);
switch (get_ins_reg_width(ins_addr)) {
case 1:
return *get_reg_w8(reg, regs);
return *get_reg_w8(reg, prf.rex, regs);

case 2:
return *(unsigned short *)get_reg_w32(reg, regs);
Expand All @@ -422,11 +468,12 @@ unsigned long get_ins_imm_val(unsigned long ins_addr)
unsigned char mod_rm;
unsigned char mod;
unsigned char *p;
int i, shorted, enlarged, rexr;
struct prefix_bits prf;
int i;
unsigned long rv;

p = (unsigned char *)ins_addr;
p += skip_prefix(p, &shorted, &enlarged, &rexr);
p += skip_prefix(p, &prf);
p += get_opcode(p, &opcode);
for (i = 0; i < ARRAY_SIZE(imm_wop); i++)
if (imm_wop[i] == opcode) {
Expand Down

0 comments on commit 66d35f4

Please sign in to comment.