KVM: x86 emulator: use correct type for memory address in operands

Currently we use a void pointer for memory addresses.  That's wrong since
these are guest virtual addresses which are not directly dereferencable by
the host.

Use the correct type, unsigned long.

Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Avi Kivity 2010-08-01 12:35:10 +03:00
parent 09ee57cdae
commit 1a6440aef6
2 changed files with 61 additions and 61 deletions

View File

@ -156,7 +156,10 @@ struct operand {
unsigned long orig_val; unsigned long orig_val;
u64 orig_val64; u64 orig_val64;
}; };
unsigned long *ptr; union {
unsigned long *reg;
unsigned long mem;
} addr;
union { union {
unsigned long val; unsigned long val;
u64 val64; u64 val64;

View File

@ -489,7 +489,7 @@ static void *decode_register(u8 modrm_reg, unsigned long *regs,
static int read_descriptor(struct x86_emulate_ctxt *ctxt, static int read_descriptor(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops, struct x86_emulate_ops *ops,
void *ptr, ulong addr,
u16 *size, unsigned long *address, int op_bytes) u16 *size, unsigned long *address, int op_bytes)
{ {
int rc; int rc;
@ -497,12 +497,10 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
if (op_bytes == 2) if (op_bytes == 2)
op_bytes = 3; op_bytes = 3;
*address = 0; *address = 0;
rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, rc = ops->read_std(addr, (unsigned long *)size, 2, ctxt->vcpu, NULL);
ctxt->vcpu, NULL);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
return rc; return rc;
rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, rc = ops->read_std(addr + 2, address, op_bytes, ctxt->vcpu, NULL);
ctxt->vcpu, NULL);
return rc; return rc;
} }
@ -552,21 +550,21 @@ static void decode_register_operand(struct operand *op,
reg = (c->b & 7) | ((c->rex_prefix & 1) << 3); reg = (c->b & 7) | ((c->rex_prefix & 1) << 3);
op->type = OP_REG; op->type = OP_REG;
if ((c->d & ByteOp) && !inhibit_bytereg) { if ((c->d & ByteOp) && !inhibit_bytereg) {
op->ptr = decode_register(reg, c->regs, highbyte_regs); op->addr.reg = decode_register(reg, c->regs, highbyte_regs);
op->val = *(u8 *)op->ptr; op->val = *(u8 *)op->addr.reg;
op->bytes = 1; op->bytes = 1;
} else { } else {
op->ptr = decode_register(reg, c->regs, 0); op->addr.reg = decode_register(reg, c->regs, 0);
op->bytes = c->op_bytes; op->bytes = c->op_bytes;
switch (op->bytes) { switch (op->bytes) {
case 2: case 2:
op->val = *(u16 *)op->ptr; op->val = *(u16 *)op->addr.reg;
break; break;
case 4: case 4:
op->val = *(u32 *)op->ptr; op->val = *(u32 *)op->addr.reg;
break; break;
case 8: case 8:
op->val = *(u64 *) op->ptr; op->val = *(u64 *) op->addr.reg;
break; break;
} }
} }
@ -976,23 +974,23 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
*/ */
switch (c->dst.bytes) { switch (c->dst.bytes) {
case 1: case 1:
*(u8 *)c->dst.ptr = (u8)c->dst.val; *(u8 *)c->dst.addr.reg = (u8)c->dst.val;
break; break;
case 2: case 2:
*(u16 *)c->dst.ptr = (u16)c->dst.val; *(u16 *)c->dst.addr.reg = (u16)c->dst.val;
break; break;
case 4: case 4:
*c->dst.ptr = (u32)c->dst.val; *c->dst.addr.reg = (u32)c->dst.val;
break; /* 64b: zero-ext */ break; /* 64b: zero-ext */
case 8: case 8:
*c->dst.ptr = c->dst.val; *c->dst.addr.reg = c->dst.val;
break; break;
} }
break; break;
case OP_MEM: case OP_MEM:
if (c->lock_prefix) if (c->lock_prefix)
rc = ops->cmpxchg_emulated( rc = ops->cmpxchg_emulated(
(unsigned long)c->dst.ptr, c->dst.addr.mem,
&c->dst.orig_val, &c->dst.orig_val,
&c->dst.val, &c->dst.val,
c->dst.bytes, c->dst.bytes,
@ -1000,14 +998,13 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
ctxt->vcpu); ctxt->vcpu);
else else
rc = ops->write_emulated( rc = ops->write_emulated(
(unsigned long)c->dst.ptr, c->dst.addr.mem,
&c->dst.val, &c->dst.val,
c->dst.bytes, c->dst.bytes,
&err, &err,
ctxt->vcpu); ctxt->vcpu);
if (rc == X86EMUL_PROPAGATE_FAULT) if (rc == X86EMUL_PROPAGATE_FAULT)
emulate_pf(ctxt, emulate_pf(ctxt, c->dst.addr.mem, err);
(unsigned long)c->dst.ptr, err);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
return rc; return rc;
break; break;
@ -1029,8 +1026,8 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt,
c->dst.bytes = c->op_bytes; c->dst.bytes = c->op_bytes;
c->dst.val = c->src.val; c->dst.val = c->src.val;
register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes); register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
c->dst.ptr = (void *) register_address(c, ss_base(ctxt, ops), c->dst.addr.mem = register_address(c, ss_base(ctxt, ops),
c->regs[VCPU_REGS_RSP]); c->regs[VCPU_REGS_RSP]);
} }
static int emulate_pop(struct x86_emulate_ctxt *ctxt, static int emulate_pop(struct x86_emulate_ctxt *ctxt,
@ -2019,7 +2016,7 @@ static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned long base,
int df = (ctxt->eflags & EFLG_DF) ? -1 : 1; int df = (ctxt->eflags & EFLG_DF) ? -1 : 1;
register_address_increment(c, &c->regs[reg], df * op->bytes); register_address_increment(c, &c->regs[reg], df * op->bytes);
op->ptr = (unsigned long *)register_address(c, base, c->regs[reg]); op->addr.mem = register_address(c, base, c->regs[reg]);
} }
static int em_push(struct x86_emulate_ctxt *ctxt) static int em_push(struct x86_emulate_ctxt *ctxt)
@ -2456,17 +2453,17 @@ done_prefixes:
if ((c->d & ModRM) && c->modrm_mod == 3) { if ((c->d & ModRM) && c->modrm_mod == 3) {
c->src.type = OP_REG; c->src.type = OP_REG;
c->src.val = c->modrm_val; c->src.val = c->modrm_val;
c->src.ptr = c->modrm_ptr; c->src.addr.reg = c->modrm_ptr;
break; break;
} }
c->src.type = OP_MEM; c->src.type = OP_MEM;
c->src.ptr = (unsigned long *)c->modrm_ea; c->src.addr.mem = c->modrm_ea;
c->src.val = 0; c->src.val = 0;
break; break;
case SrcImm: case SrcImm:
case SrcImmU: case SrcImmU:
c->src.type = OP_IMM; c->src.type = OP_IMM;
c->src.ptr = (unsigned long *)c->eip; c->src.addr.mem = c->eip;
c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
if (c->src.bytes == 8) if (c->src.bytes == 8)
c->src.bytes = 4; c->src.bytes = 4;
@ -2499,7 +2496,7 @@ done_prefixes:
case SrcImmByte: case SrcImmByte:
case SrcImmUByte: case SrcImmUByte:
c->src.type = OP_IMM; c->src.type = OP_IMM;
c->src.ptr = (unsigned long *)c->eip; c->src.addr.mem = c->eip;
c->src.bytes = 1; c->src.bytes = 1;
if ((c->d & SrcMask) == SrcImmByte) if ((c->d & SrcMask) == SrcImmByte)
c->src.val = insn_fetch(s8, 1, c->eip); c->src.val = insn_fetch(s8, 1, c->eip);
@ -2509,19 +2506,19 @@ done_prefixes:
case SrcAcc: case SrcAcc:
c->src.type = OP_REG; c->src.type = OP_REG;
c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->src.ptr = &c->regs[VCPU_REGS_RAX]; c->src.addr.reg = &c->regs[VCPU_REGS_RAX];
switch (c->src.bytes) { switch (c->src.bytes) {
case 1: case 1:
c->src.val = *(u8 *)c->src.ptr; c->src.val = *(u8 *)c->src.addr.reg;
break; break;
case 2: case 2:
c->src.val = *(u16 *)c->src.ptr; c->src.val = *(u16 *)c->src.addr.reg;
break; break;
case 4: case 4:
c->src.val = *(u32 *)c->src.ptr; c->src.val = *(u32 *)c->src.addr.reg;
break; break;
case 8: case 8:
c->src.val = *(u64 *)c->src.ptr; c->src.val = *(u64 *)c->src.addr.reg;
break; break;
} }
break; break;
@ -2532,20 +2529,20 @@ done_prefixes:
case SrcSI: case SrcSI:
c->src.type = OP_MEM; c->src.type = OP_MEM;
c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->src.ptr = (unsigned long *) c->src.addr.mem =
register_address(c, seg_override_base(ctxt, ops, c), register_address(c, seg_override_base(ctxt, ops, c),
c->regs[VCPU_REGS_RSI]); c->regs[VCPU_REGS_RSI]);
c->src.val = 0; c->src.val = 0;
break; break;
case SrcImmFAddr: case SrcImmFAddr:
c->src.type = OP_IMM; c->src.type = OP_IMM;
c->src.ptr = (unsigned long *)c->eip; c->src.addr.mem = c->eip;
c->src.bytes = c->op_bytes + 2; c->src.bytes = c->op_bytes + 2;
insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip); insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
break; break;
case SrcMemFAddr: case SrcMemFAddr:
c->src.type = OP_MEM; c->src.type = OP_MEM;
c->src.ptr = (unsigned long *)c->modrm_ea; c->src.addr.mem = c->modrm_ea;
c->src.bytes = c->op_bytes + 2; c->src.bytes = c->op_bytes + 2;
break; break;
} }
@ -2563,7 +2560,7 @@ done_prefixes:
break; break;
case Src2ImmByte: case Src2ImmByte:
c->src2.type = OP_IMM; c->src2.type = OP_IMM;
c->src2.ptr = (unsigned long *)c->eip; c->src2.addr.mem = c->eip;
c->src2.bytes = 1; c->src2.bytes = 1;
c->src2.val = insn_fetch(u8, 1, c->eip); c->src2.val = insn_fetch(u8, 1, c->eip);
break; break;
@ -2588,11 +2585,11 @@ done_prefixes:
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->dst.type = OP_REG; c->dst.type = OP_REG;
c->dst.val = c->dst.orig_val = c->modrm_val; c->dst.val = c->dst.orig_val = c->modrm_val;
c->dst.ptr = c->modrm_ptr; c->dst.addr.reg = c->modrm_ptr;
break; break;
} }
c->dst.type = OP_MEM; c->dst.type = OP_MEM;
c->dst.ptr = (unsigned long *)c->modrm_ea; c->dst.addr.mem = c->modrm_ea;
if ((c->d & DstMask) == DstMem64) if ((c->d & DstMask) == DstMem64)
c->dst.bytes = 8; c->dst.bytes = 8;
else else
@ -2601,26 +2598,26 @@ done_prefixes:
if (c->d & BitOp) { if (c->d & BitOp) {
unsigned long mask = ~(c->dst.bytes * 8 - 1); unsigned long mask = ~(c->dst.bytes * 8 - 1);
c->dst.ptr = (void *)c->dst.ptr + c->dst.addr.mem = c->dst.addr.mem +
(c->src.val & mask) / 8; (c->src.val & mask) / 8;
} }
break; break;
case DstAcc: case DstAcc:
c->dst.type = OP_REG; c->dst.type = OP_REG;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->dst.ptr = &c->regs[VCPU_REGS_RAX]; c->dst.addr.reg = &c->regs[VCPU_REGS_RAX];
switch (c->dst.bytes) { switch (c->dst.bytes) {
case 1: case 1:
c->dst.val = *(u8 *)c->dst.ptr; c->dst.val = *(u8 *)c->dst.addr.reg;
break; break;
case 2: case 2:
c->dst.val = *(u16 *)c->dst.ptr; c->dst.val = *(u16 *)c->dst.addr.reg;
break; break;
case 4: case 4:
c->dst.val = *(u32 *)c->dst.ptr; c->dst.val = *(u32 *)c->dst.addr.reg;
break; break;
case 8: case 8:
c->dst.val = *(u64 *)c->dst.ptr; c->dst.val = *(u64 *)c->dst.addr.reg;
break; break;
} }
c->dst.orig_val = c->dst.val; c->dst.orig_val = c->dst.val;
@ -2628,7 +2625,7 @@ done_prefixes:
case DstDI: case DstDI:
c->dst.type = OP_MEM; c->dst.type = OP_MEM;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->dst.ptr = (unsigned long *) c->dst.addr.mem =
register_address(c, es_base(ctxt, ops), register_address(c, es_base(ctxt, ops),
c->regs[VCPU_REGS_RDI]); c->regs[VCPU_REGS_RDI]);
c->dst.val = 0; c->dst.val = 0;
@ -2696,7 +2693,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
} }
if (c->src.type == OP_MEM) { if (c->src.type == OP_MEM) {
rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr, rc = read_emulated(ctxt, ops, c->src.addr.mem,
c->src.valptr, c->src.bytes); c->src.valptr, c->src.bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
goto done; goto done;
@ -2704,7 +2701,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
} }
if (c->src2.type == OP_MEM) { if (c->src2.type == OP_MEM) {
rc = read_emulated(ctxt, ops, (unsigned long)c->src2.ptr, rc = read_emulated(ctxt, ops, c->src2.addr.mem,
&c->src2.val, c->src2.bytes); &c->src2.val, c->src2.bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
goto done; goto done;
@ -2716,7 +2713,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { if ((c->dst.type == OP_MEM) && !(c->d & Mov)) {
/* optimisation - avoid slow emulated read if Mov */ /* optimisation - avoid slow emulated read if Mov */
rc = read_emulated(ctxt, ops, (unsigned long)c->dst.ptr, rc = read_emulated(ctxt, ops, c->dst.addr.mem,
&c->dst.val, c->dst.bytes); &c->dst.val, c->dst.bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
goto done; goto done;
@ -2880,16 +2877,16 @@ special_insn:
/* Write back the register source. */ /* Write back the register source. */
switch (c->dst.bytes) { switch (c->dst.bytes) {
case 1: case 1:
*(u8 *) c->src.ptr = (u8) c->dst.val; *(u8 *) c->src.addr.reg = (u8) c->dst.val;
break; break;
case 2: case 2:
*(u16 *) c->src.ptr = (u16) c->dst.val; *(u16 *) c->src.addr.reg = (u16) c->dst.val;
break; break;
case 4: case 4:
*c->src.ptr = (u32) c->dst.val; *c->src.addr.reg = (u32) c->dst.val;
break; /* 64b reg: zero-extend */ break; /* 64b reg: zero-extend */
case 8: case 8:
*c->src.ptr = c->dst.val; *c->src.addr.reg = c->dst.val;
break; break;
} }
/* /*
@ -2936,15 +2933,15 @@ special_insn:
goto done; goto done;
break; break;
case 0x90: /* nop / xchg r8,rax */ case 0x90: /* nop / xchg r8,rax */
if (c->dst.ptr == (unsigned long *)&c->regs[VCPU_REGS_RAX]) { if (c->dst.addr.reg == &c->regs[VCPU_REGS_RAX]) {
c->dst.type = OP_NONE; /* nop */ c->dst.type = OP_NONE; /* nop */
break; break;
} }
case 0x91 ... 0x97: /* xchg reg,rax */ case 0x91 ... 0x97: /* xchg reg,rax */
c->src.type = OP_REG; c->src.type = OP_REG;
c->src.bytes = c->op_bytes; c->src.bytes = c->op_bytes;
c->src.ptr = (unsigned long *) &c->regs[VCPU_REGS_RAX]; c->src.addr.reg = &c->regs[VCPU_REGS_RAX];
c->src.val = *(c->src.ptr); c->src.val = *(c->src.addr.reg);
goto xchg; goto xchg;
case 0x9c: /* pushf */ case 0x9c: /* pushf */
c->src.val = (unsigned long) ctxt->eflags; c->src.val = (unsigned long) ctxt->eflags;
@ -2952,7 +2949,7 @@ special_insn:
break; break;
case 0x9d: /* popf */ case 0x9d: /* popf */
c->dst.type = OP_REG; c->dst.type = OP_REG;
c->dst.ptr = (unsigned long *) &ctxt->eflags; c->dst.addr.reg = &ctxt->eflags;
c->dst.bytes = c->op_bytes; c->dst.bytes = c->op_bytes;
rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes); rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
@ -2963,7 +2960,7 @@ special_insn:
goto mov; goto mov;
case 0xa6 ... 0xa7: /* cmps */ case 0xa6 ... 0xa7: /* cmps */
c->dst.type = OP_NONE; /* Disable writeback. */ c->dst.type = OP_NONE; /* Disable writeback. */
DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.ptr, c->dst.ptr); DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.addr.mem, c->dst.addr.mem);
goto cmp; goto cmp;
case 0xa8 ... 0xa9: /* test ax, imm */ case 0xa8 ... 0xa9: /* test ax, imm */
goto test; goto test;
@ -2982,7 +2979,7 @@ special_insn:
break; break;
case 0xc3: /* ret */ case 0xc3: /* ret */
c->dst.type = OP_REG; c->dst.type = OP_REG;
c->dst.ptr = &c->eip; c->dst.addr.reg = &c->eip;
c->dst.bytes = c->op_bytes; c->dst.bytes = c->op_bytes;
goto pop_instruction; goto pop_instruction;
case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
@ -3184,7 +3181,7 @@ twobyte_insn:
c->dst.type = OP_NONE; c->dst.type = OP_NONE;
break; break;
case 2: /* lgdt */ case 2: /* lgdt */
rc = read_descriptor(ctxt, ops, c->src.ptr, rc = read_descriptor(ctxt, ops, c->src.addr.mem,
&size, &address, c->op_bytes); &size, &address, c->op_bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
goto done; goto done;
@ -3204,7 +3201,7 @@ twobyte_insn:
goto cannot_emulate; goto cannot_emulate;
} }
} else { } else {
rc = read_descriptor(ctxt, ops, c->src.ptr, rc = read_descriptor(ctxt, ops, c->src.addr.mem,
&size, &address, &size, &address,
c->op_bytes); c->op_bytes);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)
@ -3399,7 +3396,7 @@ twobyte_insn:
} else { } else {
/* Failure: write the value we saw to EAX. */ /* Failure: write the value we saw to EAX. */
c->dst.type = OP_REG; c->dst.type = OP_REG;
c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX];
} }
break; break;
case 0xb3: case 0xb3: