#define BUG() abort()
#define ASSERT assert
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
+#define BUILD_BUG_ON_ZERO(cond) \
+ sizeof(struct { _Static_assert(!(cond), "!(" #cond ")"); })
+#else
+#define BUILD_BUG_ON_ZERO(cond) sizeof(struct { int:-!!(cond); })
+#define BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
+#endif
+
#define cpu_has_amd_erratum(nr) 0
#define mark_regs_dirty(r) ((void)(r))
enum x86_segment s;
struct segment_register reg[x86_seg_tr + 1];
+ BUILD_BUG_ON(x86_seg_tr != x86_seg_gs + 1);
+
/* Entering or leaving real mode: adjust the segment registers.
* Need to read them all either way, as realmode reads can update
* the saved values we'll use when returning to prot mode. */
- for ( s = x86_seg_cs ; s <= x86_seg_tr ; s++ )
+ for ( s = 0; s < ARRAY_SIZE(reg); s++ )
vmx_get_segment_register(v, s, ®[s]);
v->arch.hvm_vmx.vmx_realmode = realmode;
if ( realmode )
{
- for ( s = x86_seg_cs ; s <= x86_seg_tr ; s++ )
+ for ( s = 0; s < ARRAY_SIZE(reg); s++ )
vmx_set_segment_register(v, s, ®[s]);
}
else
{
- for ( s = x86_seg_cs ; s <= x86_seg_tr ; s++ )
+ for ( s = 0; s < ARRAY_SIZE(reg); s++ )
if ( !(v->arch.hvm_vmx.vm86_segment_mask & (1<<s)) )
vmx_set_segment_register(
v, s, &v->arch.hvm_vmx.vm86_saved_seg[s]);
return p;
}
-#define decode_segment_failed x86_seg_tr
-static enum x86_segment
-decode_segment(uint8_t modrm_reg)
-{
- switch ( modrm_reg )
- {
- case 0: return x86_seg_es;
- case 1: return x86_seg_cs;
- case 2: return x86_seg_ss;
- case 3: return x86_seg_ds;
- case 4: return x86_seg_fs;
- case 5: return x86_seg_gs;
- default: break;
- }
- return decode_segment_failed;
-}
-
/* Inject a software interrupt/exception, emulating if needed. */
static int inject_swint(enum x86_swint_type type,
uint8_t vector, uint8_t insn_len,
case 0x8c: /* mov Sreg,r/m */ {
struct segment_register reg;
- enum x86_segment seg = decode_segment(modrm_reg);
- generate_exception_if(seg == decode_segment_failed, EXC_UD, -1);
+ enum x86_segment seg = modrm_reg & 7; /* REX.R is ignored. */
+ generate_exception_if(!is_x86_user_segment(seg), EXC_UD, -1);
fail_if(ops->read_segment == NULL);
if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 )
goto done;
}
case 0x8e: /* mov r/m,Sreg */ {
- enum x86_segment seg = decode_segment(modrm_reg);
- generate_exception_if(seg == decode_segment_failed, EXC_UD, -1);
- generate_exception_if(seg == x86_seg_cs, EXC_UD, -1);
+ enum x86_segment seg = modrm_reg & 7; /* REX.R is ignored. */
+ generate_exception_if(!is_x86_user_segment(seg) ||
+ seg == x86_seg_cs, EXC_UD, -1);
if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 )
goto done;
if ( seg == x86_seg_ss )
put_stub(stub);
return X86EMUL_UNHANDLEABLE;
}
+
+static inline void build_assertions(void)
+{
+ /* Check the values against SReg3 encoding in opcode/ModRM bytes. */
+ BUILD_BUG_ON(x86_seg_es != 0);
+ BUILD_BUG_ON(x86_seg_cs != 1);
+ BUILD_BUG_ON(x86_seg_ss != 2);
+ BUILD_BUG_ON(x86_seg_ds != 3);
+ BUILD_BUG_ON(x86_seg_fs != 4);
+ BUILD_BUG_ON(x86_seg_gs != 5);
+}