Skip to content

Commit 1b1f723

Browse files
lifeixjren1
authored andcommitted
hv: add hardware_detect_support to detect which hardware we support
Now just add some basic feature/capability detect (not all). Vapic didn't add here for if we must support vapic then the code which for vapic not supported must remove, like mmio apic r/w. Signed-off-by: Li, Fei1 <fei1.li@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 10c3a98 commit 1b1f723

File tree

6 files changed

+114
-38
lines changed

6 files changed

+114
-38
lines changed

hypervisor/arch/x86/cpu.c

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ static uint64_t get_address_mask(uint8_t limit)
126126
static void get_cpu_capabilities(void)
127127
{
128128
uint32_t eax, unused;
129-
uint32_t max_extended_function_idx;
130129
uint32_t family, model;
131130

132131
cpuid(CPUID_FEATURES, &eax, &unused,
@@ -149,28 +148,28 @@ static void get_cpu_capabilities(void)
149148
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX]);
150149

151150
cpuid(CPUID_MAX_EXTENDED_FUNCTION,
152-
&max_extended_function_idx,
151+
&boot_cpu_data.extended_cpuid_level,
153152
&unused, &unused, &unused);
154-
boot_cpu_data.cpuid_leaves[FEAT_8000_0000_EAX] =
155-
max_extended_function_idx;
156153

157-
if (max_extended_function_idx < CPUID_EXTEND_ADDRESS_SIZE) {
158-
panic("CPU w/o CPUID.80000008H is not supported");
154+
if (boot_cpu_data.extended_cpuid_level >= CPUID_EXTEND_FUNCTION_1)
155+
cpuid(CPUID_EXTEND_FUNCTION_1, &unused, &unused,
156+
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_ECX],
157+
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_EDX]);
158+
159+
if (boot_cpu_data.extended_cpuid_level >= CPUID_EXTEND_ADDRESS_SIZE) {
160+
cpuid(CPUID_EXTEND_ADDRESS_SIZE, &eax,
161+
&boot_cpu_data.cpuid_leaves[FEAT_8000_0008_EBX],
162+
&unused, &unused);
163+
164+
/* EAX bits 07-00: #Physical Address Bits
165+
* bits 15-08: #Linear Address Bits
166+
*/
167+
boot_cpu_data.x86_virt_bits = (eax >> 8) & 0xff;
168+
boot_cpu_data.x86_phys_bits = eax & 0xff;
169+
boot_cpu_data.physical_address_mask =
170+
get_address_mask(boot_cpu_data.x86_phys_bits);
159171
}
160172

