diff --git a/arch/x86/cpu.c b/arch/x86/cpu.c index 389f2e7a1..1e326a26b 100644 --- a/arch/x86/cpu.c +++ b/arch/x86/cpu.c @@ -125,6 +125,11 @@ 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; +} + static void get_cpu_capabilities(void) { uint32_t eax, unused; @@ -156,10 +161,23 @@ static void get_cpu_capabilities(void) boot_cpu_data.cpuid_leaves[FEAT_8000_0000_EAX] = max_extended_function_idx; + if (max_extended_function_idx < CPUID_EXTEND_ADDRESS_SIZE) { + panic("CPU w/o CPUID.80000008H is not supported"); + } + cpuid(CPUID_EXTEND_FUNCTION_1, &unused, &unused, &boot_cpu_data.cpuid_leaves[FEAT_8000_0001_ECX], &boot_cpu_data.cpuid_leaves[FEAT_8000_0001_EDX]); + cpuid(CPUID_EXTEND_ADDRESS_SIZE, + &eax, &unused, &unused, &unused); + boot_cpu_data.cpuid_leaves[FEAT_8000_0008_EAX] = eax; + /* EAX bits 07-00: #Physical Address Bits + * bits 15-08: #Linear Address Bits + */ + boot_cpu_data.physical_address_mask = + get_address_mask(eax & 0xff); + /* For speculation defence. * The default way is to set IBRS at vmexit and then do IBPB at vcpu * context switch(ibrs_type == IBRS_RAW). @@ -352,6 +370,11 @@ void bsp_boot_init(void) VMX_MACHINE_T_GUEST_SPEC_CTRL_OFFSET, "run_context ia32_spec_ctrl offset not match"); + /* Get CPU capabilities thru CPUID, including the physical address bit + * limit which is required for initializing paging. + */ + get_cpu_capabilities(); + /* Initialize the hypervisor paging */ init_paging(); @@ -368,8 +391,6 @@ void bsp_boot_init(void) set_fs_base(); #endif - get_cpu_capabilities(); - vapic_cap_detect(); cpu_xsave_init(); diff --git a/include/arch/x86/cpu.h b/include/arch/x86/cpu.h index dde5acf99..744da1cc9 100644 --- a/include/arch/x86/cpu.h +++ b/include/arch/x86/cpu.h @@ -228,11 +228,13 @@ enum feature_word { 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 */ FEATURE_WORDS, }; struct cpuinfo_x86 { uint8_t x86, x86_model; + uint64_t physical_address_mask; uint32_t cpuid_leaves[FEATURE_WORDS]; }; diff --git a/include/arch/x86/cpuid.h b/include/arch/x86/cpuid.h index a842fb4b9..be0702cd4 100644 --- a/include/arch/x86/cpuid.h +++ b/include/arch/x86/cpuid.h @@ -115,6 +115,7 @@ #define CPUID_EXTEND_FEATURE 7 #define CPUID_MAX_EXTENDED_FUNCTION 0x80000000 #define CPUID_EXTEND_FUNCTION_1 0x80000001 +#define CPUID_EXTEND_ADDRESS_SIZE 0x80000008 static inline void __cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) diff --git a/include/arch/x86/mmu.h b/include/arch/x86/mmu.h index 08fbb6410..bb340a2ec 100644 --- a/include/arch/x86/mmu.h +++ b/include/arch/x86/mmu.h @@ -157,6 +157,8 @@ #ifndef ASSEMBLER +#include + /* Define cache line size (in bytes) */ #define CACHE_LINE_SIZE 64 @@ -167,7 +169,8 @@ #define IA32E_INDEX_MASK_BITS 9 #define IA32E_NUM_ENTRIES 512 #define IA32E_INDEX_MASK (uint64_t)(IA32E_NUM_ENTRIES - 1) -#define IA32E_REF_MASK 0x000FFFFFFFFFF000 +#define IA32E_REF_MASK \ + (boot_cpu_data.physical_address_mask) #define IA32E_FIRST_BLOCK_INDEX 1 /* Macro to get PML4 index given an address */