diff options
Diffstat (limited to 'target/i386/hvf/x86_cpuid.c')
-rw-r--r-- | target/i386/hvf/x86_cpuid.c | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index 9874a46e92..9380b90496 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -7,7 +7,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -21,31 +21,28 @@ */ #include "qemu/osdep.h" -#include "qemu-common.h" #include "cpu.h" #include "x86.h" #include "vmx.h" #include "sysemu/hvf.h" +#include "hvf-i386.h" -static uint64_t xgetbv(uint32_t xcr) +static bool xgetbv(uint32_t cpuid_ecx, uint32_t idx, uint64_t *xcr) { - uint32_t eax, edx; + uint32_t xcrl, xcrh; - __asm__ volatile ("xgetbv" - : "=a" (eax), "=d" (edx) - : "c" (xcr)); + if (cpuid_ecx & CPUID_EXT_OSXSAVE) { + /* + * The xgetbv instruction is not available to older versions of + * the assembler, so we encode the instruction manually. + */ + asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl), "=d" (xcrh) : "c" (idx)); - return (((uint64_t)edx) << 32) | eax; -} - -static bool vmx_mpx_supported() -{ - uint64_t cap_exit, cap_entry; - - hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &cap_entry); - hv_vmx_read_capability(HV_VMX_CAP_EXIT, &cap_exit); + *xcr = (((uint64_t)xcrh) << 32) | xcrl; + return true; + } - return ((cap_exit & (1 << 23)) && (cap_entry & (1 << 16))); + return false; } uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, @@ -92,17 +89,15 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL | - CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_MPX; + CPUID_7_0_EBX_INVPCID; - if (!vmx_mpx_supported()) { - ebx &= ~CPUID_7_0_EBX_MPX; - } hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); if (!(cap & CPU_BASED2_INVPCID)) { ebx &= ~CPUID_7_0_EBX_INVPCID; } - ecx &= CPUID_7_0_ECX_AVX512BMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ; + ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ | + CPUID_7_0_ECX_RDPID; edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS; } else { ebx = 0; @@ -113,14 +108,14 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, break; case 0xD: if (idx == 0) { - uint64_t host_xcr0 = xgetbv(0); - uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK | XSTATE_SSE_MASK | - XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | - XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | - XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK); - eax &= supp_xcr0; - if (!vmx_mpx_supported()) { - eax &= ~(XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK); + uint64_t host_xcr0; + if (xgetbv(ecx, 0, &host_xcr0)) { + uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK | + XSTATE_SSE_MASK | XSTATE_YMM_MASK | + XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK | + XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | + XSTATE_Hi16_ZMM_MASK); + eax &= supp_xcr0; } } else if (idx == 1) { hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); @@ -138,8 +133,12 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX | CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX; + hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); + if (!(cap2ctrl(cap, CPU_BASED2_RDTSCP) & CPU_BASED2_RDTSCP)) { + edx &= ~CPUID_EXT2_RDTSCP; + } hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap); - if (!(cap & CPU_BASED_TSC_OFFSET)) { + if (!(cap2ctrl(cap, CPU_BASED_TSC_OFFSET) & CPU_BASED_TSC_OFFSET)) { edx &= ~CPUID_EXT2_RDTSCP; } ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG | |