Skip to content

Commit 4110e25

Browse files
lifeixjren1
authored andcommitted
Add cpuinfo_x86 to cache cpu capability/feature
Add a global boot_cpu_data to cache common cpu capbility/feature for detect cpu capbility/feature. Signed-off-by: Li, Fei1 <fei1.li@intel.com> Acked-by: Xu, Anthony <anthony.xu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 4839f78 commit 4110e25

File tree

5 files changed

+87
-102
lines changed

5 files changed

+87
-102
lines changed

hypervisor/arch/x86/cpu.c

Lines changed: 65 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -73,39 +73,84 @@ DEFINE_CPU_DATA(int, state);
7373
#define VAPIC_FEATURE_VX2APIC_MODE (1 << 5)
7474

7575
struct cpu_capability {
76-
bool tsc_adjust_supported;
77-
bool ibrs_ibpb_supported;
78-
bool stibp_supported;
7976
uint8_t vapic_features;
80-
bool monitor_supported;
8177
};
8278
static struct cpu_capability cpu_caps;
8379

80+
struct cpuinfo_x86 boot_cpu_data;
81+
8482
static void vapic_cap_detect(void);
85-
static void monitor_cap_detect(void);
8683
static void cpu_set_logical_id(uint32_t logical_id);
8784
static void print_hv_banner(void);
88-
static inline bool get_monitor_cap(void);
8985
int cpu_find_logical_id(uint32_t lapic_id);
9086
#ifndef CONFIG_EFI_STUB
9187
static void start_cpus();
9288
#endif
9389
static void pcpu_sync_sleep(unsigned long *sync, int mask_bit);
9490
int ibrs_type;
95-
static void check_cpu_capability(void)
91+
92+
static inline bool get_tsc_adjust_cap(void)
93+
{
94+
return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EBX] & CPUID_EBX_TSC_ADJ);
95+
}
96+
97+
static inline bool get_ibrs_ibpb_cap(void)
98+
{
99+
return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX] &
100+
CPUID_EDX_IBRS_IBPB);
101+
}
102+
103+
static inline bool get_stibp_cap(void)
104+
{
105+
return !!(boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX] & CPUID_EDX_STIBP);
106+
}
107+
108+
static inline bool get_monitor_cap(void)
109+
{
110+
if (boot_cpu_data.cpuid_leaves[FEAT_1_ECX] & CPUID_ECX_MONITOR) {
111+
/* don't use monitor for CPU (family: 0x6 model: 0x5c)
112+
* in hypervisor, but still expose it to the guests and
113+
* let them handle it correctly
114+
*/
115+
if (boot_cpu_data.x86 != 0x6 || boot_cpu_data.x86_model != 0x5c)
116+
return true;
117+
}
118+
119+
return false;
120+
}
121+
122+
inline bool get_vmx_cap(void)
96123
{
97-
uint32_t eax, ebx, ecx, edx;
124+
return !!(boot_cpu_data.cpuid_leaves[FEAT_1_ECX] & CPUID_ECX_VMX);
125+
}
126+
127+
static void get_cpu_capabilities(void)
128+
{
129+
uint32_t eax, unused;
130+
uint32_t family, model;
131+
132+
cpuid(CPUID_FEATURES, &eax, &unused,
133+
&boot_cpu_data.cpuid_leaves[FEAT_1_ECX],
134+
&boot_cpu_data.cpuid_leaves[FEAT_1_EDX]);
135+
family = (eax >> 8) & 0xff;
136+
if (family == 0xF)
137+
family += (eax >> 20) & 0xff;
138+
boot_cpu_data.x86 = family;
139+
140+
model = (eax >> 4) & 0xf;
141+
if (family >= 0x06)
142+
model += ((eax >> 16) & 0xf) << 4;
143+
boot_cpu_data.x86_model = model;
98144

99-
memset(&cpu_caps, 0, sizeof(struct cpu_capability));
100145

101-
cpuid(CPUID_EXTEND_FEATURE, &eax, &ebx, &ecx, &edx);
146+
cpuid(CPUID_EXTEND_FEATURE, &unused,
147+
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EBX],
148+
&boot_cpu_data.cpuid_leaves[FEAT_7_0_ECX],
149+
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX]);
102150

