[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86emul: support {,V}{LD,ST}MXCSR
commit 9a4496a35b206729f9a8218104bc7e76df74ff05 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Mar 7 17:05:24 2017 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Mar 7 17:05:24 2017 +0100 x86emul: support {,V}{LD,ST}MXCSR Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- .../x86-insn-emulator-fuzzer.c | 2 +- tools/tests/x86_emulator/test_x86_emulator.c | 83 +++++++++++++++++++++- tools/tests/x86_emulator/x86_emulate.c | 21 +++++- tools/tests/x86_emulator/x86_emulate.h | 10 ++- xen/arch/x86/x86_emulate/x86_emulate.c | 50 ++++++++++++- xen/arch/x86/xstate.c | 2 +- xen/include/asm-x86/xstate.h | 2 + 7 files changed, 164 insertions(+), 6 deletions(-) diff --git a/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c index 4a2bdbe..4b1e324 100644 --- a/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c +++ b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c @@ -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); diff --git a/tools/tests/x86_emulator/test_x86_emulator.c b/tools/tests/x86_emulator/test_x86_emulator.c index ffbf58a..90864e7 100644 --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -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 diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c index bbfd03f..f98f7f7 100644 --- a/tools/tests/x86_emulator/x86_emulate.c +++ b/tools/tests/x86_emulator/x86_emulate.c @@ -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 diff --git a/tools/tests/x86_emulator/x86_emulate.h b/tools/tests/x86_emulator/x86_emulate.h index b5e8ca5..9ea964c 100644 --- a/tools/tests/x86_emulator/x86_emulate.h +++ b/tools/tests/x86_emulator/x86_emulate.h @@ -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); \ diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 9a7f3c3..7f44547 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -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); diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index b8ae656..c2a722c 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -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); diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h index a3d37b8..b31ad75 100644 --- a/xen/include/asm-x86/xstate.h +++ b/xen/include/asm-x86/xstate.h @@ -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 */ -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |