From patchwork Tue Oct 4 13:39:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9361893 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 EC669600C8 for ; Tue, 4 Oct 2016 13:42:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC9B62872D for ; Tue, 4 Oct 2016 13:42:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D153A2878B; Tue, 4 Oct 2016 13:42:11 +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 1880D287A6 for ; Tue, 4 Oct 2016 13:42:08 +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 1brPwP-0007ao-16; Tue, 04 Oct 2016 13:39:29 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1brPwN-0007ai-Ej for xen-devel@lists.xenproject.org; Tue, 04 Oct 2016 13:39:27 +0000 Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id 16/92-15788-E01B3F75; Tue, 04 Oct 2016 13:39:26 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDIsWRWlGSWpSXmKPExsXS6fjDS5dr4+d wg9MXxC2+b5nM5MDocfjDFZYAxijWzLyk/IoE1ozbpy+wFKyyqjiyaBtLA+Np7S5GTg4hgTyJ ySv/M4LYvAJ2EndO32IFsSUEDCWevr/OBmKzCKhK3F1ylwnEZhNQl2h7th2ohoNDRMBA4tzRJ BCTWUBfYts6FpAKYYEIid1vzrBBTLeTePRzNTuIzSlgL/FjxWUWkHJeAUGJvzuEQcLMQCVPWz 4yT2DkmYWQmYUkA2FrSTz8dYsFwtaWWLbwNfMssL3SEsv/cUCEHSUadx5lRFUCYvtIHH2xmHk BI8cqRo3i1KKy1CJdI0u9pKLM9IyS3MTMHF1DA2O93NTi4sT01JzEpGK95PzcTYzAUK1nYGDc wdi01+8QoyQHk5Iob+XrT+FCfEn5KZUZicUZ8UWlOanFhxhlODiUJHj9N3wOFxIsSk1PrUjLz AFGDUxagoNHSYTXEyTNW1yQmFucmQ6ROsWoKCXO+2o9UEIAJJFRmgfXBovUS4yyUsK8jAwMDE I8BalFuZklqPKvGMU5GJWEeTlBxvNk5pXATX8FtJgJaHHglg8gi0sSEVJSDYytGeLKE5Zqh8u 0Vax3vdDrrle56Zli+Gvm84+D7LNm8OX0TP2gUaHdmnN4JX+K7zMFpa2v2GIbi8suLP1z7V46 6477hfctGjes8NCxPcrftGv+nwAzpp+rpT//9fv42mtvC0fNuaT44G8pS+IjWfxWOO2dlrDuZ co3xy0yj78nVey2KDnDJqXEUpyRaKjFXFScCADLustgzwIAAA== X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-10.tower-31.messagelabs.com!1475588360!63684351!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 36001 invoked from network); 4 Oct 2016 13:39:21 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-10.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 4 Oct 2016 13:39:21 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Tue, 04 Oct 2016 07:39:19 -0600 Message-Id: <57F3CD250200007800114EAC@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Tue, 04 Oct 2016 07:39:17 -0600 From: "Jan Beulich" To: "xen-devel" References: <57F3C95D0200007800114E99@prv-mh.provo.novell.com> In-Reply-To: <57F3C95D0200007800114E99@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH 1/3] x86emul: honor guest CR4.OSFXSR, CR4.OSXSAVE, and CR0.PE/EFLAGS.VM 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 These checks belong into the emulator instead of hvmemul_get_fpu(). Signed-off-by: Jan Beulich --- Eventually the XCR0 checks should also move into the insn emulator, but that'll require a new hook (or an extension to the read_cr() semantics). x86emul: honor guest CR4.OSFXSR, CR4.OSXSAVE, and CR0.PE/EFLAGS.VM These checks belong into the emulator instead of hvmemul_get_fpu(). Signed-off-by: Jan Beulich --- Eventually the XCR0 checks should also move into the insn emulator, but that'll require a new hook (or an extension to the read_cr() semantics). --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -129,6 +129,13 @@ static int cpuid( (edx & (1U << 26)) != 0; \ }) +#define cpu_has_xsave ({ \ + unsigned int eax = 1, ecx = 0; \ + cpuid(&eax, &eax, &ecx, &eax, NULL); \ + /* Intentionally checking OSXSAVE here. */ \ + (ecx & (1U << 27)) != 0; \ +}) + static inline uint64_t xgetbv(uint32_t xcr) { uint32_t lo, hi; @@ -169,6 +176,11 @@ static int read_cr( case 0: *val = 0x00000001; /* PE */ return X86EMUL_OKAY; + + case 4: + /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */ + *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0); + return X86EMUL_OKAY; } return X86EMUL_UNHANDLEABLE; --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -1631,20 +1631,11 @@ static int hvmemul_get_fpu( { case X86EMUL_FPU_fpu: case X86EMUL_FPU_wait: - break; case X86EMUL_FPU_mmx: - if ( !cpu_has_mmx ) - return X86EMUL_UNHANDLEABLE; - break; case X86EMUL_FPU_xmm: - if ( !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) ) - return X86EMUL_UNHANDLEABLE; break; case X86EMUL_FPU_ymm: - if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || - (ctxt->regs->eflags & X86_EFLAGS_VM) || - !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) || - !(curr->arch.xcr0 & XSTATE_SSE) || + if ( !(curr->arch.xcr0 & XSTATE_SSE) || !(curr->arch.xcr0 & XSTATE_YMM) ) return X86EMUL_UNHANDLEABLE; break; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -424,8 +424,11 @@ typedef union { #define CR0_MP (1<<1) #define CR0_EM (1<<2) #define CR0_TS (1<<3) -#define CR4_TSD (1<<2) -#define CR4_UMIP (1<<11) + +#define CR4_TSD (1<<2) +#define CR4_OSFXSR (1<<9) +#define CR4_UMIP (1<<11) +#define CR4_OSXSAVE (1<<18) /* EFLAGS bit definitions. */ #define EFLG_VIP (1<<20) @@ -770,9 +773,23 @@ static int _get_fpu( unsigned long cr0; fail_if(!ops->read_cr); + if ( type >= X86EMUL_FPU_xmm ) + { + unsigned long cr4; + + rc = ops->read_cr(4, &cr4, ctxt); + if ( rc != X86EMUL_OKAY ) + return rc; + generate_exception_if(!(cr4 & ((type == X86EMUL_FPU_xmm) + ? CR4_OSFXSR : CR4_OSXSAVE)), + EXC_UD, -1); + } + rc = ops->read_cr(0, &cr0, ctxt); if ( rc != X86EMUL_OKAY ) return rc; + if ( !(cr0 & CR0_PE) || (ctxt->regs->eflags & EFLG_VM) ) + generate_exception_if(type >= X86EMUL_FPU_ymm, EXC_UD, -1); if ( cr0 & CR0_EM ) { generate_exception_if(type == X86EMUL_FPU_fpu, EXC_NM, -1); --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -129,6 +129,13 @@ static int cpuid( (edx & (1U << 26)) != 0; \ }) +#define cpu_has_xsave ({ \ + unsigned int eax = 1, ecx = 0; \ + cpuid(&eax, &eax, &ecx, &eax, NULL); \ + /* Intentionally checking OSXSAVE here. */ \ + (ecx & (1U << 27)) != 0; \ +}) + static inline uint64_t xgetbv(uint32_t xcr) { uint32_t lo, hi; @@ -169,6 +176,11 @@ static int read_cr( case 0: *val = 0x00000001; /* PE */ return X86EMUL_OKAY; + + case 4: + /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */ + *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0); + return X86EMUL_OKAY; } return X86EMUL_UNHANDLEABLE; --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -1631,20 +1631,11 @@ static int hvmemul_get_fpu( { case X86EMUL_FPU_fpu: case X86EMUL_FPU_wait: - break; case X86EMUL_FPU_mmx: - if ( !cpu_has_mmx ) - return X86EMUL_UNHANDLEABLE; - break; case X86EMUL_FPU_xmm: - if ( !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) ) - return X86EMUL_UNHANDLEABLE; break; case X86EMUL_FPU_ymm: - if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || - (ctxt->regs->eflags & X86_EFLAGS_VM) || - !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) || - !(curr->arch.xcr0 & XSTATE_SSE) || + if ( !(curr->arch.xcr0 & XSTATE_SSE) || !(curr->arch.xcr0 & XSTATE_YMM) ) return X86EMUL_UNHANDLEABLE; break; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -424,8 +424,11 @@ typedef union { #define CR0_MP (1<<1) #define CR0_EM (1<<2) #define CR0_TS (1<<3) -#define CR4_TSD (1<<2) -#define CR4_UMIP (1<<11) + +#define CR4_TSD (1<<2) +#define CR4_OSFXSR (1<<9) +#define CR4_UMIP (1<<11) +#define CR4_OSXSAVE (1<<18) /* EFLAGS bit definitions. */ #define EFLG_VIP (1<<20) @@ -770,9 +773,23 @@ static int _get_fpu( unsigned long cr0; fail_if(!ops->read_cr); + if ( type >= X86EMUL_FPU_xmm ) + { + unsigned long cr4; + + rc = ops->read_cr(4, &cr4, ctxt); + if ( rc != X86EMUL_OKAY ) + return rc; + generate_exception_if(!(cr4 & ((type == X86EMUL_FPU_xmm) + ? CR4_OSFXSR : CR4_OSXSAVE)), + EXC_UD, -1); + } + rc = ops->read_cr(0, &cr0, ctxt); if ( rc != X86EMUL_OKAY ) return rc; + if ( !(cr0 & CR0_PE) || (ctxt->regs->eflags & EFLG_VM) ) + generate_exception_if(type >= X86EMUL_FPU_ymm, EXC_UD, -1); if ( cr0 & CR0_EM ) { generate_exception_if(type == X86EMUL_FPU_fpu, EXC_NM, -1);