[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86emul: split off opcode 0fae handling
commit 3e957de632532dc287ae4cd356fd8d7882d4f233 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Mon Apr 3 12:42:44 2023 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Mon Apr 3 12:42:44 2023 +0200 x86emul: split off opcode 0fae handling There's a fair amount of sub-cases (with some yet to be implemented), so a separate function seems warranted. Code moved gets slightly adjusted in a few places, e.g. replacing EXC_* by X86_EXC_* (such that EXC_* don't need to move as well; we want these to be phased out anyway). Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- tools/fuzz/x86_instruction_emulator/Makefile | 2 +- tools/tests/x86_emulator/Makefile | 2 +- xen/arch/x86/x86_emulate/0fae.c | 222 ++++++++++++++++++++++++ xen/arch/x86/x86_emulate/Makefile | 1 + xen/arch/x86/x86_emulate/private.h | 77 +++++++++ xen/arch/x86/x86_emulate/x86_emulate.c | 249 ++------------------------- 6 files changed, 315 insertions(+), 238 deletions(-) diff --git a/tools/fuzz/x86_instruction_emulator/Makefile b/tools/fuzz/x86_instruction_emulator/Makefile index 08c96c1615..22eb035a64 100644 --- a/tools/fuzz/x86_instruction_emulator/Makefile +++ b/tools/fuzz/x86_instruction_emulator/Makefile @@ -32,7 +32,7 @@ GCOV_FLAGS := --coverage $(CC) -c $(CFLAGS) $(GCOV_FLAGS) $< -o $@ OBJS := fuzz-emul.o x86-emulate.o -OBJS += x86_emulate/0f01.o +OBJS += x86_emulate/0f01.o x86_emulate/0fae.o x86-emulate.h: x86_emulate/x86_emulate.h x86-emulate.o x86-emulate-cov.o: x86-emulate.h x86_emulate/x86_emulate.c x86_emulate/private.h diff --git a/tools/tests/x86_emulator/Makefile b/tools/tests/x86_emulator/Makefile index 72134564f8..5663a305eb 100644 --- a/tools/tests/x86_emulator/Makefile +++ b/tools/tests/x86_emulator/Makefile @@ -251,7 +251,7 @@ xop.h avx512f.h: simd-fma.c endif # 32-bit override OBJS := x86-emulate.o cpuid.o test_x86_emulator.o evex-disp8.o predicates.o wrappers.o -OBJS += x86_emulate/0f01.o +OBJS += x86_emulate/0f01.o x86_emulate/0fae.o $(TARGET): $(OBJS) $(HOSTCC) $(HOSTCFLAGS) -o $@ $^ diff --git a/xen/arch/x86/x86_emulate/0fae.c b/xen/arch/x86/x86_emulate/0fae.c new file mode 100644 index 0000000000..db5f419671 --- /dev/null +++ b/xen/arch/x86/x86_emulate/0fae.c @@ -0,0 +1,222 @@ +/****************************************************************************** + * 0fae.c - helper for x86_emulate.c + * + * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#include "private.h" + +#if defined(__XEN__) && \ + (!defined(X86EMUL_NO_FPU) || !defined(X86EMUL_NO_MMX) || \ + !defined(X86EMUL_NO_SIMD)) +# include <asm/xstate.h> +#endif + +int x86emul_0fae(struct x86_emulate_state *s, + struct cpu_user_regs *regs, + struct operand *dst, + const struct operand *src, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops, + enum x86_emulate_fpu_type *fpu_type) +#define fpu_type (*fpu_type) /* for get_fpu() */ +{ + unsigned long cr4; + int rc; + + if ( !s->vex.opcx && (!s->vex.pfx || s->vex.pfx == vex_66) ) + { + switch ( s->modrm_reg & 7 ) + { +#if !defined(X86EMUL_NO_FPU) || !defined(X86EMUL_NO_MMX) || \ + !defined(X86EMUL_NO_SIMD) + case 0: /* fxsave */ + case 1: /* fxrstor */ + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(fxsr); + generate_exception_if(s->ea.type != OP_MEM, X86_EXC_UD); + generate_exception_if(!is_aligned(s->ea.mem.seg, s->ea.mem.off, 16, + ctxt, ops), + X86_EXC_GP, 0); + fail_if(!ops->blk); + s->op_bytes = +#ifdef __x86_64__ + !mode_64bit() ? offsetof(struct x86_fxsr, xmm[8]) : +#endif + sizeof(struct x86_fxsr); + if ( amd_like(ctxt) ) + { + uint64_t msr_val; + + /* Assume "normal" operation in case of missing hooks. */ + if ( !ops->read_cr || + ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY ) + cr4 = X86_CR4_OSFXSR; + if ( !ops->read_msr || + ops->read_msr(MSR_EFER, &msr_val, ctxt) != X86EMUL_OKAY ) + msr_val = 0; + if ( !(cr4 & X86_CR4_OSFXSR) || + (mode_64bit() && mode_ring0() && (msr_val & EFER_FFXSE)) ) + s->op_bytes = offsetof(struct x86_fxsr, xmm[0]); + } + /* + * This could also be X86EMUL_FPU_mmx, but it shouldn't be + * X86EMUL_FPU_xmm, as we don't want CR4.OSFXSR checked. + */ + get_fpu(X86EMUL_FPU_fpu); + s->fpu_ctrl = true; + s->blk = s->modrm_reg & 1 ? blk_fxrstor : blk_fxsave; + if ( (rc = ops->blk(s->ea.mem.seg, s->ea.mem.off, NULL, + sizeof(struct x86_fxsr), ®s->eflags, + s, ctxt)) != X86EMUL_OKAY ) + goto done; + break; +#endif /* X86EMUL_NO_{FPU,MMX,SIMD} */ + +#ifndef X86EMUL_NO_SIMD + case 2: /* ldmxcsr */ + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(sse); + ldmxcsr: + generate_exception_if(src->type != OP_MEM, X86_EXC_UD); + get_fpu(s->vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm); + generate_exception_if(src->val & ~mxcsr_mask, X86_EXC_GP, 0); + asm volatile ( "ldmxcsr %0" :: "m" (src->val) ); + break; + + case 3: /* stmxcsr */ + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(sse); + stmxcsr: + generate_exception_if(dst->type != OP_MEM, X86_EXC_UD); + get_fpu(s->vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm); + asm volatile ( "stmxcsr %0" : "=m" (dst->val) ); + break; +#endif /* X86EMUL_NO_SIMD */ + + case 5: /* lfence */ + fail_if(s->modrm_mod != 3); + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(sse2); + asm volatile ( "lfence" ::: "memory" ); + break; + case 6: + if ( s->modrm_mod == 3 ) /* mfence */ + { + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(sse2); + asm volatile ( "mfence" ::: "memory" ); + break; + } + /* else clwb */ + fail_if(!s->vex.pfx); + vcpu_must_have(clwb); + fail_if(!ops->cache_op); + if ( (rc = ops->cache_op(x86emul_clwb, s->ea.mem.seg, s->ea.mem.off, + ctxt)) != X86EMUL_OKAY ) + goto done; + break; + case 7: + if ( s->modrm_mod == 3 ) /* sfence */ + { + generate_exception_if(s->vex.pfx, X86_EXC_UD); + vcpu_must_have(mmxext); + asm volatile ( "sfence" ::: "memory" ); + break; + } + /* else clflush{,opt} */ + if ( !s->vex.pfx ) + vcpu_must_have(clflush); + else + vcpu_must_have(clflushopt); + fail_if(!ops->cache_op); + if ( (rc = ops->cache_op(s->vex.pfx ? x86emul_clflushopt + : x86emul_clflush, + s->ea.mem.seg, s->ea.mem.off, + ctxt)) != X86EMUL_OKAY ) + goto done; + break; + default: + return X86EMUL_UNIMPLEMENTED; + } + } +#ifndef X86EMUL_NO_SIMD + else if ( s->vex.opcx && !s->vex.pfx ) + { + switch ( s->modrm_reg & 7 ) + { + case 2: /* vldmxcsr */ + generate_exception_if(s->vex.l || s->vex.reg != 0xf, X86_EXC_UD); + vcpu_must_have(avx); + goto ldmxcsr; + case 3: /* vstmxcsr */ + generate_exception_if(s->vex.l || s->vex.reg != 0xf, X86_EXC_UD); + vcpu_must_have(avx); + goto stmxcsr; + } + return X86EMUL_UNRECOGNIZED; + } +#endif /* !X86EMUL_NO_SIMD */ + else if ( !s->vex.opcx && s->vex.pfx == vex_f3 ) + { + enum x86_segment seg; + struct segment_register sreg; + + fail_if(s->modrm_mod != 3); + generate_exception_if((s->modrm_reg & 4) || !mode_64bit(), X86_EXC_UD); + fail_if(!ops->read_cr); + if ( (rc = ops->read_cr(4, &cr4, ctxt)) != X86EMUL_OKAY ) + goto done; + generate_exception_if(!(cr4 & X86_CR4_FSGSBASE), X86_EXC_UD); + seg = s->modrm_reg & 1 ? x86_seg_gs : x86_seg_fs; + 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); + if ( !(s->modrm_reg & 2) ) + { + /* rd{f,g}sbase */ + dst->type = OP_REG; + dst->bytes = (s->op_bytes == 8) ? 8 : 4; + dst->val = sreg.base; + } + else + { + /* wr{f,g}sbase */ + if ( s->op_bytes == 8 ) + { + sreg.base = *dst->reg; + generate_exception_if(!is_canonical_address(sreg.base), + X86_EXC_GP, 0); + } + else + sreg.base = (uint32_t)*dst->reg; + fail_if(!ops->write_segment); + if ( (rc = ops->write_segment(seg, &sreg, ctxt)) != X86EMUL_OKAY ) + goto done; + } + } + else + { + ASSERT_UNREACHABLE(); + return X86EMUL_UNRECOGNIZED; + } + + rc = X86EMUL_OKAY; + + done: + return rc; +} diff --git a/xen/arch/x86/x86_emulate/Makefile b/xen/arch/x86/x86_emulate/Makefile index 36d75f84bd..40336c071c 100644 --- a/xen/arch/x86/x86_emulate/Makefile +++ b/xen/arch/x86/x86_emulate/Makefile @@ -1 +1,2 @@ obj-y += 0f01.o +obj-y += 0fae.o diff --git a/xen/arch/x86/x86_emulate/private.h b/xen/arch/x86/x86_emulate/private.h index 7907f30122..b571ec2d66 100644 --- a/xen/arch/x86/x86_emulate/private.h +++ b/xen/arch/x86/x86_emulate/private.h @@ -22,6 +22,7 @@ # include <xen/kernel.h> # include <asm/msr-index.h> +# include <asm/x86-vendors.h> # include <asm/x86_emulate.h> # ifndef CONFIG_HVM @@ -308,6 +309,29 @@ struct x86_emulate_state { #endif }; +struct x86_fxsr { + uint16_t fcw; + uint16_t fsw; + uint8_t ftw, :8; + uint16_t fop; + union { + struct { + uint32_t offs; + uint16_t sel, :16; + }; + uint64_t addr; + } fip, fdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + struct { + uint8_t data[10]; + uint16_t :16, :16, :16; + } fpreg[8]; + uint64_t __attribute__ ((aligned(16))) xmm[16][2]; + uint64_t rsvd[6]; + uint64_t avl[6]; +}; + /* * Externally visible return codes from x86_emulate() are non-negative. * Use negative values for internal state change indicators from helpers @@ -397,6 +421,18 @@ in_protmode( (_cpl == 0); \ }) +static inline bool +_amd_like(const struct cpuid_policy *cp) +{ + return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); +} + +static inline bool +amd_like(const struct x86_emulate_ctxt *ctxt) +{ + return _amd_like(ctxt->cpuid); +} + #define vcpu_has_fpu() (ctxt->cpuid->basic.fpu) #define vcpu_has_sep() (ctxt->cpuid->basic.sep) #define vcpu_has_cx8() (ctxt->cpuid->basic.cx8) @@ -502,11 +538,52 @@ in_protmode( int x86emul_get_cpl(struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops); +int x86emul_get_fpu(enum x86_emulate_fpu_type type, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops); + +#define get_fpu(type) \ +do { \ + rc = x86emul_get_fpu(fpu_type = (type), ctxt, ops); \ + if ( rc ) goto done; \ +} while (0) + int x86emul_0f01(struct x86_emulate_state *s, struct cpu_user_regs *regs, struct operand *dst, struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops); +int x86emul_0fae(struct x86_emulate_state *s, + struct cpu_user_regs *regs, + struct operand *dst, + const struct operand *src, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops, + enum x86_emulate_fpu_type *fpu_type); + +static inline bool is_aligned(enum x86_segment seg, unsigned long offs, + unsigned int size, struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + struct segment_register reg; + + /* Expecting powers of two only. */ + ASSERT(!(size & (size - 1))); + + if ( mode_64bit() && seg < x86_seg_fs ) + memset(®, 0, sizeof(reg)); + else + { + /* No alignment checking when we have no way to read segment data. */ + if ( !ops->read_segment ) + return true; + + if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) + return false; + } + + return !((reg.base + offs) & (size - 1)); +} static inline bool umip_active(struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 5f6749534c..20d27765f2 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -695,29 +695,6 @@ typedef union { uint32_t data32[16]; } mmval_t; -struct x86_fxsr { - uint16_t fcw; - uint16_t fsw; - uint8_t ftw, :8; - uint16_t fop; - union { - struct { - uint32_t offs; - uint16_t sel, :16; - }; - uint64_t addr; - } fip, fdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - struct { - uint8_t data[10]; - uint16_t :16, :16, :16; - } fpreg[8]; - uint64_t __attribute__ ((aligned(16))) xmm[16][2]; - uint64_t rsvd[6]; - uint64_t avl[6]; -}; - /* * While proper alignment gets specified above, this doesn't get honored by * the compiler for automatic variables. Use this helper to instantiate a @@ -1063,7 +1040,7 @@ do { \ ops->write_segment(x86_seg_cs, cs, ctxt); \ }) -static int _get_fpu( +int x86emul_get_fpu( enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) @@ -1102,7 +1079,7 @@ static int _get_fpu( break; } - rc = ops->get_fpu(type, ctxt); + rc = (ops->get_fpu)(type, ctxt); if ( rc == X86EMUL_OKAY ) { @@ -1146,12 +1123,6 @@ static int _get_fpu( return rc; } -#define get_fpu(type) \ -do { \ - rc = _get_fpu(fpu_type = (type), ctxt, ops); \ - if ( rc ) goto done; \ -} while (0) - static void put_fpu( enum x86_emulate_fpu_type type, bool failed_late, @@ -1556,18 +1527,6 @@ static int ioport_access_check( return rc; } -static bool -_amd_like(const struct cpuid_policy *cp) -{ - return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); -} - -static bool -amd_like(const struct x86_emulate_ctxt *ctxt) -{ - return _amd_like(ctxt->cpuid); -} - /* Initialise output state in x86_emulate_ctxt */ static void init_context(struct x86_emulate_ctxt *ctxt) { @@ -1980,30 +1939,6 @@ static unsigned int decode_disp8scale(enum disp8scale scale, } \ } while ( false ) -static bool is_aligned(enum x86_segment seg, unsigned long offs, - unsigned int size, struct x86_emulate_ctxt *ctxt, - const struct x86_emulate_ops *ops) -{ - struct segment_register reg; - - /* Expecting powers of two only. */ - ASSERT(!(size & (size - 1))); - - if ( mode_64bit() && seg < x86_seg_fs ) - memset(®, 0, sizeof(reg)); - else - { - /* No alignment checking when we have no way to read segment data. */ - if ( !ops->read_segment ) - return true; - - if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) - return false; - } - - return !((reg.base + offs) & (size - 1)); -} - static bool is_branch_step(struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) { @@ -3346,7 +3281,8 @@ x86_emulate( #ifndef X86EMUL_NO_SIMD /* With a memory operand, fetch the mask register in use (if any). */ if ( ea.type == OP_MEM && evex.opmsk && - _get_fpu(fpu_type = X86EMUL_FPU_opmask, ctxt, ops) == X86EMUL_OKAY ) + x86emul_get_fpu(fpu_type = X86EMUL_FPU_opmask, + ctxt, ops) == X86EMUL_OKAY ) { uint8_t *stb = get_stub(stub); @@ -3369,7 +3305,7 @@ x86_emulate( if ( fpu_type == X86EMUL_FPU_opmask ) { - /* Squash (side) effects of the _get_fpu() above. */ + /* Squash (side) effects of the x86emul_get_fpu() above. */ x86_emul_reset_event(ctxt); put_fpu(X86EMUL_FPU_opmask, false, state, ctxt, ops); fpu_type = X86EMUL_FPU_none; @@ -7435,173 +7371,14 @@ x86_emulate( emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags); break; - case X86EMUL_OPC(0x0f, 0xae): case X86EMUL_OPC_66(0x0f, 0xae): /* Grp15 */ - switch ( modrm_reg & 7 ) - { -#if !defined(X86EMUL_NO_FPU) || !defined(X86EMUL_NO_MMX) || \ - !defined(X86EMUL_NO_SIMD) - case 0: /* fxsave */ - case 1: /* fxrstor */ - generate_exception_if(vex.pfx, EXC_UD); - vcpu_must_have(fxsr); - generate_exception_if(ea.type != OP_MEM, EXC_UD); - generate_exception_if(!is_aligned(ea.mem.seg, ea.mem.off, 16, - ctxt, ops), - EXC_GP, 0); - fail_if(!ops->blk); - op_bytes = -#ifdef __x86_64__ - !mode_64bit() ? offsetof(struct x86_fxsr, xmm[8]) : -#endif - sizeof(struct x86_fxsr); - if ( amd_like(ctxt) ) - { - /* Assume "normal" operation in case of missing hooks. */ - if ( !ops->read_cr || - ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY ) - cr4 = X86_CR4_OSFXSR; - if ( !ops->read_msr || - ops->read_msr(MSR_EFER, &msr_val, ctxt) != X86EMUL_OKAY ) - msr_val = 0; - if ( !(cr4 & X86_CR4_OSFXSR) || - (mode_64bit() && mode_ring0() && (msr_val & EFER_FFXSE)) ) - op_bytes = offsetof(struct x86_fxsr, xmm[0]); - } - /* - * This could also be X86EMUL_FPU_mmx, but it shouldn't be - * X86EMUL_FPU_xmm, as we don't want CR4.OSFXSR checked. - */ - get_fpu(X86EMUL_FPU_fpu); - state->fpu_ctrl = true; - state->blk = modrm_reg & 1 ? blk_fxrstor : blk_fxsave; - if ( (rc = ops->blk(ea.mem.seg, ea.mem.off, NULL, - sizeof(struct x86_fxsr), &_regs.eflags, - state, ctxt)) != X86EMUL_OKAY ) - goto done; - break; -#endif /* X86EMUL_NO_{FPU,MMX,SIMD} */ - -#ifndef X86EMUL_NO_SIMD - case 2: /* ldmxcsr */ - generate_exception_if(vex.pfx, EXC_UD); - vcpu_must_have(sse); - ldmxcsr: - generate_exception_if(src.type != OP_MEM, EXC_UD); - get_fpu(vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm); - 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); - get_fpu(vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm); - asm volatile ( "stmxcsr %0" : "=m" (dst.val) ); - break; -#endif /* X86EMUL_NO_SIMD */ - - case 5: /* lfence */ - fail_if(modrm_mod != 3); - generate_exception_if(vex.pfx, EXC_UD); - vcpu_must_have(sse2); - asm volatile ( "lfence" ::: "memory" ); - break; - case 6: - if ( modrm_mod == 3 ) /* mfence */ - { - generate_exception_if(vex.pfx, EXC_UD); - vcpu_must_have(sse2); - asm volatile ( "mfence" ::: "memory" ); - break; - } - /* else clwb */ - fail_if(!vex.pfx); - vcpu_must_have(clwb); - fail_if(!ops->cache_op); - if ( (rc = ops->cache_op(x86emul_clwb, ea.mem.seg, ea.mem.off, - ctxt)) != X86EMUL_OKAY ) - goto done; - break; - case 7: - if ( modrm_mod == 3 ) /* sfence */ - { - generate_exception_if(vex.pfx, EXC_UD); - vcpu_must_have(mmxext); - asm volatile ( "sfence" ::: "memory" ); - break; - } - /* else clflush{,opt} */ - if ( !vex.pfx ) - vcpu_must_have(clflush); - else - vcpu_must_have(clflushopt); - fail_if(!ops->cache_op); - if ( (rc = ops->cache_op(vex.pfx ? x86emul_clflushopt - : x86emul_clflush, - ea.mem.seg, ea.mem.off, - ctxt)) != X86EMUL_OKAY ) - goto done; - break; - default: - goto unimplemented_insn; - } - break; - + case X86EMUL_OPC(0x0f, 0xae): /* Grp15 */ + case X86EMUL_OPC_66(0x0f, 0xae): + case X86EMUL_OPC_F3(0x0f, 0xae): #ifndef X86EMUL_NO_SIMD - - 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 unrecognized_insn; - -#endif /* !X86EMUL_NO_SIMD */ - - case X86EMUL_OPC_F3(0x0f, 0xae): /* Grp15 */ - fail_if(modrm_mod != 3); - generate_exception_if((modrm_reg & 4) || !mode_64bit(), EXC_UD); - fail_if(!ops->read_cr); - if ( (rc = ops->read_cr(4, &cr4, ctxt)) != X86EMUL_OKAY ) - goto done; - generate_exception_if(!(cr4 & X86_CR4_FSGSBASE), EXC_UD); - seg = modrm_reg & 1 ? x86_seg_gs : x86_seg_fs; - fail_if(!ops->read_segment); - if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != X86EMUL_OKAY ) - goto done; - dst.reg = decode_gpr(&_regs, modrm_rm); - if ( !(modrm_reg & 2) ) - { - /* rd{f,g}sbase */ - dst.type = OP_REG; - dst.bytes = (op_bytes == 8) ? 8 : 4; - dst.val = sreg.base; - } - else - { - /* wr{f,g}sbase */ - if ( op_bytes == 8 ) - { - sreg.base = *dst.reg; - generate_exception_if(!is_canonical_address(sreg.base), - EXC_GP, 0); - } - else - sreg.base = (uint32_t)*dst.reg; - fail_if(!ops->write_segment); - if ( (rc = ops->write_segment(seg, &sreg, ctxt)) != X86EMUL_OKAY ) - goto done; - } - break; + case X86EMUL_OPC_VEX(0x0f, 0xae): +#endif + rc = x86emul_0fae(state, &_regs, &dst, &src, ctxt, ops, &fpu_type); + goto dispatch_from_helper; case X86EMUL_OPC(0x0f, 0xaf): /* imul */ emulate_2op_SrcV_srcmem("imul", src, dst, _regs.eflags); @@ -10543,7 +10320,7 @@ x86_emulate( goto unrecognized_insn; default: - unimplemented_insn: + unimplemented_insn: __maybe_unused; rc = X86EMUL_UNIMPLEMENTED; goto done; unrecognized_insn: -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |