|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 04/30] x86emul: add eGPR parameter to decode_gpr()
The respective structure is introduced empty here, for this to be a
purely mechanical change. Note however that NULL is passed in a few
cases, when eGPR-s can't come into play (e.g. for insns not valid in
64-bit mode, or for encodings [e.g. VEX] which cannot specify eGPR-s).
While doing this rename decode_gpr()'s last parameter, though: "modrm"
clearly has been misleading at best.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2179,7 +2179,8 @@ int hvm_set_efer(uint64_t value)
int hvm_mov_to_cr(unsigned int cr, unsigned int gpr)
{
struct vcpu *curr = current;
- unsigned long val = *decode_gpr(guest_cpu_user_regs(), gpr);
+ struct egpr egpr = {};
+ unsigned long val = *decode_gpr(guest_cpu_user_regs(), &egpr, gpr);
int rc;
TRACE(TRC_HVM_CR_WRITE64, cr, val, val >> 32);
@@ -2228,7 +2229,8 @@ int hvm_mov_to_cr(unsigned int cr, unsig
int hvm_mov_from_cr(unsigned int cr, unsigned int gpr)
{
struct vcpu *curr = current;
- unsigned long val = 0, *reg = decode_gpr(guest_cpu_user_regs(), gpr);
+ struct egpr egpr = {};
+ unsigned long val = 0, *reg = decode_gpr(guest_cpu_user_regs(), &egpr,
gpr);
switch ( cr )
{
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4718,12 +4718,13 @@ void asmlinkage vmx_vmexit_handler(struc
case EXIT_REASON_URDMSR: /* NB: User-MSR bitmap was checked by the CPU. */
{
uint64_t msr_content = 0;
+ struct egpr egpr = {};
switch ( hvm_msr_read_intercept(vmread(EXIT_QUALIFICATION),
&msr_content) )
{
case X86EMUL_OKAY:
- *decode_gpr(regs, msr_imm_gpr()) = msr_content;
+ *decode_gpr(regs, &egpr, msr_imm_gpr()) = msr_content;
update_guest_eip(); /* Safe: URDMSR / RDMSR <imm> */
break;
@@ -4743,9 +4744,13 @@ void asmlinkage vmx_vmexit_handler(struc
}
fallthrough;
case EXIT_REASON_UWRMSR: /* NB: User-MSR bitmap was checked by the CPU. */
+ {
+ struct egpr egpr = {};
+
exit_qualification = vmread(EXIT_QUALIFICATION);
switch ( hvm_msr_write_intercept(exit_qualification,
- *decode_gpr(regs, msr_imm_gpr()),
+ *decode_gpr(regs, &egpr,
+ msr_imm_gpr()),
true) )
{
case X86EMUL_OKAY:
@@ -4757,6 +4762,7 @@ void asmlinkage vmx_vmexit_handler(struc
break;
}
break;
+ }
case EXIT_REASON_VMXOFF:
case EXIT_REASON_VMXON:
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -360,10 +360,10 @@ enum vmx_insn_errno set_vvmcs_real_safe(
return virtual_vmcs_vmwrite_safe(v, encoding, val);
}
-static unsigned long reg_read(struct cpu_user_regs *regs,
+static unsigned long reg_read(struct cpu_user_regs *regs, struct egpr *egpr,
unsigned int index)
{
- unsigned long val = *decode_gpr(regs, index);
+ unsigned long val = *decode_gpr(regs, egpr, index);
/*
* Outside of 64-bit mode, zero-extend the result from 32 bits, like
@@ -377,7 +377,7 @@ static unsigned long reg_read(struct cpu
return val;
}
-static void reg_write(struct cpu_user_regs *regs,
+static void reg_write(struct cpu_user_regs *regs, struct egpr *egpr,
unsigned int index,
unsigned long value)
{
@@ -389,7 +389,7 @@ static void reg_write(struct cpu_user_re
*/
if ( !hvm_long_mode_active(current) )
value = (uint32_t)value;
- *decode_gpr(regs, index) = value;
+ *decode_gpr(regs, egpr, index) = value;
}
static inline u32 __n2_pin_exec_control(struct vcpu *v)
@@ -413,6 +413,7 @@ static inline u32 __n2_secondary_exec_co
}
static int decode_vmx_inst(struct cpu_user_regs *regs,
+ struct egpr *egpr,
struct vmx_inst_decoded *decode,
unsigned long *poperandS, unsigned int size)
{
@@ -429,7 +430,7 @@ static int decode_vmx_inst(struct cpu_us
decode->type = VMX_INST_MEMREG_TYPE_REG;
decode->reg1 = info.fields.reg1;
if ( poperandS != NULL )
- *poperandS = reg_read(regs, decode->reg1);
+ *poperandS = reg_read(regs, egpr, decode->reg1);
}
else
{
@@ -443,10 +444,10 @@ static int decode_vmx_inst(struct cpu_us
seg_base = seg.base;
base = info.fields.base_reg_invalid ? 0 :
- reg_read(regs, info.fields.base_reg);
+ reg_read(regs, egpr, info.fields.base_reg);
index = info.fields.index_reg_invalid ? 0 :
- reg_read(regs, info.fields.index_reg);
+ reg_read(regs, egpr, info.fields.index_reg);
scale = 1 << info.fields.scaling;
@@ -1558,7 +1559,7 @@ void asmlinkage nvmx_switch_guest(void)
* VMX instructions handling
*/
-static int nvmx_handle_vmxon(struct cpu_user_regs *regs)
+static int nvmx_handle_vmxon(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v=current;
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
@@ -1568,7 +1569,7 @@ static int nvmx_handle_vmxon(struct cpu_
uint32_t nvmcs_revid;
int rc;
- rc = decode_vmx_inst(regs, &decode, &gpa, sizeof(gpa));
+ rc = decode_vmx_inst(regs, egpr, &decode, &gpa, sizeof(gpa));
if ( rc != X86EMUL_OKAY )
return rc;
@@ -1787,7 +1788,7 @@ static int nvmx_handle_vmlaunch(struct c
return rc;
}
-static int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
+static int nvmx_handle_vmptrld(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1795,7 +1796,7 @@ static int nvmx_handle_vmptrld(struct cp
unsigned long gpa = 0;
int rc;
- rc = decode_vmx_inst(regs, &decode, &gpa, sizeof(gpa));
+ rc = decode_vmx_inst(regs, egpr, &decode, &gpa, sizeof(gpa));
if ( rc != X86EMUL_OKAY )
return rc;
@@ -1863,7 +1864,7 @@ out:
return X86EMUL_OKAY;
}
-static int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
+static int nvmx_handle_vmptrst(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1872,7 +1873,7 @@ static int nvmx_handle_vmptrst(struct cp
unsigned long gpa = 0;
int rc;
- rc = decode_vmx_inst(regs, &decode, &gpa, sizeof(gpa));
+ rc = decode_vmx_inst(regs, egpr, &decode, &gpa, sizeof(gpa));
if ( rc != X86EMUL_OKAY )
return rc;
@@ -1888,7 +1889,7 @@ static int nvmx_handle_vmptrst(struct cp
return X86EMUL_OKAY;
}
-static int nvmx_handle_vmclear(struct cpu_user_regs *regs)
+static int nvmx_handle_vmclear(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1898,7 +1899,7 @@ static int nvmx_handle_vmclear(struct cp
void *vvmcs;
int rc;
- rc = decode_vmx_inst(regs, &decode, &gpa, sizeof(gpa));
+ rc = decode_vmx_inst(regs, egpr, &decode, &gpa, sizeof(gpa));
if ( rc != X86EMUL_OKAY )
return rc;
@@ -1952,7 +1953,7 @@ out:
return X86EMUL_OKAY;
}
-static int nvmx_handle_vmread(struct cpu_user_regs *regs)
+static int nvmx_handle_vmread(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -1960,7 +1961,7 @@ static int nvmx_handle_vmread(struct cpu
u64 value = 0;
int rc;
- rc = decode_vmx_inst(regs, &decode, NULL, 0);
+ rc = decode_vmx_inst(regs, egpr, &decode, NULL, 0);
if ( rc != X86EMUL_OKAY )
return rc;
@@ -1970,7 +1971,7 @@ static int nvmx_handle_vmread(struct cpu
return X86EMUL_OKAY;
}
- rc = get_vvmcs_safe(v, reg_read(regs, decode.reg2), &value);
+ rc = get_vvmcs_safe(v, reg_read(regs, egpr, decode.reg2), &value);
if ( rc != VMX_INSN_SUCCEED )
{
vmfail(regs, rc);
@@ -1986,7 +1987,7 @@ static int nvmx_handle_vmread(struct cpu
return X86EMUL_EXCEPTION;
break;
case VMX_INST_MEMREG_TYPE_REG:
- reg_write(regs, decode.reg1, value);
+ reg_write(regs, egpr, decode.reg1, value);
break;
}
@@ -1994,7 +1995,7 @@ static int nvmx_handle_vmread(struct cpu
return X86EMUL_OKAY;
}
-static int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
+static int nvmx_handle_vmwrite(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vcpu *v = current;
struct vmx_inst_decoded decode;
@@ -2003,7 +2004,7 @@ static int nvmx_handle_vmwrite(struct cp
enum vmx_insn_errno err;
int rc;
- rc = decode_vmx_inst(regs, &decode, &operand, 0);
+ rc = decode_vmx_inst(regs, egpr, &decode, &operand, 0);
if ( rc != X86EMUL_OKAY )
return rc;
@@ -2013,7 +2014,7 @@ static int nvmx_handle_vmwrite(struct cp
return X86EMUL_OKAY;
}
- vmcs_encoding = reg_read(regs, decode.reg2);
+ vmcs_encoding = reg_read(regs, egpr, decode.reg2);
err = set_vvmcs_safe(v, vmcs_encoding, operand);
if ( err != VMX_INSN_SUCCEED )
{
@@ -2039,16 +2040,16 @@ static int nvmx_handle_vmwrite(struct cp
return X86EMUL_OKAY;
}
-static int nvmx_handle_invept(struct cpu_user_regs *regs)
+static int nvmx_handle_invept(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vmx_inst_decoded decode;
unsigned long eptp;
int ret;
- if ( (ret = decode_vmx_inst(regs, &decode, &eptp, 16)) != X86EMUL_OKAY )
+ if ( (ret = decode_vmx_inst(regs, egpr, &decode, &eptp, 16)) !=
X86EMUL_OKAY )
return ret;
- switch ( reg_read(regs, decode.reg2) )
+ switch ( reg_read(regs, egpr, decode.reg2) )
{
case INVEPT_SINGLE_CONTEXT:
{
@@ -2067,16 +2068,16 @@ static int nvmx_handle_invept(struct cpu
return X86EMUL_OKAY;
}
-static int nvmx_handle_invvpid(struct cpu_user_regs *regs)
+static int nvmx_handle_invvpid(struct cpu_user_regs *regs, struct egpr *egpr)
{
struct vmx_inst_decoded decode;
unsigned long vpid;
int ret;
- if ( (ret = decode_vmx_inst(regs, &decode, &vpid, 16)) != X86EMUL_OKAY )
+ if ( (ret = decode_vmx_inst(regs, egpr, &decode, &vpid, 16)) !=
X86EMUL_OKAY )
return ret;
- switch ( reg_read(regs, decode.reg2) )
+ switch ( reg_read(regs, egpr, decode.reg2) )
{
/* Just invalidate all tlb entries for all types! */
case INVVPID_INDIVIDUAL_ADDR:
@@ -2094,9 +2095,11 @@ static int nvmx_handle_invvpid(struct cp
return X86EMUL_OKAY;
}
-int nvmx_handle_vmx_insn(struct cpu_user_regs *regs, unsigned int exit_reason)
+int nvmx_handle_vmx_insn(struct cpu_user_regs *regs,
+ unsigned int exit_reason)
{
struct vcpu *curr = current;
+ struct egpr egpr = {};
int ret;
if ( !(curr->arch.hvm.guest_cr[4] & X86_CR4_VMXE) ||
@@ -2130,27 +2133,27 @@ int nvmx_handle_vmx_insn(struct cpu_user
break;
case EXIT_REASON_VMXON:
- ret = nvmx_handle_vmxon(regs);
+ ret = nvmx_handle_vmxon(regs, &egpr);
break;
case EXIT_REASON_VMCLEAR:
- ret = nvmx_handle_vmclear(regs);
+ ret = nvmx_handle_vmclear(regs, &egpr);
break;
case EXIT_REASON_VMPTRLD:
- ret = nvmx_handle_vmptrld(regs);
+ ret = nvmx_handle_vmptrld(regs, &egpr);
break;
case EXIT_REASON_VMPTRST:
- ret = nvmx_handle_vmptrst(regs);
+ ret = nvmx_handle_vmptrst(regs, &egpr);
break;
case EXIT_REASON_VMREAD:
- ret = nvmx_handle_vmread(regs);
+ ret = nvmx_handle_vmread(regs, &egpr);
break;
case EXIT_REASON_VMWRITE:
- ret = nvmx_handle_vmwrite(regs);
+ ret = nvmx_handle_vmwrite(regs, &egpr);
break;
case EXIT_REASON_VMLAUNCH:
@@ -2162,11 +2165,11 @@ int nvmx_handle_vmx_insn(struct cpu_user
break;
case EXIT_REASON_INVEPT:
- ret = nvmx_handle_invept(regs);
+ ret = nvmx_handle_invept(regs, &egpr);
break;
case EXIT_REASON_INVVPID:
- ret = nvmx_handle_invvpid(regs);
+ ret = nvmx_handle_invvpid(regs, &egpr);
break;
default:
@@ -2699,7 +2702,9 @@ int nvmx_n2_vmexit_handler(struct cpu_us
{
case VMX_CR_ACCESS_TYPE_MOV_TO_CR:
{
- val = reg_read(regs, qual.gpr);
+ struct egpr egpr = {};
+
+ val = reg_read(regs, &egpr, qual.gpr);
if ( qual.cr == 0 )
{
--- a/xen/arch/x86/x86_emulate/0fae.c
+++ b/xen/arch/x86/x86_emulate/0fae.c
@@ -176,7 +176,7 @@ int x86emul_0fae(struct x86_emulate_stat
fail_if(!ops->read_segment);
if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != X86EMUL_OKAY )
goto done;
- dst->reg = decode_gpr(regs, s->modrm_rm);
+ dst->reg = decode_gpr(regs, &s->egpr, s->modrm_rm);
if ( !(s->modrm_reg & 2) )
{
/* rd{f,g}sbase */
--- a/xen/arch/x86/x86_emulate/decode.c
+++ b/xen/arch/x86/x86_emulate/decode.c
@@ -1827,7 +1827,7 @@ int x86emul_decode(struct x86_emulate_st
!s->evex.RX) << 4;
else if ( s->sib_index != 4 )
{
- s->ea.mem.off = *decode_gpr(ctxt->regs, s->sib_index);
+ s->ea.mem.off = *decode_gpr(ctxt->regs, &s->egpr,
s->sib_index);
s->ea.mem.off <<= s->sib_scale;
}
if ( (s->modrm_mod == 0) && ((sib_base & 7) == 5) )
@@ -1847,13 +1847,13 @@ int x86emul_decode(struct x86_emulate_st
s->ea.mem.off += ctxt->regs->r(bp);
}
else
- s->ea.mem.off += *decode_gpr(ctxt->regs, sib_base);
+ s->ea.mem.off += *decode_gpr(ctxt->regs, &s->egpr,
sib_base);
}
else
{
generate_exception_if(d & vSIB, X86_EXC_UD);
s->modrm_rm |= (s->rex_prefix & 1) << 3;
- s->ea.mem.off = *decode_gpr(ctxt->regs, s->modrm_rm);
+ s->ea.mem.off = *decode_gpr(ctxt->regs, &s->egpr, s->modrm_rm);
if ( (s->modrm_rm == 5) && (s->modrm_mod != 0) )
s->ea.mem.seg = x86_seg_ss;
}
--- a/xen/arch/x86/x86_emulate/private.h
+++ b/xen/arch/x86/x86_emulate/private.h
@@ -336,6 +336,8 @@ struct x86_emulate_state {
unsigned long ip;
+ struct egpr egpr;
+
struct stub_exn *stub_exn;
#ifndef NDEBUG
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1168,7 +1168,8 @@ const uint8_t cpu_user_regs_gpr_offsets[
};
static void *_decode_gpr(
- struct cpu_user_regs *regs, unsigned int modrm_reg, bool legacy)
+ struct cpu_user_regs *regs, struct egpr *egpr, unsigned int modrm_reg,
+ bool legacy)
{
static const uint8_t byte_reg_offsets[] = {
offsetof(struct cpu_user_regs, al),
@@ -1182,7 +1183,7 @@ static void *_decode_gpr(
};
if ( !legacy )
- return decode_gpr(regs, modrm_reg);
+ return decode_gpr(regs, egpr, modrm_reg);
/* Check that the array is a power of two. */
BUILD_BUG_ON(ARRAY_SIZE(byte_reg_offsets) &
@@ -1200,7 +1201,7 @@ static unsigned long *decode_vex_gpr(
unsigned int vex_reg, struct cpu_user_regs *regs,
const struct x86_emulate_ctxt *ctxt)
{
- return decode_gpr(regs, ~vex_reg & (mode_64bit() ? 0xf : 7));
+ return decode_gpr(regs, NULL, ~vex_reg & (mode_64bit() ? 0xf : 7));
}
#define visa_check(subfeat) \
@@ -1370,7 +1371,8 @@ x86_emulate(
generate_exception_if(state->not_64bit && mode_64bit(), X86_EXC_UD);
if ( ea.type == OP_REG )
- ea.reg = _decode_gpr(&_regs, modrm_rm, (d & ByteOp) && !rex_prefix &&
!vex.opcx);
+ ea.reg = _decode_gpr(&_regs, &state->egpr, modrm_rm,
+ (d & ByteOp) && !rex_prefix && !vex.opcx);
memset(mmvalp, 0xaa /* arbitrary */, sizeof(*mmvalp));
@@ -1384,13 +1386,14 @@ x86_emulate(
src.type = OP_REG;
if ( d & ByteOp )
{
- src.reg = _decode_gpr(&_regs, modrm_reg, !rex_prefix && !vex.opcx);
+ src.reg = _decode_gpr(&_regs, &state->egpr, modrm_reg,
+ !rex_prefix && !vex.opcx);
src.val = *(uint8_t *)src.reg;
src.bytes = 1;
}
else
{
- src.reg = decode_gpr(&_regs, modrm_reg);
+ src.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
switch ( (src.bytes = op_bytes) )
{
case 2: src.val = *(uint16_t *)src.reg; break;
@@ -1496,13 +1499,14 @@ x86_emulate(
dst.type = OP_REG;
if ( d & ByteOp )
{
- dst.reg = _decode_gpr(&_regs, modrm_reg, !rex_prefix && !vex.opcx);
+ dst.reg = _decode_gpr(&_regs, &state->egpr, modrm_reg,
+ !rex_prefix && !vex.opcx);
dst.val = *(uint8_t *)dst.reg;
dst.bytes = 1;
}
else
{
- dst.reg = decode_gpr(&_regs, modrm_reg);
+ dst.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
switch ( (dst.bytes = op_bytes) )
{
case 2: dst.val = *(uint16_t *)dst.reg; break;
@@ -1739,7 +1743,7 @@ x86_emulate(
case 0x40 ... 0x4f: /* inc/dec reg */
dst.type = OP_REG;
- dst.reg = decode_gpr(&_regs, b & 7);
+ dst.reg = decode_gpr(&_regs, NULL, b & 7);
dst.bytes = op_bytes;
dst.val = *dst.reg;
if ( b & 8 )
@@ -1749,12 +1753,14 @@ x86_emulate(
break;
case 0x50 ... 0x57: /* push reg */
- src.val = *decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3));
+ src.val = *decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3));
goto push;
case 0x58 ... 0x5f: /* pop reg */
dst.type = OP_REG;
- dst.reg = decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3));
+ dst.reg = decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3));
dst.bytes = op_bytes;
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
@@ -1768,7 +1774,7 @@ x86_emulate(
ea.val = _regs.esp;
for ( i = 0; i < 8; i++ )
{
- void *reg = decode_gpr(&_regs, i);
+ void *reg = decode_gpr(&_regs, NULL, i);
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
reg != &_regs.esp ? reg : &ea.val,
@@ -1780,7 +1786,7 @@ x86_emulate(
case 0x61: /* popa */
for ( i = 0; i < 8; i++ )
{
- void *reg = decode_gpr(&_regs, 7 - i);
+ void *reg = decode_gpr(&_regs, NULL, 7 - i);
if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
&dst.val, op_bytes, ctxt, ops)) != 0 )
@@ -2079,7 +2085,8 @@ x86_emulate(
case 0x91 ... 0x97: /* xchg reg,%%rax */
dst.type = OP_REG;
dst.bytes = op_bytes;
- dst.reg = decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3));
+ dst.reg = decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3));
dst.val = *dst.reg;
goto xchg;
@@ -2325,13 +2332,15 @@ x86_emulate(
}
case 0xb0 ... 0xb7: /* mov imm8,r8 */
- dst.reg = _decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3),
+ dst.reg = _decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3),
!rex_prefix);
dst.val = src.val;
break;
case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */
- dst.reg = decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3));
+ dst.reg = decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3));
dst.val = src.val;
break;
@@ -3787,7 +3796,7 @@ x86_emulate(
}
place_ret(&opc[2]);
- ea.reg = decode_gpr(&_regs, modrm_reg);
+ ea.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
invoke_stub("", "", "=a" (*ea.reg) : "c" (mmvalp), "m" (*mmvalp));
put_stub(stub);
@@ -5079,7 +5088,7 @@ x86_emulate(
place_ret(&opc[2]);
copy_VEX(opc, vex);
- ea.reg = decode_gpr(&_regs, modrm_rm);
+ ea.reg = decode_gpr(&_regs, NULL, modrm_rm);
invoke_stub("", "", "=m" (dummy) : "a" (*ea.reg));
put_stub(stub);
@@ -5094,7 +5103,7 @@ x86_emulate(
generate_exception_if(vex.l || vex.reg != 0xf || ea.type != OP_REG,
X86_EXC_UD);
dst = ea;
- dst.reg = decode_gpr(&_regs, modrm_reg);
+ dst.reg = decode_gpr(&_regs, NULL, modrm_reg);
if ( vex.pfx == vex_f2 )
{
@@ -5219,7 +5228,7 @@ x86_emulate(
else
{
shift = src.val;
- src.reg = decode_gpr(&_regs, modrm_reg);
+ src.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
src.val = truncate_word(*src.reg, dst.bytes);
}
@@ -5321,7 +5330,7 @@ x86_emulate(
case X86EMUL_OPC(0x0f, 0xb6): /* movzx rm8,r{16,32,64} */
/* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
- dst.reg = decode_gpr(&_regs, modrm_reg);
+ dst.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
dst.bytes = op_bytes;
dst.val = (uint8_t)src.val;
break;
@@ -5380,7 +5389,7 @@ x86_emulate(
case X86EMUL_OPC(0x0f, 0xbe): /* movsx rm8,r{16,32,64} */
/* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
- dst.reg = decode_gpr(&_regs, modrm_reg);
+ dst.reg = decode_gpr(&_regs, &state->egpr, modrm_reg);
dst.bytes = op_bytes;
dst.val = (int8_t)src.val;
break;
@@ -5524,7 +5533,8 @@ x86_emulate(
case X86EMUL_OPC(0x0f, 0xc8) ... X86EMUL_OPC(0x0f, 0xcf): /* bswap */
dst.type = OP_REG;
- dst.reg = decode_gpr(&_regs, (b & 7) | ((rex_prefix & 1) << 3));
+ dst.reg = decode_gpr(&_regs, &state->egpr,
+ (b & 7) | ((rex_prefix & 1) << 3));
switch ( dst.bytes = op_bytes )
{
default: /* case 2: */
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -634,12 +634,16 @@ int x86_emulate_wrapper(
/* Map GPRs by ModRM encoding to their offset within struct cpu_user_regs. */
extern const uint8_t cpu_user_regs_gpr_offsets[X86_NR_GPRS];
+struct egpr {
+};
+
/*
* Given the 'reg' portion of a ModRM byte, and a register block, return a
* pointer into the block that addresses the relevant register.
*/
static inline unsigned long *decode_gpr(struct cpu_user_regs *regs,
- unsigned int modrm)
+ struct egpr *egpr,
+ unsigned int reg)
{
/* Check that the array is a power of two. */
BUILD_BUG_ON(ARRAY_SIZE(cpu_user_regs_gpr_offsets) &
@@ -651,9 +655,9 @@ static inline unsigned long *decode_gpr(
* hence truncation is what we want (bits not ignored will get checked
* elsewhere).
*/
- modrm &= ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1;
+ reg &= ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1;
- return (void *)regs + cpu_user_regs_gpr_offsets[modrm];
+ return (void *)regs + cpu_user_regs_gpr_offsets[reg];
}
/* Unhandleable read, write or instruction fetch */
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |