diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index dbad9712e..38d70c3e8 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -94,25 +94,20 @@ static void start_cpus(void); static void pcpu_sync_sleep(unsigned long *sync, int mask_bit); int ibrs_type; -static inline bool get_tsc_adjust_cap(void) +inline bool cpu_has_cap(uint32_t bit) { - return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EBX] & CPUID_EBX_TSC_ADJ); -} + int feat_idx = bit >> 5; + int feat_bit = bit & 0x1f; -static inline bool get_ibrs_ibpb_cap(void) -{ - return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX] & - CPUID_EDX_IBRS_IBPB); -} + if (feat_idx >= FEATURE_WORDS) + return false; -static inline bool get_stibp_cap(void) -{ - return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX] & CPUID_EDX_STIBP); + return !!(boot_cpu_data.cpuid_leaves[feat_idx] & (1 << feat_bit)); } static inline bool get_monitor_cap(void) { - if (boot_cpu_data.cpuid_leaves[FEAT_1_ECX] & CPUID_ECX_MONITOR) { + if (cpu_has_cap(X86_FEATURE_MONITOR)) { /* don't use monitor for CPU (family: 0x6 model: 0x5c) * in hypervisor, but still expose it to the guests and * let them handle it correctly @@ -124,11 +119,6 @@ static inline bool get_monitor_cap(void) return false; } -inline bool get_vmx_cap(void) -{ - return !!(boot_cpu_data.cpuid_leaves[FEAT_1_ECX] & CPUID_ECX_VMX); -} - static uint64_t get_address_mask(uint8_t limit) { return ((1ULL << limit) - 1) & CPU_PAGE_MASK; @@ -198,9 +188,9 @@ static void get_cpu_capabilities(void) * should be set all the time instead of relying on retpoline */ #ifndef CONFIG_RETPOLINE - if (get_ibrs_ibpb_cap()) { + if (cpu_has_cap(X86_FEATURE_IBRS_IBPB)) { ibrs_type = IBRS_RAW; - if (get_stibp_cap()) + if (cpu_has_cap(X86_FEATURE_STIBP)) ibrs_type = IBRS_OPT; } #endif @@ -470,7 +460,8 @@ void bsp_boot_init(void) pr_dbg("Core %d is up", CPU_BOOT_ID); /* Warn for security feature not ready */ - if (!get_ibrs_ibpb_cap() && !get_stibp_cap()) { + if (!cpu_has_cap(X86_FEATURE_IBRS_IBPB) && + !cpu_has_cap(X86_FEATURE_STIBP)) { pr_fatal("SECURITY WARNING!!!!!!"); pr_fatal("Please apply the latest CPU uCode patch!"); } @@ -786,7 +777,7 @@ static void cpu_xsave_init(void) { uint64_t val64; - if (is_xsave_supported()) { + if (cpu_has_cap(X86_FEATURE_XSAVE)) { CPU_CR_READ(cr4, &val64); val64 |= CR4_OSXSAVE; CPU_CR_WRITE(cr4, val64); diff --git a/hypervisor/common/hv_main.c b/hypervisor/common/hv_main.c index 15e267402..6bad1a806 100644 --- a/hypervisor/common/hv_main.c +++ b/hypervisor/common/hv_main.c @@ -152,7 +152,7 @@ int hv_main(int cpu_id) "cpu_id/tsc_aux mismatch"); /* Check if virtualization extensions are supported */ - ret = get_vmx_cap(); + ret = cpu_has_cap(X86_FEATURE_VMX); ASSERT(ret == 1, "VMX not supported!"); /* Enable virtualization extensions */ diff --git a/hypervisor/include/arch/x86/cpu.h b/hypervisor/include/arch/x86/cpu.h index 21c82d817..c58e25a5f 100644 --- a/hypervisor/include/arch/x86/cpu.h +++ b/hypervisor/include/arch/x86/cpu.h @@ -224,15 +224,15 @@ extern uint64_t pcpu_active_bitmap; /* CPUID feature words */ enum feature_word { - FEAT_1_ECX, /* CPUID[1].ECX */ - FEAT_1_EDX, /* CPUID[1].EDX */ - FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */ - FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */ - FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */ - FEAT_8000_0000_EAX, /* CPUID[8000_0000].EAX */ - FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */ - FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */ - FEAT_8000_0008_EAX, /* CPUID[8000_0008].EAX */ + FEAT_1_ECX = 0, /* CPUID[1].ECX */ + FEAT_1_EDX = 1, /* CPUID[1].EDX */ + FEAT_7_0_EBX = 2, /* CPUID[EAX=7,ECX=0].EBX */ + FEAT_7_0_ECX = 3, /* CPUID[EAX=7,ECX=0].ECX */ + FEAT_7_0_EDX = 4, /* CPUID[EAX=7,ECX=0].EDX */ + FEAT_8000_0000_EAX = 5, /* CPUID[8000_0000].EAX */ + FEAT_8000_0001_ECX = 6, /* CPUID[8000_0001].ECX */ + FEAT_8000_0001_EDX = 7, /* CPUID[8000_0001].EDX */ + FEAT_8000_0008_EAX = 8, /* CPUID[8000_0008].EAX */ FEATURE_WORDS, }; @@ -258,8 +258,8 @@ int hv_main(int cpu_id); bool is_vapic_supported(void); bool is_vapic_intr_delivery_supported(void); bool is_vapic_virt_reg_supported(void); -bool get_vmx_cap(void); bool is_xsave_supported(void); +bool cpu_has_cap(uint32_t bit); /* Read control register */ #define CPU_CR_READ(cr, result_ptr) \ diff --git a/hypervisor/include/arch/x86/cpufeatures.h b/hypervisor/include/arch/x86/cpufeatures.h new file mode 100644 index 000000000..2cdb00500 --- /dev/null +++ b/hypervisor/include/arch/x86/cpufeatures.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __X86_CPUFEATURES_H__ +#define __X86_CPUFEATURES_H__ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ECX)*/ +#define X86_FEATURE_SSE3 ((FEAT_1_ECX << 5) + 0) +#define X86_FEATURE_PCLMUL ((FEAT_1_ECX << 5) + 1) +#define X86_FEATURE_DTES64 ((FEAT_1_ECX << 5) + 2) +#define X86_FEATURE_MONITOR ((FEAT_1_ECX << 5) + 3) +#define X86_FEATURE_DS_CPL ((FEAT_1_ECX << 5) + 4) +#define X86_FEATURE_VMX ((FEAT_1_ECX << 5) + 5) +#define X86_FEATURE_SMX ((FEAT_1_ECX << 5) + 6) +#define X86_FEATURE_EST ((FEAT_1_ECX << 5) + 7) +#define X86_FEATURE_TM2 ((FEAT_1_ECX << 5) + 8) +#define X86_FEATURE_SSSE3 ((FEAT_1_ECX << 5) + 9) +#define X86_FEATURE_CID ((FEAT_1_ECX << 5) + 10) +#define X86_FEATURE_FMA ((FEAT_1_ECX << 5) + 12) +#define X86_FEATURE_CX16 ((FEAT_1_ECX << 5) + 13) +#define X86_FEATURE_ETPRD ((FEAT_1_ECX << 5) + 14) +#define X86_FEATURE_PDCM ((FEAT_1_ECX << 5) + 15) +#define X86_FEATURE_PCID ((FEAT_1_ECX << 5) + 17) +#define X86_FEATURE_DCA ((FEAT_1_ECX << 5) + 18) +#define X86_FEATURE_SSE4_1 ((FEAT_1_ECX << 5) + 19) +#define X86_FEATURE_SSE4_2 ((FEAT_1_ECX << 5) + 20) +#define X86_FEATURE_x2APIC ((FEAT_1_ECX << 5) + 21) +#define X86_FEATURE_MOVBE ((FEAT_1_ECX << 5) + 22) +#define X86_FEATURE_POPCNT ((FEAT_1_ECX << 5) + 23) +#define X86_FEATURE_AES ((FEAT_1_ECX << 5) + 25) +#define X86_FEATURE_XSAVE ((FEAT_1_ECX << 5) + 26) +#define X86_FEATURE_OSXSAVE ((FEAT_1_ECX << 5) + 27) +#define X86_FEATURE_AVX ((FEAT_1_ECX << 5) + 28) + +/* Intel-defined CPU features, CPUID level 0x00000001 (EDX)*/ +#define X86_FEATURE_FPU ((FEAT_1_EDX << 5) + 0) +#define X86_FEATURE_VME ((FEAT_1_EDX << 5) + 1) +#define X86_FEATURE_DE ((FEAT_1_EDX << 5) + 2) +#define X86_FEATURE_PSE ((FEAT_1_EDX << 5) + 3) +#define X86_FEATURE_TSC ((FEAT_1_EDX << 5) + 4) +#define X86_FEATURE_MSR ((FEAT_1_EDX << 5) + 5) +#define X86_FEATURE_PAE ((FEAT_1_EDX << 5) + 6) +#define X86_FEATURE_MCE ((FEAT_1_EDX << 5) + 7) +#define X86_FEATURE_CX8 ((FEAT_1_EDX << 5) + 8) +#define X86_FEATURE_APIC ((FEAT_1_EDX << 5) + 9) +#define X86_FEATURE_SEP ((FEAT_1_EDX << 5) + 11) +#define X86_FEATURE_MTRR ((FEAT_1_EDX << 5) + 12) +#define X86_FEATURE_PGE ((FEAT_1_EDX << 5) + 13) +#define X86_FEATURE_MCA ((FEAT_1_EDX << 5) + 14) +#define X86_FEATURE_CMOV ((FEAT_1_EDX << 5) + 15) +#define X86_FEATURE_PAT ((FEAT_1_EDX << 5) + 16) +#define X86_FEATURE_PSE36 ((FEAT_1_EDX << 5) + 17) +#define X86_FEATURE_PSN ((FEAT_1_EDX << 5) + 18) +#define X86_FEATURE_CLF ((FEAT_1_EDX << 5) + 19) +#define X86_FEATURE_DTES ((FEAT_1_EDX << 5) + 21) +#define X86_FEATURE_ACPI ((FEAT_1_EDX << 5) + 22) +#define X86_FEATURE_MMX ((FEAT_1_EDX << 5) + 23) +#define X86_FEATURE_FXSR ((FEAT_1_EDX << 5) + 24) +#define X86_FEATURE_SSE ((FEAT_1_EDX << 5) + 25) +#define X86_FEATURE_SSE2 ((FEAT_1_EDX << 5) + 26) +#define X86_FEATURE_SS ((FEAT_1_EDX << 5) + 27) +#define X86_FEATURE_HTT ((FEAT_1_EDX << 5) + 28) +#define X86_FEATURE_TM1 ((FEAT_1_EDX << 5) + 29) +#define X86_FEATURE_IA64 ((FEAT_1_EDX << 5) + 30) +#define X86_FEATURE_PBE ((FEAT_1_EDX << 5) + 31) + +/* Intel-defined CPU features, CPUID level 0x00000007 (EBX)*/ +#define X86_FEATURE_TSC_ADJ ((FEAT_7_0_EBX << 5) + 1) +#define X86_FEATURE_INVPCID ((FEAT_7_0_EBX << 5) + 10) + +/* Intel-defined CPU features, CPUID level 0x00000007 (EDX)*/ +#define X86_FEATURE_IBRS_IBPB ((FEAT_7_0_EDX << 5) + 26) +#define X86_FEATURE_STIBP ((FEAT_7_0_EDX << 5) + 27) + +/* Intel-defined CPU features, CPUID level 0x80000001 (EDX)*/ +#define X86_FEATURE_PAGE1GB ((FEAT_8000_0001_EDX << 5) + 26) + +#endif /*__X86_CPUFEATURES_H__*/ diff --git a/hypervisor/include/arch/x86/hv_arch.h b/hypervisor/include/arch/x86/hv_arch.h index 226bb5bb7..011e73bfd 100644 --- a/hypervisor/include/arch/x86/hv_arch.h +++ b/hypervisor/include/arch/x86/hv_arch.h @@ -58,5 +58,6 @@ #include #include #include +#include #endif /* HV_ARCH_H */