103-
cpu_caps.tsc_adjust_supported = (ebx & CPUID_EBX_TSC_ADJ) ?
104-
(true) : (false);
105-
cpu_caps.ibrs_ibpb_supported = (edx & CPUID_EDX_IBRS_IBPB) ?
106-
(true) : (false);
107-
cpu_caps.stibp_supported = (edx & CPUID_EDX_STIBP) ?
108-
(true) : (false);
151+
cpuid(CPUID_EXTEND_FUNCTION_1, &unused, &unused,
152+
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_ECX],
153+
&boot_cpu_data.cpuid_leaves[FEAT_8000_0001_EDX]);
109154

110155
/* For speculation defence.
111156
* The default way is to set IBRS at vmexit and then do IBPB at vcpu
@@ -123,29 +168,14 @@ static void check_cpu_capability(void)
123168
* should be set all the time instead of relying on retpoline
124169
*/
125170
#ifndef CONFIG_RETPOLINE
126-
if (cpu_caps.ibrs_ibpb_supported) {
171+
if (get_ibrs_ibpb_cap()) {
127172
ibrs_type = IBRS_RAW;
128-
if (cpu_caps.stibp_supported)
173+
if (get_stibp_cap())
129174
ibrs_type = IBRS_OPT;
130175
}
131176
#endif
132177
}
133178

