上一篇简单说明了QEMU Object Module的注册实现,本篇简单介绍Qemu的启动整个流程。QEMU版本是2.10-rc2 (2017-08-14的版本master分支), 函数的深入细节不涉及~
Startup
QEMU是从vl.c
中的main()
开始执行的↓:
main()
:
1 | 2994 int main(int argc, char **argv, char **envp) |
module_call_init()
:实现如下↓
1 | 90 void module_call_init(module_init_type type) |
在前一篇中已经说明了ModuleTypeList
已经在main()
执行前初始化过了,所以这里QTAILQ_FOREACH
就是在遍历所有的entry并调用真正的init初始化函数。
qemu_init_cpu_list()
, 初始化完Trace后,紧接着初始化cpu_list
, 这个主要是初始化一些锁和同步机制的相关变量。qemu_init_cpu_loop()
:
这个函数我们主要需要注意其中的qemu_init_sigbus
, 其他就是初始化锁之类的
1 |
|
在函数里面初始化了sigbus, 这里sigbus会建立一个sigaction
, sigaction
是vcpu对signal的动作,当config为Linux时,sigbus_handler
会调用kvm的相关函数.
接下来都是些比较简单的初始化,初始化QOM和OPT类型的Module,
之后就是冗长的参数解析和处理过程…
1 | 3746 case QEMU_OPTION_enable_kvm: |
其中有一项就是判断是否开启了kvm, 如果开启了kvm则将accelerator设置为KVM.
当参数这些弄完后,就会开始选择target的machine类型, (机器支持的类型可以通过qemu -machine help
查看到):
1 | # For example, arm64: |
继续就是设置虚拟机的内存大小。
1 | 4123 set_memory_options(&ram_slots, &maxram_size, machine_class); |
再往下就是实际为虚拟机分配内存:
cpu_exec_init_all()
↓
1 | 2760 static void memory_map_init(void) |
往下就是初始化smp、默认的显示器、log、Page页大小、socket, 之后就是和kvm非常相关的配置accelerator了, 与kvm的交互我们放下一篇细说,这里不深入了。
1 | 4424 configure_accelerator(current_machine); |
之后就是读取kernel镜像位置等和启动参数等,然后初始化console、设置默认的启动介质、设置watchdog、其他设备相关的初始化。
最终qemu就会初始化完成虚拟机machine,
1 | 4786 vm_start(); |
之后QEMU会调用vm_start()
所有的vcpu开始被调度,QEMU自身进入main_loop()
, 当我们停止虚拟机的时候,main_loop()
会跳出并回收资源.
1 | 1845 void vm_start(void) |
这就是整个QEMU的执行过程。