X86分区虚拟化 - 多核初始化启动和GUEST OS初始化启动

时间:2022-09-04 17:50:26
最近在研究硬件分区虚拟化的模型实现方法,总结了一下,共享出来。需要先了解芯片的启动流程,以便加入Thin Hypervisor代码。下面以志强芯片为例,描述X86初始化流程
  • 多核初始化协议定义了两类处理器:bootstrap processor(BSP) 和 application processors (APs). 上电或者MP复位后,系统硬件动态选择一个作为BSP,其余的作为APs. 
  • BSP的IA32_APIC_BASE中的BSP flag将被置位,其他的处理器中该位将被清空.上电或者复位后,AP等待BSP的SIPI(startup signal)信号,接收到SIPI信号后,AP执行BIOS中的AP配置代码,然后进入halt状态.
  • 对于支持Hyper_Threading的处理器,每个逻辑处理器将被作为一个单独的处理器对待,都会有一个唯一的APIC ID.

志强处理器MP初始化协议算法:
X86分区虚拟化 - 多核初始化启动和GUEST OS初始化启动 
1. 基于系统拓扑结构,每个逻辑处理器将分配一个8位的APIC ID.这个ID将被写入到每个处理器的local APIC ID寄存器中BSP被确定后,BSP创建一个ACPI的table和一个MP的table并将自己的初始APIC ID加到这些表中
2. 在boot-strap流程的最后,BSP设置处理器数目为1,并开始广播SIPI. 这里,SIPI包含BIOS AP初始化代码的向量
3. AP收到SIPI后,第一个得到信号量的AP开始执行初始化代码,将自己的APIC ID加到ACPI和MP的表里面,并将处理器数目加1.完成初始化后,AP执行一个CLI指令并halt自己
4. 所有的AP都初始化完后,BSP得到一个系统处理器的个数,完成boot-strap代码,进入OS.
5. 此时AP保持halt状态,等待INITs, NMIs和SMIs.

BSP初始化过程
X86分区虚拟化 - 多核初始化启动和GUEST OS初始化启动 

1. 初始化memory
2. Load microcode到处理器
3. 初始化内存范围寄存器(MTRRs)
4. enable cache
5. 确定BSP是否是"GenuineIntel"
6. 执行CPUID,保存CPU信息为将来使用
7. load AP的启动代码到低1M的一个4K的页里
8. 切换到保护模式
9. 转换4K的页基址为一个8位的向量. 例如
    0x000BD000H --> 0xBDH
10.设置APIC的SVR的bit8来enable local APIC
11.建立错误处理handler
12.初始化锁信号量
13.探测系统中的AP, 方法如下:
   - 设置处理器COUNT为1
   - 启动一个timer,BSP开始等待
   - 此时AP开始初始化,并将COUNT加1
   - timer到期,BSP检查COUNT,如果没有增加,就表示系统中没有AP.
14. 等timer中断,检查COUNT并建立处理器数目

AP初始化
X86分区虚拟化 - 多核初始化启动和GUEST OS初始化启动 

1. 获取信号量,开始初始化
2. load microcode到处理器
3. 初始化内存范围寄存器(MTRRs)
4. enable cache
5. 检查AP是否是"GenuineIntel"
6. 保存CPUID信息,为将来使用
7. 切换到保护模式
8. 配置AP的共存内存接口执行环境
9. 将处理器个数加1
10.释放信号量
11. 执行CLI并且进入halt状态
12.等待INIT IPI

GUEST OS初始化启动流程 X86分区虚拟化 - 多核初始化启动和GUEST OS初始化启动