134-
bool check_tsc_adjust_support(void)
135-
{
136-
return cpu_caps.tsc_adjust_supported;
137-
}
138-
139-
bool check_ibrs_ibpb_support(void)
140-
{
141-
return cpu_caps.ibrs_ibpb_supported;
142-
}
143-
144-
bool check_stibp_support(void)
145-
{
146-
return cpu_caps.stibp_supported;
147-
}
148-
149179
static void alloc_phy_cpu_data(int pcpu_num)
150180
{
151181
phy_cpu_num = pcpu_num;
@@ -313,12 +343,10 @@ void bsp_boot_init(void)
313343
set_fs_base();
314344
#endif
315345

316-
check_cpu_capability();
346+
get_cpu_capabilities();
317347

318348
vapic_cap_detect();
319349

320-
monitor_cap_detect();
321-
322350
/* Set state for this CPU to initializing */
323351
cpu_set_current_state(CPU_BOOT_ID, CPU_STATE_INITIALIZING);
324352

@@ -361,7 +389,7 @@ void bsp_boot_init(void)
361389
pr_dbg("Core %d is up", CPU_BOOT_ID);
362390

363391
/* Warn for security feature not ready */
364-
if (!check_ibrs_ibpb_support() && !check_stibp_support()) {
392+
if (!get_ibrs_ibpb_cap() && !get_stibp_cap()) {
365393
pr_fatal("SECURITY WARNING!!!!!!");
366394
pr_fatal("Please apply the latest CPU uCode patch!");
367395
}
@@ -654,40 +682,3 @@ bool is_vapic_virt_reg_supported(void)
654682
{
655683
return ((cpu_caps.vapic_features & VAPIC_FEATURE_VIRT_REG) != 0);
656684
}
657-
658-
static void monitor_cap_detect(void)
659-
{
660-
uint32_t eax, ebx, ecx, edx;
661-
uint32_t family;
662-
uint32_t model;
663-
664-
/* Run CPUID to determine if MONITOR support available */
665-
cpuid(CPUID_FEATURES, &eax, &ebx, &ecx, &edx);
666-
667-
/* See if MONITOR feature bit is set in ECX */
668-
if (ecx & CPUID_ECX_MONITOR)
669-
cpu_caps.monitor_supported = true;
670-
671-
/* don't use monitor for CPU (family: 0x6 model: 0x5c)
672-
* in hypervisor, but still expose it to the guests and
673-
* let them handle it correctly
674-
*/
675-
family = (eax >> 8) & 0xff;
676-
if (family == 0xF)
677-
family += (eax >> 20) & 0xff;
678-
679-
model = (eax >> 4) & 0xf;
680-
if (family >= 0x06)
681-
model += ((eax >> 16) & 0xf) << 4;
682-
683-
if (cpu_caps.monitor_supported &&
684-
(family == 0x06) &&
685-
(model == 0x5c)) {
686-
cpu_caps.monitor_supported = false;
687-
}
688-
}
689-
690-
static inline bool get_monitor_cap(void)
691-
{
692-
return cpu_caps.monitor_supported;
693-
}

hypervisor/arch/x86/intr_lapic.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,6 @@ send_startup_ipi(enum intr_cpu_startup_shorthand cpu_startup_shorthand,
325325
union apic_icr icr;
326326
uint8_t shorthand;
327327
int status = 0;
328-
uint32_t eax, ebx, ecx, edx;
329-
uint32_t family;
330328

331329
if (cpu_startup_shorthand >= INTR_CPU_STARTUP_UNKNOWN)
332330
status = -EINVAL;
@@ -344,15 +342,6 @@ send_startup_ipi(enum intr_cpu_startup_shorthand cpu_startup_shorthand,
344342
icr.value_32.hi_32 = 0;
345343
}
346344

347-
/*
348-
* family calculation from SDM Vol. 2A
349-
* CPUID with INPUT EAX=01h:Returns Model, Family, Stepping Information
350-
*/
351-
cpuid(CPUID_FEATURES, &eax, &ebx, &ecx, &edx);
352-
family = (eax >> 8) & 0xff;
353-
if (family == 0xF)
354-
family += (eax >> 20) & 0xff;
355-
356345
/* Assert INIT IPI */
357346
write_lapic_reg32(LAPIC_INT_COMMAND_REGISTER_1, icr.value_32.hi_32);
358347
icr.bits.shorthand = shorthand;
@@ -365,7 +354,7 @@ send_startup_ipi(enum intr_cpu_startup_shorthand cpu_startup_shorthand,
365354
/* Give 10ms for INIT sequence to complete for old processors.
366355
* Modern processors (family == 6) don't need to wait here.
367356
*/
368-
if (family != 6)
357+
if (boot_cpu_data.x86 != 6)
369358
mdelay(10);
370359

371360
/* De-assert INIT IPI */
@@ -383,7 +372,7 @@ send_startup_ipi(enum intr_cpu_startup_shorthand cpu_startup_shorthand,
383372
write_lapic_reg32(LAPIC_INT_COMMAND_REGISTER_0, icr.value_32.lo_32);
384373
wait_for_delivery();
385374

386-
if (family == 6) /* 10us is enough for Modern processors */
375+
if (boot_cpu_data.x86 == 6) /* 10us is enough for Modern processors */
387376
udelay(10);
388377
else /* 200us for old processors */
389378
udelay(200);

hypervisor/arch/x86/vmx.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,6 @@ static inline int exec_vmxon(void *addr)
9393
return status;
9494
}
9595

96-
bool get_vmx_cap(void)
97-
{
98-
uint32_t eax, ebx, ecx, edx;
99-
100-
/* Run CPUID to determine if VTX support available */
101-
cpuid(CPUID_FEATURES, &eax, &ebx, &ecx, &edx);
102-
103-
/* See if VMX feature bit is set in ECX */
104-
return !!(ecx & CPUID_ECX_VMX);
105-
}
106-
10796
int exec_vmxon_instr(void)
10897
{
10998
uint64_t tmp64;

hypervisor/include/arch/x86/cpu.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,35 @@ extern int phy_cpu_num;
216216
/* get percpu data for current pcpu */
217217
#define get_cpu_var(name) per_cpu(name, get_cpu_id())
218218

219+
/* CPUID feature words */
220+
enum feature_word {
221+
FEAT_1_ECX, /* CPUID[1].ECX */
222+
FEAT_1_EDX, /* CPUID[1].EDX */
223+
FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */
224+
FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */
225+
FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */
226+
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
227+
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
228+
FEATURE_WORDS,
229+
};
230+
231+
struct cpuinfo_x86 {
232+
uint8_t x86, x86_model;
233+
uint32_t cpuid_leaves[FEATURE_WORDS];
234+
};
235+
236+
extern struct cpuinfo_x86 boot_cpu_data;
237+
219238
/* Function prototypes */
220239
void cpu_halt(uint32_t logical_id);
221240
uint64_t cpu_cycles_per_second(void);
222241
uint64_t tsc_cycles_in_period(uint16_t timer_period_in_us);
223242
void cpu_secondary_reset(void);
224243
int hv_main(int cpu_id);
225-
bool check_tsc_adjust_support(void);
226-
bool check_ibrs_ibpb_support(void);
227-
bool check_stibp_support(void);
228244
bool is_vapic_supported(void);
229245
bool is_vapic_intr_delivery_supported(void);
230246
bool is_vapic_virt_reg_supported(void);
247+
bool get_vmx_cap(void);
231248

232249
/* Read control register */
233250
#define CPU_CR_READ(cr, result_ptr) \

hypervisor/include/arch/x86/vmx.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,6 @@
427427
#define PAGE_PROTECTED_MODE 2
428428

429429
/* External Interfaces */
430-
bool get_vmx_cap(void);
431430
int exec_vmxon_instr(void);
432431
uint64_t exec_vmread(uint32_t field);
433432
uint64_t exec_vmread64(uint32_t field_full);

0 commit comments

Comments
 (0)