在init_primary_cpu
函数里面的init_cpu_pre
填充cpu数据结构,包括:boot_cpu_data、cpu_pm_state_info、e820。
void init_primary_cpu(void)
{
uint64_t rsp;
init_cpu_pre(BOOT_CPU_ID);
/* Switch to run-time stack */
rsp = (uint64_t)(&get_cpu_var(stack)[CONFIG_STACK_SIZE - 1]);
rsp &= ~(CPU_STACK_ALIGN - 1UL);
SWITCH_TO(rsp, init_primary_cpu_post);
}
void init_cpu_pre(uint16_t pcpu_id_args)
{
uint16_t pcpu_id = pcpu_id_args;
if (pcpu_id == BOOT_CPU_ID) {
start_tsc = rdtsc();
/* Clear BSS */
(void)memset(&ld_bss_start, 0U, (size_t)(&ld_bss_end - &ld_bss_start));
/* Get CPU capabilities thru CPUID, including the physical address bit
* limit which is required for initializing paging.
*/
init_cpu_capabilities();
init_cpu_model_name();
load_cpu_state_data();
/* Initialize the hypervisor paging */
init_e820();
init_paging();
if (!cpu_has_cap(X86_FEATURE_X2APIC)) {
panic("x2APIC is not present!");
}
early_init_lapic();
init_percpu_lapic_id();
} else {
/* Switch this CPU to use the same page tables set-up by the
* primary/boot CPU
*/
enable_paging();
early_init_lapic();
pcpu_id = get_cpu_id_from_lapic_id(get_cur_lapic_id());
if (pcpu_id >= CONFIG_MAX_PCPU_NUM) {
panic("Invalid pCPU ID!");
}
}
bitmap_set_nolock(pcpu_id, &pcpu_active_bitmap);
/* Set state for this CPU to initializing */
cpu_set_current_state(pcpu_id, PCPU_STATE_INITIALIZING);
}
void init_cpu_capabilities(void)
{
uint32_t eax, unused;
uint32_t family, model;
cpuid(CPUID_VENDORSTRING,
&boot_cpu_data.cpuid_level,
&unused, &unused, &unused);
cpuid(CPUID_FEATURES, &eax, &unused,
&boot_cpu_data.cpuid_leaves[FEAT_1_ECX],
&boot_cpu_data.cpuid_leaves[FEAT_1_EDX]);
family = (eax >> 8U) & 0xffU;
if (family == 0xFU) {
family += (eax >> 20U) & 0xffU;
}
boot_cpu_data.family = (uint8_t)family;
model = (eax >> 4U) & 0xfU;
if (family >= 0x06U) {
model += ((eax >> 16U) & 0xfU) << 4U;
}
boot_cpu_data.model = (uint8_t)model;
cpuid(CPUID_EXTEND_FEATURE, &unused,
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EBX],
&boot_cpu_data.cpuid_leaves[FEAT_7_0_ECX],
&boot_cpu_data.cpuid_leaves[FEAT_7_0_EDX]);
cpuid(CPUID_MAX_EXTENDED_FUNCTION,
&boot_cpu_data.extended_cpuid_level,
&unused, &unused, &unused);
if (boot_cpu_data.extended_cpuid_level >= CPUID_EXTEND_FUNCTION_1) {
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]);
}
if (boot_cpu_data.extended_cpuid_level >= CPUID_EXTEND_ADDRESS_SIZE) {
cpuid(CPUID_EXTEND_ADDRESS_SIZE, &eax,
&boot_cpu_data.cpuid_leaves[FEAT_8000_0008_EBX],
&unused, &unused);
/* EAX bits 07-00: #Physical Address Bits
* bits 15-08: #Linear Address Bits
*/
boot_cpu_data.virt_bits = (uint8_t)((eax >> 8U) & 0xffU);
boot_cpu_data.phys_bits = (uint8_t)(eax & 0xffU);
boot_cpu_data.physical_address_mask =
get_address_mask(boot_cpu_data.phys_bits);
}
detect_cpu_cap();
}
void init_cpu_model_name(void)
{
cpuid(CPUID_EXTEND_FUNCTION_2,
(uint32_t *)(boot_cpu_data.model_name),
(uint32_t *)(&boot_cpu_data.model_name[4]),
(uint32_t *)(&boot_cpu_data.model_name[8]),
(uint32_t *)(&boot_cpu_data.model_name[12]));
cpuid(CPUID_EXTEND_FUNCTION_3,
(uint32_t *)(&boot_cpu_data.model_name[16]),
(uint32_t *)(&boot_cpu_data.model_name[20]),
(uint32_t *)(&boot_cpu_data.model_name[24]),
(uint32_t *)(&boot_cpu_data.model_name[28]));
cpuid(CPUID_EXTEND_FUNCTION_4,
(uint32_t *)(&boot_cpu_data.model_name[32]),
(uint32_t *)(&boot_cpu_data.model_name[36]),
(uint32_t *)(&boot_cpu_data.model_name[40]),
(uint32_t *)(&boot_cpu_data.model_name[44]));
boot_cpu_data.model_name[48] = '\0';
}
void load_cpu_state_data(void)
{
int32_t tbl_idx;
const struct cpu_state_info *state_info;
struct cpuinfo_x86 *cpu_info = get_cpu_info();
(void)memset(&cpu_pm_state_info, 0U, sizeof(struct cpu_state_info));
tbl_idx = get_state_tbl_idx(cpu_info->model_name);
if (tbl_idx >= 0) {
/* The state table is found. */
state_info = &(cpu_state_tbl + tbl_idx)->state_info;
if ((state_info->px_cnt != 0U) && (state_info->px_data != NULL)) {
if (state_info->px_cnt > MAX_PSTATE) {
cpu_pm_state_info.px_cnt = MAX_PSTATE;
} else {
cpu_pm_state_info.px_cnt = state_info->px_cnt;
}
cpu_pm_state_info.px_data = state_info->px_data;
}
if ((state_info->cx_cnt != 0U) && (state_info->cx_data != NULL)) {
if (state_info->cx_cnt > MAX_CX_ENTRY) {
cpu_pm_state_info.cx_cnt = MAX_CX_ENTRY;
} else {
cpu_pm_state_info.cx_cnt = state_info->cx_cnt;
}
cpu_pm_state_info.cx_data = state_info->cx_data;
}
}
}