161-
cpuid(CPUID_EXTEND_FUNCTION_1, &unused, &unused,
162-
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_ECX],
163-
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_EDX]);
164-
165-
cpuid(CPUID_EXTEND_ADDRESS_SIZE,
166-
&eax, &unused, &unused, &unused);
167-
boot_cpu_data.cpuid_leaves[FEAT_8000_0008_EAX] = eax;
168-
/* EAX bits 07-00: #Physical Address Bits
169-
* bits 15-08: #Linear Address Bits
170-
*/
171-
boot_cpu_data.physical_address_mask =
172-
get_address_mask(eax & 0xff);
173-
174173
/* For speculation defence.
175174
* The default way is to set IBRS at vmexit and then do IBPB at vcpu
176175
* context switch(ibrs_type == IBRS_RAW).
@@ -195,6 +194,64 @@ static void get_cpu_capabilities(void)
195194
#endif
196195
}
197196

197+
/*
198+
* basic hardware capability check
199+
* we should supplement which feature/capability we must support
200+
* here later.
201+
*/
202+
static int hardware_detect_support(void)
203+
{
204+
int ret;
205+
206+
/* Long Mode (x86-64, 64-bit support) */
207+
if (!cpu_has_cap(X86_FEATURE_LM)) {
208+
pr_fatal("%s, LM not supported\n", __func__);
209+
return -ENODEV;
210+
}
211+
if ((boot_cpu_data.x86_phys_bits == 0) ||
212+
(boot_cpu_data.x86_virt_bits == 0)) {
213+
pr_fatal("%s, can't detect Linear/Physical Address size\n",
214+
__func__);
215+
return -ENODEV;
216+
}
217+
218+
/* lapic TSC deadline timer */
219+
if (!cpu_has_cap(X86_FEATURE_TSC_DEADLINE)) {
220+
pr_fatal("%s, TSC deadline not supported\n", __func__);
221+
return -ENODEV;
222+
}
223+
224+
/* Execute Disable */
225+
if (!cpu_has_cap(X86_FEATURE_NX)) {
226+
pr_fatal("%s, NX not supported\n", __func__);
227+
return -ENODEV;
228+
}
229+
230+
/* Supervisor-Mode Execution Prevention */
231+
if (!cpu_has_cap(X86_FEATURE_SMEP)) {
232+
pr_fatal("%s, SMEP not supported\n", __func__);
233+
return -ENODEV;
234+
}
235+
236+
/* Supervisor-Mode Access Prevention */
237+
if (!cpu_has_cap(X86_FEATURE_SMAP)) {
238+
pr_fatal("%s, SMAP not supported\n", __func__);
239+
return -ENODEV;
240+
}
241+
242+
if (!cpu_has_cap(X86_FEATURE_VMX)) {
243+
pr_fatal("%s, vmx not supported\n", __func__);
244+
return -ENODEV;
245+
}
246+
247+
ret = check_vmx_mmu_cap();
248+
if (ret)
249+
return ret;
250+
251+
printf("hardware support HV\n");
252+
return 0;
253+
}
254+
198255
static void alloc_phy_cpu_data(int pcpu_num)
199256
{
200257
phy_cpu_num = pcpu_num;
@@ -458,6 +515,11 @@ void bsp_boot_init(void)
458515

459516
pr_dbg("Core %d is up", CPU_BOOT_ID);
460517

518+
if (hardware_detect_support() != 0) {
519+
pr_fatal("hardware not support!\n");
520+
return;
521+
}
522+
461523
/* Warn for security feature not ready */
462524
if (!cpu_has_cap(X86_FEATURE_IBRS_IBPB) &&
463525
!cpu_has_cap(X86_FEATURE_STIBP)) {
@@ -492,7 +554,10 @@ void bsp_boot_init(void)
492554

493555
ASSERT(get_cpu_id() == CPU_BOOT_ID, "");
494556

495-
init_iommu();
557+
if (init_iommu() != 0) {
558+
pr_fatal("%s, init iommu failed\n", __func__);
559+
return;
560+
}
496561

497562
console_setup_timer();
498563

hypervisor/arch/x86/mmu.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static inline bool cpu_has_vmx_vpid_cap(uint32_t bit_mask)
9494
return !!(vmx_caps.vpid & bit_mask);
9595
}
9696

97-
static void check_mmu_capability(void)
97+
int check_vmx_mmu_cap(void)
9898
{
9999
uint64_t val;
100100

@@ -103,8 +103,17 @@ static void check_mmu_capability(void)
103103
vmx_caps.ept = (uint32_t) val;
104104
vmx_caps.vpid = (uint32_t) (val >> 32);
105105

106-
if (!cpu_has_vmx_ept_cap(VMX_EPT_INVEPT))
107-
panic("invept must be supported");
106+
if (!cpu_has_vmx_ept_cap(VMX_EPT_INVEPT)) {
107+
pr_fatal("%s, invept not supported\n", __func__);
108+
return -ENODEV;
109+
}
110+
111+
if (!cpu_has_vmx_vpid_cap(VMX_VPID_INVVPID)) {
112+
pr_fatal("%s, invvpid not supported\n", __func__);
113+
return -ENODEV;
114+
}
115+
116+
return 0;
108117
}
109118

110119
void invept(struct vcpu *vcpu)
@@ -495,8 +504,6 @@ void init_paging(void)
495504

496505
pr_dbg("HV MMU Initialization");
497506

498-
check_mmu_capability();
499-
500507
/* Allocate memory for Hypervisor PML4 table */
501508
mmu_pml4_addr = alloc_paging_struct();
502509

hypervisor/common/hv_main.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@ int hv_main(int cpu_id)
150150
ASSERT((uint64_t) cpu_id == get_cpu_id(),
151151
"cpu_id/tsc_aux mismatch");
152152

153-
/* Check if virtualization extensions are supported */
154-
ret = cpu_has_cap(X86_FEATURE_VMX);
155-
ASSERT(ret == 1, "VMX not supported!");
156-
157153
/* Enable virtualization extensions */
158154
ret = exec_vmxon_instr();
159155
ASSERT(ret == 0, "Unable to enable VMX!");

hypervisor/include/arch/x86/cpu.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,13 @@ extern uint64_t pcpu_active_bitmap;
225225
/* CPUID feature words */
226226
enum feature_word {
227227
FEAT_1_ECX = 0, /* CPUID[1].ECX */
228-
FEAT_1_EDX = 1, /* CPUID[1].EDX */
229-
FEAT_7_0_EBX = 2, /* CPUID[EAX=7,ECX=0].EBX */
230-
FEAT_7_0_ECX = 3, /* CPUID[EAX=7,ECX=0].ECX */
231-
FEAT_7_0_EDX = 4, /* CPUID[EAX=7,ECX=0].EDX */
232-
FEAT_8000_0000_EAX = 5, /* CPUID[8000_0000].EAX */
233-
FEAT_8000_0001_ECX = 6, /* CPUID[8000_0001].ECX */
234-
FEAT_8000_0001_EDX = 7, /* CPUID[8000_0001].EDX */
235-
FEAT_8000_0008_EAX = 8, /* CPUID[8000_0008].EAX */
228+
FEAT_1_EDX, /* CPUID[1].EDX */
229+
FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */
230+
FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */
231+
FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */
232+
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
233+
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
234+
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EAX */
236235
FEATURE_WORDS,
237236
};
238237

@@ -243,6 +242,9 @@ struct cpu_state_info {
243242

244243
struct cpuinfo_x86 {
245244
uint8_t x86, x86_model;
245+
uint8_t x86_virt_bits;
246+
uint8_t x86_phys_bits;
247+
uint32_t extended_cpuid_level;
246248
uint64_t physical_address_mask;
247249
uint32_t cpuid_leaves[FEATURE_WORDS];
248250
char model_name[64];

hypervisor/include/arch/x86/cpufeatures.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define X86_FEATURE_x2APIC ((FEAT_1_ECX << 5) + 21)
5555
#define X86_FEATURE_MOVBE ((FEAT_1_ECX << 5) + 22)
5656
#define X86_FEATURE_POPCNT ((FEAT_1_ECX << 5) + 23)
57+
#define X86_FEATURE_TSC_DEADLINE ((FEAT_1_ECX << 5) + 24)
5758
#define X86_FEATURE_AES ((FEAT_1_ECX << 5) + 25)
5859
#define X86_FEATURE_XSAVE ((FEAT_1_ECX << 5) + 26)
5960
#define X86_FEATURE_OSXSAVE ((FEAT_1_ECX << 5) + 27)
@@ -93,13 +94,17 @@
9394

9495
/* Intel-defined CPU features, CPUID level 0x00000007 (EBX)*/
9596
#define X86_FEATURE_TSC_ADJ ((FEAT_7_0_EBX << 5) + 1)
97+
#define X86_FEATURE_SMEP ((FEAT_7_0_EBX << 5) + 7)
9698
#define X86_FEATURE_INVPCID ((FEAT_7_0_EBX << 5) + 10)
99+
#define X86_FEATURE_SMAP ((FEAT_7_0_EBX << 5) + 20)
97100

98101
/* Intel-defined CPU features, CPUID level 0x00000007 (EDX)*/
99102
#define X86_FEATURE_IBRS_IBPB ((FEAT_7_0_EDX << 5) + 26)
100103
#define X86_FEATURE_STIBP ((FEAT_7_0_EDX << 5) + 27)
101104

102105
/* Intel-defined CPU features, CPUID level 0x80000001 (EDX)*/
106+
#define X86_FEATURE_NX ((FEAT_8000_0001_EDX << 5) + 20)
103107
#define X86_FEATURE_PAGE1GB ((FEAT_8000_0001_EDX << 5) + 26)
108+
#define X86_FEATURE_LM ((FEAT_8000_0001_EDX << 5) + 29)
104109

105110
#endif /*__X86_CPUFEATURES_H__*/

hypervisor/include/arch/x86/mmu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
#define IA32E_NUM_ENTRIES 512
171171
#define IA32E_INDEX_MASK (uint64_t)(IA32E_NUM_ENTRIES - 1)
172172
#define IA32E_REF_MASK \
173-
(boot_cpu_data.physical_address_mask)
173+
(boot_cpu_data.physical_address_mask)
174174
#define IA32E_FIRST_BLOCK_INDEX 1
175175

176176
/* Macro to get PML4 index given an address */
@@ -326,6 +326,7 @@ int unmap_mem(struct map_params *map_params, void *paddr, void *vaddr,
326326
uint64_t size, uint32_t flags);
327327
int modify_mem(struct map_params *map_params, void *paddr, void *vaddr,
328328
uint64_t size, uint32_t flags);
329+
int check_vmx_mmu_cap(void);
329330
void invept(struct vcpu *vcpu);
330331
bool check_continuous_hpa(struct vm *vm, uint64_t gpa, uint64_t size);
331332
int obtain_last_page_table_entry(struct map_params *map_params,

0 commit comments

Comments
 (0)