arm体系结构的入口点为virt/kvm/arm/arm.c文件中的函数arm_init。函数arm_init直接调用virt/kvm/kvm_main.c文件的统一初始化函数kvm_init。
体系结构实现的函数kvm_arch_init,在virt/kvm/arm/arm.c文件中。
1)函数is_hyp_mode_available用于判断HYP模式是否有效。
数组__boot_cpu_mode[2]记录了CPUs启动的模式,正确的bootloader必须把所有CPUs启动到相同的模式上,即数组的两个元素必须一样,如果两者不相等,表明bootloader可能出错了。第一个元素的静态初始化值是BOOT_CPU_MODE_EL2,第二个元素的静态初始化值是BOOT_CPU_MODE_EL1。在arch/arm64/kernel/head.S文件中的汇编函数el2_setup动态识别本地cpu的模式,w0记录本地cpu模式;然后如果本地cpu模式是BOOT_CPU_MODE_EL2,汇编函数setup_cpu_boot_mode_flag就将第二个元素修改为BOOT_CPU_MODE_EL2。
2)函数kvm_arch_check_sve_has_vhe,用于判断sve系统是否支持vhe;要求sve系统必须支持vhe。
函数system_supports_sve用于判断与sve相关的内核配置参数和CPU特征是否满足。如果内核配置参数和CPU特征表明支持sve,那么就需要就需要调用函数has_vhe。也就是说,如果非sve系统可以不需要vhe支持。 内核配置参数为CONFIG_ARM64_SVE。
3) 每个处理器都要调用一次函数check_kvm_target_cpu。
函数check_kvm_target_cpu主要调用函数kvm_target_cpu,该函数主要通过read_cpuid_implementor获取CPU厂商号,通过read_cpuid_part_number获取CPU型号。函数kvm_target_cpu最终返回目标CPU类型编号,无论如何都会返回一个默认的CPU类型编号GENERIC_V8。
4)函数init_common_resource,设置虚拟机标识符VMID的位长度。函数kvm_get_vmid_bits直接返回8,给全局变量kvm_vmid_bits。
5)函数is_kernel_in_hyp_mode和函数init_hyp_mode。
函数is_kernel_in_hyp_mode直接读取CurrentEL寄存器,判断是否为CurrentEL_EL2。如果当前权限级已经是EL2,表示内核已经处于VHE模式。
如果当前权限级还不是EL2,即内核处于hyp模式,就调用函数init_hyp_mode。函数init_hyp_mode主要是初始化所有在线CPU上的hyp模式。
函数init_hyp_mode首先调用函数kvm_mmu_init,分配和初始化HYP的启动代码段PGD页表。物理地址范围[hyp_idmap_start, hyp_idmap_end]为HYP代码段,hyp_idmap_vector是HYP中断向量表起始物理地址。函数__kvm_cpu_uses_extended_idmap,用于判断是否内核配置的页表级别是否满足硬件要求,如果满足直接调用函数kvm_map_idmap_text创建映射HYP代码段的页表;否则要申请更多的页,来创建HYP代码段的页表。
函数init_hyp_mode为每个CPU分配一个堆栈页,定义给PER_CPU变量kvm_arm_hyp_stack_page。(建议:PER_CPU变量是否可以按照NUMA方式来分配内存?)
函数init_hyp_mode为代码段,数据段和BSS段建立映射。这个代码段、数据段和BSS段主要是用于host主机操作系统调用。
函数init_hyp_mode为每个CPU堆栈页建立映射。
函数init_hyp_mode为每个CPU的kvm处理器上下文环境建立映射。DEFINE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
struct kvm_cpu_context {
struct kvm_regs gp_regs;
union {
u64 sys_regs[NR_SYS_REGS];
u32 copro[NR_COPRO_REGS];
};
struct kvm_vcpu *__hyp_running_vcpu;
};
函数init_hyp_mode最后调用函数hyp_map_aux_data为辅助数据创建映射,例如ssbd的回调需要的数据。
6)函数init_subsystems
每个CPU调用_kvm_arch_hardware_enable,进入EL2权限级。
调用函数hyp_cpu_pm_init,注册低功耗通告函数。
调用函数kvm_vgic_hyp_init,进行虚拟中断控制器vgic相关初始化。
调用函数kvm_timer_hyp_init,进行虚拟定时器相关初始化。
调用函数kvm_perf_init,进行perf相关的初始化。
调用函数kvm_coproc_table_init,进行XXX初始化。
每个CPU调用_kvm_arch_hardware_disable,退出EL2权限级。
247

被折叠的 条评论
为什么被折叠?



