x86emul: support {,V}{LD,ST}MXCSR

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Jan Beulich committed 2017-03-07 17:05:24 +01:00
1 parent eb705cc741
commit 9a4496a35b
7 files changed
+164 -6

No files matched your search

@@ -657,7 +657,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
};
int rc;
stack_exec = emul_test_make_stack_executable();
stack_exec = emul_test_init();
if ( !stack_exec )
{
printf("Warning: Stack could not be made executable (%d).\n", errno);
+82 -1
View File
@@ -219,7 +219,7 @@ int main(int argc, char **argv)
}
instr = (char *)res + 0x100;
stack_exec = emul_test_make_stack_executable();
stack_exec = emul_test_init();
if ( !stack_exec )
printf("Warning: Stack could not be made executable (%d).\n", errno);
@@ -2398,6 +2398,87 @@ int main(int argc, char **argv)
else
printf("skipped\n");
printf("%-40s", "Testing stmxcsr (%edx)...");
if ( cpu_has_sse )
{
decl_insn(stmxcsr);
asm volatile ( put_insn(stmxcsr, "stmxcsr (%0)") :: "d" (NULL) );
res[0] = 0x12345678;
res[1] = 0x87654321;
asm ( "stmxcsr %0" : "=m" (res[2]) );
set_insn(stmxcsr);
regs.edx = (unsigned long)res;
rc = x86_emulate(&ctxt, &emulops);
if ( rc != X86EMUL_OKAY || !check_eip(stmxcsr) ||
res[0] != res[2] || res[1] != 0x87654321 )
goto fail;
printf("okay\n");
}
else
printf("skipped\n");
printf("%-40s", "Testing ldmxcsr 4(%ecx)...");
if ( cpu_has_sse )
{
decl_insn(ldmxcsr);
asm volatile ( put_insn(ldmxcsr, "ldmxcsr 4(%0)") :: "c" (NULL) );
set_insn(ldmxcsr);
res[1] = mxcsr_mask;
regs.ecx = (unsigned long)res;
rc = x86_emulate(&ctxt, &emulops);
asm ( "stmxcsr %0; ldmxcsr %1" : "=m" (res[0]) : "m" (res[2]) );
if ( rc != X86EMUL_OKAY || !check_eip(ldmxcsr) ||
res[0] != mxcsr_mask )
goto fail;
printf("okay\n");
}
else
printf("skipped\n");
printf("%-40s", "Testing vstmxcsr (%ecx)...");
if ( cpu_has_avx )
{
decl_insn(vstmxcsr);
asm volatile ( put_insn(vstmxcsr, "vstmxcsr (%0)") :: "c" (NULL) );
res[0] = 0x12345678;
res[1] = 0x87654321;
set_insn(vstmxcsr);
regs.ecx = (unsigned long)res;
rc = x86_emulate(&ctxt, &emulops);
if ( rc != X86EMUL_OKAY || !check_eip(vstmxcsr) ||
res[0] != res[2] || res[1] != 0x87654321 )
goto fail;
printf("okay\n");
}
else
printf("skipped\n");
printf("%-40s", "Testing vldmxcsr 4(%edx)...");
if ( cpu_has_avx )
{
decl_insn(vldmxcsr);
asm volatile ( put_insn(vldmxcsr, "vldmxcsr 4(%0)") :: "d" (NULL) );
set_insn(vldmxcsr);
res[1] = mxcsr_mask;
regs.edx = (unsigned long)res;
rc = x86_emulate(&ctxt, &emulops);
asm ( "stmxcsr %0; ldmxcsr %1" : "=m" (res[0]) : "m" (res[2]) );
if ( rc != X86EMUL_OKAY || !check_eip(vldmxcsr) ||
res[0] != mxcsr_mask )
goto fail;
printf("okay\n");
}
else
printf("skipped\n");
#undef decl_insn
#undef put_insn
#undef set_insn
+20 -1
View File
@@ -25,10 +25,29 @@
})
#define put_stub(stb) ((stb).addr = 0)
bool emul_test_make_stack_executable(void)
uint32_t mxcsr_mask = 0x0000ffbf;
bool emul_test_init(void)
{
unsigned long sp;
if ( cpu_has_fxsr )
{
static union __attribute__((__aligned__(16))) {
char x[464];
struct {
uint32_t other[6];
uint32_t mxcsr;
uint32_t mxcsr_mask;
/* ... */
};
} fxs;
asm ( "fxsave %0" : "=m" (fxs) );
if ( fxs.mxcsr_mask )
mxcsr_mask = fxs.mxcsr_mask;
}
/*
* Mark the entire stack executable so that the stub executions
* don't fault
+9 -1
View File
@@ -42,8 +42,10 @@
#define is_canonical_address(x) (((int64_t)(x) >> 47) == ((int64_t)(x) >> 63))
extern uint32_t mxcsr_mask;
#define MMAP_SZ 16384
bool emul_test_make_stack_executable(void);
bool emul_test_init(void);
#include "x86_emulate/x86_emulate.h"
@@ -68,6 +70,12 @@ static inline uint64_t xgetbv(uint32_t xcr)
(res.d & (1U << 23)) != 0; \
})
#define cpu_has_fxsr ({ \
struct cpuid_leaf res; \
emul_test_cpuid(1, 0, &res, NULL); \
(res.d & (1U << 24)) != 0; \
})
#define cpu_has_sse ({ \
struct cpuid_leaf res; \
emul_test_cpuid(1, 0, &res, NULL); \
+49 -1
View File
@@ -2178,7 +2178,6 @@ x86_decode_twobyte(
case 0x50 ... 0x77:
case 0x79 ... 0x7d:
case 0x7f:
case 0xae:
case 0xc2 ... 0xc3:
case 0xc5 ... 0xc6:
case 0xd0 ... 0xfe:
@@ -2209,6 +2208,24 @@ x86_decode_twobyte(
}
break;
case 0xae:
ctxt->opcode |= MASK_INSR(vex.pfx, X86EMUL_OPC_PFX_MASK);
/* fall through */
case X86EMUL_OPC_VEX(0, 0xae):
switch ( modrm_reg & 7 )
{
case 2: /* {,v}ldmxcsr */
state->desc = DstImplicit | SrcMem | ModRM | Mov;
op_bytes = 4;
break;
case 3: /* {,v}stmxcsr */
state->desc = DstMem | SrcImplicit | ModRM | Mov;
op_bytes = 4;
break;
}
break;
case 0xb8: /* jmpe / popcnt */
if ( rep_prefix() )
ctxt->opcode |= MASK_INSR(vex.pfx, X86EMUL_OPC_PFX_MASK);
@@ -6210,6 +6227,23 @@ x86_emulate(
case X86EMUL_OPC(0x0f, 0xae): case X86EMUL_OPC_66(0x0f, 0xae): /* Grp15 */
switch ( modrm_reg & 7 )
{
case 2: /* ldmxcsr */
generate_exception_if(vex.pfx, EXC_UD);
vcpu_must_have(sse);
ldmxcsr:
generate_exception_if(src.type != OP_MEM, EXC_UD);
generate_exception_if(src.val & ~mxcsr_mask, EXC_GP, 0);
asm volatile ( "ldmxcsr %0" :: "m" (src.val) );
break;
case 3: /* stmxcsr */
generate_exception_if(vex.pfx, EXC_UD);
vcpu_must_have(sse);
stmxcsr:
generate_exception_if(dst.type != OP_MEM, EXC_UD);
asm volatile ( "stmxcsr %0" : "=m" (dst.val) );
break;
case 5: /* lfence */
fail_if(modrm_mod != 3);
generate_exception_if(vex.pfx, EXC_UD);
@@ -6253,6 +6287,20 @@ x86_emulate(
}
break;
case X86EMUL_OPC_VEX(0x0f, 0xae): /* Grp15 */
switch ( modrm_reg & 7 )
{
case 2: /* vldmxcsr */
generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD);
vcpu_must_have(avx);
goto ldmxcsr;
case 3: /* vstmxcsr */
generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD);
vcpu_must_have(avx);
goto stmxcsr;
}
goto cannot_emulate;
case X86EMUL_OPC_F3(0x0f, 0xae): /* Grp15 */
fail_if(modrm_mod != 3);
generate_exception_if((modrm_reg & 4) || !mode_64bit(), EXC_UD);
+1 -1
View File
@@ -29,7 +29,7 @@ unsigned int *__read_mostly xstate_sizes;
u64 __read_mostly xstate_align;
static unsigned int __read_mostly xstate_features;
static uint32_t __read_mostly mxcsr_mask = 0x0000ffbf;
uint32_t __read_mostly mxcsr_mask = 0x0000ffbf;
/* Cached xcr0 for fast read */
static DEFINE_PER_CPU(uint64_t, xcr0);
+2
View File
@@ -15,6 +15,8 @@
#define FCW_RESET 0x0040
#define MXCSR_DEFAULT 0x1f80
extern uint32_t mxcsr_mask;
#define XSTATE_CPUID 0x0000000d
#define XCR_XFEATURE_ENABLED_MASK 0x00000000 /* index of XCR0 */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.