From patchwork Thu Sep 14 15:22:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9953379 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 42794602C9 for ; Thu, 14 Sep 2017 15:24:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F95B290F3 for ; Thu, 14 Sep 2017 15:24:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 23F67290F7; Thu, 14 Sep 2017 15:24:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 782B8290F6 for ; Thu, 14 Sep 2017 15:24:38 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dsVy6-000514-Db; Thu, 14 Sep 2017 15:22:18 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dsVy4-000508-8Y for xen-devel@lists.xenproject.org; Thu, 14 Sep 2017 15:22:16 +0000 Received: from [85.158.139.211] by server-15.bemta-5.messagelabs.com id 37/AF-01761-7AE9AB95; Thu, 14 Sep 2017 15:22:15 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrPIsWRWlGSWpSXmKPExsXS6fjDS3fZvF2 RBm//8Vh83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBkfJu1nKehfx1TxYeZ75gbGfYcZuxg5OYQE 8iTaDk5kBrF5BewkOrdOZgOxJQQMJU4vvMkCYrMIqEo8vjIJzGYTUJdoe7adtYuRg0NEwEDi3 NGkLkYuDmaBLkaJuTNmgs0UFnCRuDPxMhvE/CKJ250QcU4Be4nO+dPAenkFBCX+7hAGCTMLaE k8/HWLBcLWlli28DUzSAmzgLTE8n8cExj5ZiE0zELSMAtJwyyEhgWMLKsYNYpTi8pSi3QNjfS SijLTM0pyEzNzdA0NTPVyU4uLE9NTcxKTivWS83M3MQIDkAEIdjD2zXI+xCjJwaQkyrtXd2ek EF9SfkplRmJxRnxRaU5q8SFGGQ4OJQneBXN3RQoJFqWmp1akZeYAYwEmLcHBoyTCew4kzVtck JhbnJkOkTrFaMlxbNPlP0wcqyZcAZIdN+/+YRJiycvPS5US590G0iAA0pBRmgc3DhavlxhlpY R5GYEOFOIpSC3KzSxBlX/FKM7BqCTMewFkCk9mXgnc1ldABzEBHXTm9A6Qg0oSEVJSDYwsddw lCsEbNxu/sWEPtuw5kP9C4PLNd5uWx8U5yX2bKDHnl4vzVom9u2R9ty1Xnj/jXJdI8qa4Dpfo JO0TvNNXTdw0OcTo4/nV97hvlH+cMPfM8hU3T4QJfXpx7/W/dVKLxWZreEdd5VDSZixevUum/ ccZiWXud3/v+30q3Zoz84TLTb4X13duUmIpzkg01GIuKk4EADc2I9/SAgAA X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-12.tower-206.messagelabs.com!1505402531!75293647!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 12735 invoked from network); 14 Sep 2017 15:22:13 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-12.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 14 Sep 2017 15:22:13 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Thu, 14 Sep 2017 09:22:11 -0600 Message-Id: <59BABAC1020000780017B3FF@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.2 Date: Thu, 14 Sep 2017 09:22:09 -0600 From: "Jan Beulich" To: "xen-devel" References: <59BAB38A020000780017B34E@prv-mh.provo.novell.com> <59BAB38A020000780017B34E@prv-mh.provo.novell.com> In-Reply-To: <59BAB38A020000780017B34E@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Disposition: inline Cc: George Dunlap , Andrew Cooper , Paul Durrant Subject: [Xen-devel] [PATCH v2 17/17] x86/HVM: eliminate custom #MF/#XM handling X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Use the generic stub exception handling instead. Signed-off-by: Jan Beulich Reviewed-by: Paul Durrant --- v2: Re-base. --- a/tools/tests/x86_emulator/x86_emulate.c +++ b/tools/tests/x86_emulator/x86_emulate.c @@ -134,8 +134,6 @@ int emul_test_read_xcr( } int emul_test_get_fpu( - void (*exception_callback)(void *, struct cpu_user_regs *), - void *exception_callback_arg, enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt) { --- a/tools/tests/x86_emulator/x86_emulate.h +++ b/tools/tests/x86_emulator/x86_emulate.h @@ -221,8 +221,6 @@ int emul_test_read_xcr( struct x86_emulate_ctxt *ctxt); int emul_test_get_fpu( - void (*exception_callback)(void *, struct cpu_user_regs *), - void *exception_callback_arg, enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt); --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -1739,8 +1739,6 @@ int hvmemul_cpuid(uint32_t leaf, uint32_ } static int hvmemul_get_fpu( - void (*exception_callback)(void *, struct cpu_user_regs *), - void *exception_callback_arg, enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt) { @@ -1778,9 +1776,6 @@ static int hvmemul_get_fpu( } } - curr->arch.hvm_vcpu.fpu_exception_callback = exception_callback; - curr->arch.hvm_vcpu.fpu_exception_callback_arg = exception_callback_arg; - return X86EMUL_OKAY; } @@ -1791,8 +1786,6 @@ static void hvmemul_put_fpu( { struct vcpu *curr = current; - curr->arch.hvm_vcpu.fpu_exception_callback = NULL; - if ( aux ) { typeof(curr->arch.xsave_area->fpu_sse) *fpu_ctxt = curr->arch.fpu_ctxt; --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -703,7 +703,6 @@ void do_reserved_trap(struct cpu_user_re void do_trap(struct cpu_user_regs *regs) { - struct vcpu *curr = current; unsigned int trapnr = regs->entry_vector; unsigned long fixup; @@ -723,15 +722,6 @@ void do_trap(struct cpu_user_regs *regs) return; } - if ( ((trapnr == TRAP_copro_error) || (trapnr == TRAP_simd_error)) && - system_state >= SYS_STATE_active && is_hvm_vcpu(curr) && - curr->arch.hvm_vcpu.fpu_exception_callback ) - { - curr->arch.hvm_vcpu.fpu_exception_callback( - curr->arch.hvm_vcpu.fpu_exception_callback_arg, regs); - return; - } - if ( likely((fixup = search_exception_table(regs)) != 0) ) { dprintk(XENLOG_ERR, "Trap %u: %p [%ps] -> %p\n", --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -959,6 +959,33 @@ static inline int mkec(uint8_t e, int32_ #define generate_exception(e, ec...) generate_exception_if(true, e, ##ec) #ifdef __XEN__ +static int exception_from_stub(union stub_exception_token res, + void *stub, unsigned int line, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + int rc = X86EMUL_UNHANDLEABLE; + + generate_exception_if(res.fields.trapnr == EXC_MF, EXC_MF); + if ( res.fields.trapnr == EXC_XM ) + { + unsigned long cr4; + + if ( !ops->read_cr || !ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY ) + cr4 = X86_CR4_OSXMMEXCPT; + generate_exception(cr4 & X86_CR4_OSXMMEXCPT ? EXC_XM : EXC_UD); + } + gprintk(XENLOG_WARNING, + "exception %u (ec=%04x) in emulation stub (line %u)\n", + res.fields.trapnr, res.fields.ec, line); + gprintk(XENLOG_INFO, "stub: %"__stringify(MAX_INST_LEN)"ph\n", stub); + generate_exception_if(res.fields.trapnr == EXC_UD, EXC_UD); + domain_crash(current->domain); + + done: + return rc; +} + # define invoke_stub(pre, post, constraints...) do { \ union stub_exception_token res_ = { .raw = ~0 }; \ asm volatile ( pre "\n\tcall *%[stub]\n\t" post "\n" \ @@ -974,14 +1001,8 @@ static inline int mkec(uint8_t e, int32_ "m" (*(uint8_t(*)[MAX_INST_LEN + 1])stub.ptr) ); \ if ( unlikely(~res_.raw) ) \ { \ - gprintk(XENLOG_WARNING, \ - "exception %u (ec=%04x) in emulation stub (line %u)\n", \ - res_.fields.trapnr, res_.fields.ec, __LINE__); \ - gprintk(XENLOG_INFO, "stub: %"__stringify(MAX_INST_LEN)"ph\n", \ - stub.func); \ - generate_exception_if(res_.fields.trapnr == EXC_UD, EXC_UD); \ - domain_crash(current->domain); \ - goto cannot_emulate; \ + rc = exception_from_stub(res_, stub.func, __LINE__, ctxt, ops); \ + goto done; \ } \ } while (0) #else @@ -1097,23 +1118,8 @@ do { ops->write_segment(x86_seg_cs, cs, ctxt); \ }) -struct fpu_insn_ctxt { - uint8_t insn_bytes; - uint8_t type; - int8_t exn_raised; -}; - -static void fpu_handle_exception(void *_fic, struct cpu_user_regs *regs) -{ - struct fpu_insn_ctxt *fic = _fic; - ASSERT(regs->entry_vector < 0x20); - fic->exn_raised = regs->entry_vector; - regs->r(ip) += fic->insn_bytes; -} - static int _get_fpu( enum x86_emulate_fpu_type type, - struct fpu_insn_ctxt *fic, struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) { @@ -1138,14 +1144,13 @@ static int _get_fpu( break; } - rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt); + rc = ops->get_fpu(type, ctxt); if ( rc == X86EMUL_OKAY ) { unsigned long cr0; fail_if(type == X86EMUL_FPU_fpu && !ops->put_fpu); - fic->type = type; fail_if(!ops->read_cr); if ( type >= X86EMUL_FPU_xmm ) @@ -1183,37 +1188,22 @@ static int _get_fpu( return rc; } -#define get_fpu(_type, _fic) \ +#define get_fpu(type) \ do { \ - rc = _get_fpu(_type, _fic, ctxt, ops); \ + rc = _get_fpu(fpu_type = (type), ctxt, ops); \ if ( rc ) goto done; \ } while (0) -#define check_fpu_exn(fic) \ -do { \ - generate_exception_if((fic)->exn_raised >= 0, \ - (fic)->exn_raised); \ -} while (0) - -#define check_xmm_exn(fic) \ -do { \ - if ( (fic)->exn_raised == EXC_XM && ops->read_cr && \ - ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && \ - !(cr4 & X86_CR4_OSXMMEXCPT) ) \ - (fic)->exn_raised = EXC_UD; \ - check_fpu_exn(fic); \ -} while (0) - static void put_fpu( - struct fpu_insn_ctxt *fic, + enum x86_emulate_fpu_type type, bool failed_late, const struct x86_emulate_state *state, struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) { - if ( unlikely(failed_late) && fic->type == X86EMUL_FPU_fpu ) + if ( unlikely(failed_late) && type == X86EMUL_FPU_fpu ) ops->put_fpu(ctxt, X86EMUL_FPU_fpu, NULL); - else if ( unlikely(fic->type == X86EMUL_FPU_fpu) && !state->fpu_ctrl ) + else if ( unlikely(type == X86EMUL_FPU_fpu) && !state->fpu_ctrl ) { struct x86_emul_fpu_aux aux = { .ip = ctxt->regs->r(ip), @@ -1247,9 +1237,8 @@ static void put_fpu( } ops->put_fpu(ctxt, X86EMUL_FPU_none, &aux); } - else if ( fic->type != X86EMUL_FPU_none && ops->put_fpu ) + else if ( type != X86EMUL_FPU_none && ops->put_fpu ) ops->put_fpu(ctxt, X86EMUL_FPU_none, NULL); - fic->type = X86EMUL_FPU_none; } static inline bool fpu_check_write(void) @@ -1264,29 +1253,27 @@ static inline bool fpu_check_write(void) #define emulate_fpu_insn_memdst(opc, ext, arg) \ do { \ /* ModRM: mod=0, reg=ext, rm=0, i.e. a (%rax) operand */ \ - fic.insn_bytes = 2; \ + insn_bytes = 2; \ memcpy(get_stub(stub), \ ((uint8_t[]){ opc, ((ext) & 7) << 3, 0xc3 }), 3); \ - invoke_stub("", "", "+m" (fic), "+m" (arg) : "a" (&(arg))); \ + invoke_stub("", "", "+m" (arg) : "a" (&(arg))); \ put_stub(stub); \ } while (0) #define emulate_fpu_insn_memsrc(opc, ext, arg) \ do { \ /* ModRM: mod=0, reg=ext, rm=0, i.e. a (%rax) operand */ \ - fic.insn_bytes = 2; \ memcpy(get_stub(stub), \ ((uint8_t[]){ opc, ((ext) & 7) << 3, 0xc3 }), 3); \ - invoke_stub("", "", "+m" (fic) : "m" (arg), "a" (&(arg))); \ + invoke_stub("", "", "=m" (dummy) : "m" (arg), "a" (&(arg))); \ put_stub(stub); \ } while (0) #define emulate_fpu_insn_stub(bytes...) \ do { \ unsigned int nr_ = sizeof((uint8_t[]){ bytes }); \ - fic.insn_bytes = nr_; \ memcpy(get_stub(stub), ((uint8_t[]){ bytes, 0xc3 }), nr_ + 1); \ - invoke_stub("", "", "=m" (fic) : "m" (fic)); \ + invoke_stub("", "", "=m" (dummy) : "i" (0)); \ put_stub(stub); \ } while (0) @@ -1294,12 +1281,10 @@ do { do { \ unsigned int nr_ = sizeof((uint8_t[]){ bytes }); \ unsigned long tmp_; \ - fic.insn_bytes = nr_; \ memcpy(get_stub(stub), ((uint8_t[]){ bytes, 0xc3 }), nr_ + 1); \ invoke_stub(_PRE_EFLAGS("[eflags]", "[mask]", "[tmp]"), \ _POST_EFLAGS("[eflags]", "[mask]", "[tmp]"), \ - [eflags] "+g" (_regs.eflags), [tmp] "=&r" (tmp_), \ - "+m" (fic) \ + [eflags] "+g" (_regs.eflags), [tmp] "=&r" (tmp_) \ : [mask] "i" (X86_EFLAGS_ZF|X86_EFLAGS_PF|X86_EFLAGS_CF)); \ put_stub(stub); \ } while (0) @@ -3142,14 +3127,14 @@ x86_emulate( struct x86_emulate_state state; int rc; uint8_t b, d, *opc = NULL; - unsigned int first_byte = 0; + unsigned int first_byte = 0, insn_bytes = 0; bool singlestep = (_regs.eflags & X86_EFLAGS_TF) && !is_branch_step(ctxt, ops); bool sfence = false; struct operand src = { .reg = PTR_POISON }; struct operand dst = { .reg = PTR_POISON }; unsigned long cr4; - struct fpu_insn_ctxt fic = { .type = X86EMUL_FPU_none, .exn_raised = -1 }; + enum x86_emulate_fpu_type fpu_type = X86EMUL_FPU_none; struct x86_emulate_stub stub = {}; DECLARE_ALIGNED(mmval_t, mmval); @@ -3839,9 +3824,8 @@ x86_emulate( case 0x9b: /* wait/fwait */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_wait, &fic); + get_fpu(X86EMUL_FPU_wait); emulate_fpu_insn_stub(b); - check_fpu_exn(&fic); break; case 0x9c: /* pushf */ @@ -4245,7 +4229,7 @@ x86_emulate( case 0xd8: /* FPU 0xd8 */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* fadd %stN,%st */ @@ -4267,12 +4251,11 @@ x86_emulate( emulate_fpu_insn_memsrc(b, modrm_reg, src.val); break; } - check_fpu_exn(&fic); break; case 0xd9: /* FPU 0xd9 */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xfb: /* fsincos */ @@ -4354,12 +4337,11 @@ x86_emulate( if ( dst.type == OP_MEM && !state->fpu_ctrl && !fpu_check_write() ) dst.type = OP_NONE; } - check_fpu_exn(&fic); break; case 0xda: /* FPU 0xda */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* fcmovb %stN */ @@ -4376,12 +4358,11 @@ x86_emulate( generate_exception_if(ea.type != OP_MEM, EXC_UD); goto fpu_memsrc32; } - check_fpu_exn(&fic); break; case 0xdb: /* FPU 0xdb */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* fcmovnb %stN */ @@ -4434,12 +4415,11 @@ x86_emulate( generate_exception(EXC_UD); } } - check_fpu_exn(&fic); break; case 0xdc: /* FPU 0xdc */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* fadd %st,%stN */ @@ -4461,12 +4441,11 @@ x86_emulate( emulate_fpu_insn_memsrc(b, modrm_reg, src.val); break; } - check_fpu_exn(&fic); break; case 0xdd: /* FPU 0xdd */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* ffree %stN */ @@ -4510,12 +4489,11 @@ x86_emulate( if ( dst.type == OP_MEM && !state->fpu_ctrl && !fpu_check_write() ) dst.type = OP_NONE; } - check_fpu_exn(&fic); break; case 0xde: /* FPU 0xde */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xc0 ... 0xc7: /* faddp %stN */ @@ -4533,12 +4511,11 @@ x86_emulate( emulate_fpu_insn_memsrc(b, modrm_reg, src.val); break; } - check_fpu_exn(&fic); break; case 0xdf: /* FPU 0xdf */ host_and_vcpu_must_have(fpu); - get_fpu(X86EMUL_FPU_fpu, &fic); + get_fpu(X86EMUL_FPU_fpu); switch ( modrm ) { case 0xe0: @@ -4583,7 +4560,6 @@ x86_emulate( goto fpu_memdst64; } } - check_fpu_exn(&fic); break; case 0xe0 ... 0xe2: /* loop{,z,nz} */ { @@ -5415,7 +5391,7 @@ x86_emulate( else generate_exception(EXC_UD); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); d = DstReg | SrcMem; op_bytes = 8; @@ -5505,7 +5481,7 @@ x86_emulate( else vcpu_must_have(sse); simd_0f_xmm: - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { @@ -5515,7 +5491,7 @@ x86_emulate( simd_0f_avx: host_and_vcpu_must_have(avx); simd_0f_ymm: - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } simd_0f_common: opc = init_prefixes(stub); @@ -5528,7 +5504,7 @@ x86_emulate( vex.b = 1; opc[1] &= 0x38; } - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; break; case X86EMUL_OPC_66(0x0f, 0x12): /* movlpd m64,xmm */ @@ -5615,12 +5591,12 @@ x86_emulate( vcpu_must_have(sse2); else vcpu_must_have(sse); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } if ( ea.type == OP_MEM ) @@ -5646,14 +5622,14 @@ x86_emulate( vcpu_must_have(sse2); else vcpu_must_have(sse); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { generate_exception_if(vex.reg != 0xf, EXC_UD); vex.l = 0; host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } opc = init_prefixes(stub); @@ -5676,17 +5652,14 @@ x86_emulate( opc[1] = modrm & 0xc7; if ( !mode_64bit() ) vex.w = 0; - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; opc[2] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); ea.reg = decode_register(modrm_reg, &_regs, 0); - invoke_stub("", "", "=a" (*ea.reg), "+m" (fic.exn_raised) - : "c" (mmvalp), "m" (*mmvalp)); + invoke_stub("", "", "=a" (*ea.reg) : "c" (mmvalp), "m" (*mmvalp)); put_stub(stub); - check_xmm_exn(&fic); - state->simd_size = simd_none; break; @@ -5700,13 +5673,13 @@ x86_emulate( vcpu_must_have(sse2); else vcpu_must_have(sse); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { generate_exception_if(vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } opc = init_prefixes(stub); @@ -5724,20 +5697,17 @@ x86_emulate( vex.b = 1; opc[1] &= 0x38; } - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; opc[2] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); invoke_stub(_PRE_EFLAGS("[eflags]", "[mask]", "[tmp]"), _POST_EFLAGS("[eflags]", "[mask]", "[tmp]"), [eflags] "+g" (_regs.eflags), - [tmp] "=&r" (dummy), "+m" (*mmvalp), - "+m" (fic.exn_raised) + [tmp] "=&r" (dummy), "+m" (*mmvalp) : "a" (mmvalp), [mask] "i" (EFLAGS_MASK)); put_stub(stub); - check_xmm_exn(&fic); - ASSERT(!state->simd_size); break; @@ -5875,9 +5845,9 @@ x86_emulate( if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0xc7; - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; simd_0f_to_gpr: - opc[fic.insn_bytes - PFX_BYTES] = 0xc3; + opc[insn_bytes - PFX_BYTES] = 0xc3; generate_exception_if(ea.type != OP_REG, EXC_UD); @@ -5896,9 +5866,9 @@ x86_emulate( vcpu_must_have(sse); } if ( b == 0x50 || (vex.pfx & VEX_PREFIX_DOUBLE_MASK) ) - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); else - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } else { @@ -5907,14 +5877,13 @@ x86_emulate( host_and_vcpu_must_have(avx); else host_and_vcpu_must_have(avx2); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", "=a" (dst.val) : [dummy] "i" (0)); put_stub(stub); - check_xmm_exn(&fic); ASSERT(!state->simd_size); dst.bytes = 4; @@ -6080,7 +6049,7 @@ x86_emulate( goto simd_0f_sse2; simd_0f_mmx: host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); goto simd_0f_common; CASE_SIMD_PACKED_INT(0x0f, 0x6e): /* mov{d,q} r/m,{,x}mm */ @@ -6091,17 +6060,17 @@ x86_emulate( { generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } else if ( vex.pfx ) { vcpu_must_have(sse2); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } simd_0f_rm: @@ -6113,17 +6082,14 @@ x86_emulate( if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0x38; - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; opc[2] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); - invoke_stub("", "", "+m" (src.val), "+m" (fic.exn_raised) - : "a" (&src.val)); + invoke_stub("", "", "+m" (src.val) : "a" (&src.val)); dst.val = src.val; put_stub(stub); - check_xmm_exn(&fic); - ASSERT(!state->simd_size); break; @@ -6189,19 +6155,19 @@ x86_emulate( host_and_vcpu_must_have(avx); } simd_0f_imm8_ymm: - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } else if ( vex.pfx ) { simd_0f_imm8_sse2: vcpu_must_have(sse2); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); vcpu_must_have(mmxext); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } simd_0f_imm8: opc = init_prefixes(stub); @@ -6215,7 +6181,7 @@ x86_emulate( opc[1] &= 0x38; } opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; break; CASE_SIMD_PACKED_INT(0x0f, 0x71): /* Grp12 */ @@ -6243,33 +6209,31 @@ x86_emulate( host_and_vcpu_must_have(avx2); else host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } else if ( vex.pfx ) { vcpu_must_have(sse2); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } opc = init_prefixes(stub); opc[0] = b; opc[1] = modrm; opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; simd_0f_reg_only: - opc[fic.insn_bytes - PFX_BYTES] = 0xc3; + opc[insn_bytes - PFX_BYTES] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", [dummy_out] "=g" (dummy) : [dummy_in] "i" (0) ); put_stub(stub); - check_xmm_exn(&fic); - ASSERT(!state->simd_size); break; @@ -6304,7 +6268,7 @@ x86_emulate( { generate_exception_if(vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); #ifdef __x86_64__ if ( !mode_64bit() ) @@ -6346,12 +6310,12 @@ x86_emulate( else { host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } opc = init_prefixes(stub); opc[0] = b; - fic.insn_bytes = PFX_BYTES + 1; + insn_bytes = PFX_BYTES + 1; goto simd_0f_reg_only; case X86EMUL_OPC_66(0x0f, 0x78): /* Grp17 */ @@ -6367,14 +6331,14 @@ x86_emulate( generate_exception_if(ea.type != OP_REG, EXC_UD); host_and_vcpu_must_have(sse4a); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); opc = init_prefixes(stub); opc[0] = b; opc[1] = modrm; opc[2] = imm1; opc[3] = imm2; - fic.insn_bytes = PFX_BYTES + 4; + insn_bytes = PFX_BYTES + 4; goto simd_0f_reg_only; case X86EMUL_OPC_66(0x0f, 0x79): /* extrq xmm,xmm */ @@ -6502,7 +6466,7 @@ x86_emulate( vcpu_must_have(sse); ldmxcsr: generate_exception_if(src.type != OP_MEM, EXC_UD); - get_fpu(vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm, &fic); + 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; @@ -6512,7 +6476,7 @@ x86_emulate( vcpu_must_have(sse); stmxcsr: generate_exception_if(dst.type != OP_MEM, EXC_UD); - get_fpu(vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm, &fic); + get_fpu(vex.opcx ? X86EMUL_FPU_ymm : X86EMUL_FPU_xmm); asm volatile ( "stmxcsr %0" : "=m" (dst.val) ); break; @@ -6766,7 +6730,7 @@ x86_emulate( if ( vex.pfx & VEX_PREFIX_DOUBLE_MASK ) goto simd_0f_imm8_sse2; vcpu_must_have(sse); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); goto simd_0f_imm8; } goto simd_0f_imm8_avx; @@ -6797,7 +6761,7 @@ x86_emulate( vex.w = 0; opc[1] = modrm & 0xc7; opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; goto simd_0f_to_gpr; case X86EMUL_OPC(0x0f, 0xc7): /* Grp9 */ @@ -7043,18 +7007,18 @@ x86_emulate( generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD); d |= TwoOp; host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } else if ( vex.pfx ) { vcpu_must_have(sse2); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); vcpu_must_have(mmxext); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } /* @@ -7074,7 +7038,6 @@ x86_emulate( if ( !mode_64bit() ) vex.w = 0; opc[1] = modrm & 0xc7; - fic.insn_bytes = PFX_BYTES + 2; opc[2] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); @@ -7087,6 +7050,7 @@ x86_emulate( opc = init_prefixes(stub); opc[0] = b; opc[1] = modrm; + insn_bytes = PFX_BYTES + 2; /* Restore high bit of XMM destination. */ if ( sfence ) { @@ -7133,12 +7097,12 @@ x86_emulate( if ( vex.pfx ) { simd_0f38_common: - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } opc = init_prefixes(stub); opc[0] = 0x38; @@ -7151,7 +7115,7 @@ x86_emulate( vex.b = 1; opc[2] &= 0x38; } - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; break; case X86EMUL_OPC_VEX_66(0x0f38, 0x19): /* vbroadcastsd m64,ymm */ @@ -7175,13 +7139,13 @@ x86_emulate( if ( vex.opcx == vex_none ) { host_and_vcpu_must_have(sse4_1); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { generate_exception_if(vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } opc = init_prefixes(stub); @@ -7200,21 +7164,19 @@ x86_emulate( vex.b = 1; opc[1] &= 0x38; } - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; opc[2] = 0xc3; if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ --opc; - ++fic.insn_bytes; + ++insn_bytes; } copy_REX_VEX(opc, rex_prefix, vex); emulate_stub("+m" (*mmvalp), "a" (mmvalp)); put_stub(stub); - check_xmm_exn(&fic); - state->simd_size = simd_none; dst.type = OP_NONE; break; @@ -7303,7 +7265,7 @@ x86_emulate( generate_exception_if(ea.type != OP_MEM || vex.w, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); /* * While we can't reasonably provide fully correct behavior here @@ -7352,7 +7314,7 @@ x86_emulate( rex_prefix &= ~REX_B; vex.b = 1; opc[1] = modrm & 0x38; - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; break; } @@ -7401,7 +7363,7 @@ x86_emulate( generate_exception_if(ea.type != OP_MEM, EXC_UD); host_and_vcpu_must_have(avx2); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); /* * While we can't reasonably provide fully correct behavior here @@ -7448,7 +7410,7 @@ x86_emulate( rex_prefix &= ~REX_B; vex.b = 1; opc[1] = modrm & 0x38; - fic.insn_bytes = PFX_BYTES + 2; + insn_bytes = PFX_BYTES + 2; break; } @@ -7471,7 +7433,7 @@ x86_emulate( state->sib_index == mask_reg, EXC_UD); generate_exception_if(!cpu_has_avx, EXC_UD); vcpu_must_have(avx2); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); /* Read destination, index, and mask registers. */ opc = init_prefixes(stub); @@ -7808,12 +7770,12 @@ x86_emulate( if ( vex.pfx ) { simd_0f3a_common: - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { host_and_vcpu_must_have(mmx); - get_fpu(X86EMUL_FPU_mmx, &fic); + get_fpu(X86EMUL_FPU_mmx); } opc = init_prefixes(stub); opc[0] = 0x3a; @@ -7827,7 +7789,7 @@ x86_emulate( opc[2] &= 0x38; } opc[3] = imm1; - fic.insn_bytes = PFX_BYTES + 4; + insn_bytes = PFX_BYTES + 4; break; case X86EMUL_OPC_66(0x0f3a, 0x14): /* pextrb $imm8,xmm,r/m */ @@ -7835,7 +7797,7 @@ x86_emulate( case X86EMUL_OPC_66(0x0f3a, 0x16): /* pextr{d,q} $imm8,xmm,r/m */ case X86EMUL_OPC_66(0x0f3a, 0x17): /* extractps $imm8,xmm,r/m */ host_and_vcpu_must_have(sse4_1); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); opc = init_prefixes(stub); opc++[0] = 0x3a; @@ -7848,20 +7810,16 @@ x86_emulate( vex.w = 0; opc[1] = modrm & 0x38; opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; opc[3] = 0xc3; if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ --opc; - ++fic.insn_bytes; } copy_REX_VEX(opc, rex_prefix, vex); invoke_stub("", "", "=m" (dst.val) : "a" (&dst.val)); - put_stub(stub); - check_xmm_exn(&fic); ASSERT(!state->simd_size); dst.bytes = dst.type == OP_REG || b == 0x17 ? 4 : 1 << (b & 3); @@ -7875,7 +7833,7 @@ x86_emulate( case X86EMUL_OPC_VEX_66(0x0f3a, 0x17): /* vextractps $imm8,xmm,r/m */ generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); opc = init_prefixes(stub); goto pextr; @@ -7897,17 +7855,15 @@ x86_emulate( opc[1] &= 0x38; } opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; opc[3] = 0xc3; copy_VEX(opc, vex); /* Latch MXCSR - we may need to restore it below. */ invoke_stub("stmxcsr %[mxcsr]", "", - "=m" (*mmvalp), "+m" (fic.exn_raised), [mxcsr] "=m" (mxcsr) - : "a" (mmvalp)); + "=m" (*mmvalp), [mxcsr] "=m" (mxcsr) : "a" (mmvalp)); put_stub(stub); - check_xmm_exn(&fic); if ( ea.type == OP_MEM ) { @@ -7926,7 +7882,7 @@ x86_emulate( case X86EMUL_OPC_66(0x0f3a, 0x20): /* pinsrb $imm8,r32/m8,xmm */ case X86EMUL_OPC_66(0x0f3a, 0x22): /* pinsr{d,q} $imm8,r/m,xmm */ host_and_vcpu_must_have(sse4_1); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); memcpy(mmvalp, &src.val, op_bytes); ea.type = OP_MEM; op_bytes = src.bytes; @@ -8036,13 +7992,13 @@ x86_emulate( if ( vex.opcx == vex_none ) { host_and_vcpu_must_have(sse4_2); - get_fpu(X86EMUL_FPU_xmm, &fic); + get_fpu(X86EMUL_FPU_xmm); } else { generate_exception_if(vex.l || vex.reg != 0xf, EXC_UD); host_and_vcpu_must_have(avx); - get_fpu(X86EMUL_FPU_ymm, &fic); + get_fpu(X86EMUL_FPU_ymm); } opc = init_prefixes(stub); @@ -8063,13 +8019,13 @@ x86_emulate( goto done; } opc[2] = imm1; - fic.insn_bytes = PFX_BYTES + 3; + insn_bytes = PFX_BYTES + 3; opc[3] = 0xc3; if ( vex.opcx == vex_none ) { /* Cover for extra prefix byte. */ --opc; - ++fic.insn_bytes; + ++insn_bytes; } copy_REX_VEX(opc, rex_prefix, vex); @@ -8297,7 +8253,7 @@ x86_emulate( if ( !opc ) BUG(); - opc[fic.insn_bytes - PFX_BYTES] = 0xc3; + opc[insn_bytes - PFX_BYTES] = 0xc3; copy_REX_VEX(opc, rex_prefix, vex); if ( ea.type == OP_MEM ) @@ -8374,13 +8330,11 @@ x86_emulate( if ( likely((ctxt->opcode & ~(X86EMUL_OPC_PFX_MASK | X86EMUL_OPC_ENCODING_MASK)) != X86EMUL_OPC(0x0f, 0xf7)) ) - invoke_stub("", "", "+m" (*mmvalp), "+m" (fic.exn_raised) - : "a" (mmvalp)); + invoke_stub("", "", "+m" (*mmvalp) : "a" (mmvalp)); else invoke_stub("", "", "+m" (*mmvalp) : "D" (mmvalp)); put_stub(stub); - check_xmm_exn(&fic); } switch ( dst.type ) @@ -8423,7 +8377,8 @@ x86_emulate( } complete_insn: /* Commit shadow register state. */ - put_fpu(&fic, false, state, ctxt, ops); + put_fpu(fpu_type, false, state, ctxt, ops); + fpu_type = X86EMUL_FPU_none; /* Zero the upper 32 bits of %rip if not in 64-bit mode. */ if ( !mode_64bit() ) @@ -8447,7 +8402,7 @@ x86_emulate( ctxt->regs->eflags &= ~X86_EFLAGS_RF; done: - put_fpu(&fic, fic.insn_bytes > 0 && dst.type == OP_MEM, state, ctxt, ops); + put_fpu(fpu_type, insn_bytes > 0 && dst.type == OP_MEM, state, ctxt, ops); put_stub(stub); return rc; #undef state --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -421,12 +421,8 @@ struct x86_emulate_ops /* * get_fpu: Load emulated environment's FPU state onto processor. - * @exn_callback: On any FPU or SIMD exception, pass control to - * (*exception_callback)(exception_callback_arg, regs). */ int (*get_fpu)( - void (*exception_callback)(void *, struct cpu_user_regs *), - void *exception_callback_arg, enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt); --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -196,10 +196,6 @@ struct hvm_vcpu { struct hvm_vcpu_io hvm_io; - /* Callback into x86_emulate when emulating FPU/MMX/XMM instructions. */ - void (*fpu_exception_callback)(void *, struct cpu_user_regs *); - void *fpu_exception_callback_arg; - /* Pending hw/sw interrupt (.vector = -1 means nothing pending). */ struct x86_event inject_event;