acrn hypervisor源码分析 - 第四节

init_primary_cpu函数里面的init_cpu_pre填充cpu数据结构,包括:boot_cpu_data、cpu_pm_state_info、e820。

  1. 初始化primary cpu。
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);
}
  1. BOOT_CPU_ID是多核处理器上电后第一个运行的cpu。rdtsc是将处理器的时间标签计数器的当前值加载到 EDX:EAX 寄存器中,最后赋值给start_tsc。BSS段通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0。这里手动将其清0。
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);
}
  1. cpuid是获取cpu的信息,通过cpuid汇编指令实现;
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();
}
  1. 应该是获取cpu架构;
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';
}
  1. 暂不清楚
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;
		}
	}
}

你可能感兴趣的:(汇编,acrn,hypervisor)