int hvm_mov_to_cr(unsigned int cr, unsigned int gpr)
{
struct vcpu *curr = current;
- unsigned long val, *reg;
+ unsigned long val = *decode_gpr(guest_cpu_user_regs(), gpr);
int rc;
- if ( (reg = decode_register(gpr, guest_cpu_user_regs(), 0)) == NULL )
- {
- gdprintk(XENLOG_ERR, "invalid gpr: %u\n", gpr);
- goto exit_and_crash;
- }
-
- val = *reg;
HVMTRACE_LONG_2D(CR_WRITE, cr, TRC_PAR_LONG(val));
HVM_DBG_LOG(DBG_LEVEL_1, "CR%u, value = %lx", cr, val);
int hvm_mov_from_cr(unsigned int cr, unsigned int gpr)
{
struct vcpu *curr = current;
- unsigned long val = 0, *reg;
-
- if ( (reg = decode_register(gpr, guest_cpu_user_regs(), 0)) == NULL )
- {
- gdprintk(XENLOG_ERR, "invalid gpr: %u\n", gpr);
- goto exit_and_crash;
- }
+ unsigned long val = 0, *reg = decode_gpr(guest_cpu_user_regs(), gpr);
switch ( cr )
{
static unsigned long reg_read(struct cpu_user_regs *regs,
unsigned int index)
{
- unsigned long *pval = decode_register(index, regs, 0);
-
- return *pval;
+ return *decode_gpr(regs, index);
}
static void reg_write(struct cpu_user_regs *regs,
unsigned int index,
unsigned long value)
{
- unsigned long *pval = decode_register(index, regs, 0);
-
- *pval = value;
+ *decode_gpr(regs, index) = value;
}
static inline u32 __n2_pin_exec_control(struct vcpu *v)
case VMX_CONTROL_REG_ACCESS_TYPE_MOV_TO_CR:
{
unsigned long gp = VMX_CONTROL_REG_ACCESS_GPR(exit_qualification);
- unsigned long *reg;
+ val = *decode_gpr(guest_cpu_user_regs(), gp);
- if ( (reg = decode_register(gp, guest_cpu_user_regs(), 0)) == NULL )
- {
- gdprintk(XENLOG_ERR, "invalid gpr: %lx\n", gp);
- break;
- }
- val = *reg;
if ( cr == 0 )
{
u64 cr0_gh_mask = get_vvmcs(v, CR0_GUEST_HOST_MASK);
}
/* Map GPRs by ModRM encoding to their offset within struct cpu_user_regs. */
-static const uint8_t cpu_user_regs_gpr_offsets[] = {
+const uint8_t cpu_user_regs_gpr_offsets[] = {
offsetof(struct cpu_user_regs, r(ax)),
offsetof(struct cpu_user_regs, r(cx)),
offsetof(struct cpu_user_regs, r(dx)),
};
if ( !highbyte_regs )
- {
- /* Check that the array is a power of two. */
- BUILD_BUG_ON(ARRAY_SIZE(cpu_user_regs_gpr_offsets) &
- (ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1));
-
- ASSERT(modrm_reg < ARRAY_SIZE(cpu_user_regs_gpr_offsets));
-
- /* For safety in release builds. Debug builds will hit the ASSERT() */
- modrm_reg &= ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1;
-
- return (void *)regs + cpu_user_regs_gpr_offsets[modrm_reg];
- }
+ return decode_gpr(regs, modrm_reg);
/* Check that the array is a power of two. */
BUILD_BUG_ON(ARRAY_SIZE(byte_reg_offsets) &
#define MAX_INST_LEN 15
+#if defined(__i386__)
+# define X86_NR_GPRS 8
+#elif defined(__x86_64__)
+# define X86_NR_GPRS 16
+#else
+# error Unknown compilation width
+#endif
+
struct x86_emulate_ctxt;
/*
#define x86_emulate x86_emulate_wrapper
#endif
+/* 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];
+
/*
* Given the 'reg' portion of a ModRM byte, and a register block, return a
* pointer into the block that addresses the relevant register.
- * @highbyte_regs specifies whether to decode AH,CH,DH,BH.
*/
-void *
-decode_register(
- uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs);
+static inline unsigned long *decode_gpr(struct cpu_user_regs *regs,
+ unsigned int modrm)
+{
+ /* Check that the array is a power of two. */
+ BUILD_BUG_ON(ARRAY_SIZE(cpu_user_regs_gpr_offsets) &
+ (ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1));
+
+ ASSERT(modrm < ARRAY_SIZE(cpu_user_regs_gpr_offsets));
+
+ /* For safety in release builds. Debug builds will hit the ASSERT() */
+ modrm &= ARRAY_SIZE(cpu_user_regs_gpr_offsets) - 1;
+
+ return (void *)regs + cpu_user_regs_gpr_offsets[modrm];
+}
/* Unhandleable read, write or instruction fetch */
int