kvmtool正式运行kvm
前言
在上一篇文章中介绍了 kvmtool 的 run 命令的初始化流程,其中涉及多个子模块的初始化,包括 cpu、内存已经外设等。这些都是正式启动系统构建的虚拟硬件环境,而这篇文章将介绍基于之前初始化的硬件环境,运行一个虚拟系统。
run 命令的执行流程
接着上一篇的分析:
int kvm_cmd_run(int argc, const char **argv, const char *prefix)
{
int ret = -EFAULT;
struct kvm *kvm;
kvm = kvm_cmd_run_init(argc, argv);
if (IS_ERR(kvm))
return PTR_ERR(kvm);
ret = kvm_cmd_run_work(kvm);
kvm_cmd_run_exit(kvm, ret);
return ret;
}
跟着 kvm_cmd_run_work
继续运行:
static int kvm_cmd_run_work(struct kvm *kvm)
{
int i;
for (i = 0; i < kvm->nrcpus; i++) {
if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0)
die("unable to create KVM VCPU thread");
}
/* Only VCPU #0 is going to exit by itself when shutting down */
if (pthread_join(kvm->cpus[0]->thread, NULL) != 0)
die("unable to join with vcpu 0");
return kvm_cpu__exit(kvm);
}
可以看到,kvmtool 基于之前构建的cpu环境,为每一个虚拟 cpu 创建一个 vcpu 线程用于启动虚拟机。
启动 vcpu 线程
上面的 kvm_cpu_thrad
做的是就一件事,即 kvm_cpu__start
。
int kvm_cpu__start(struct kvm_cpu *cpu)
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
signal(SIGKVMEXIT, kvm_cpu_signal_handler);
signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
signal(SIGKVMTASK, kvm_cpu_signal_handler);
kvm_cpu__reset_vcpu(cpu);
if (cpu->kvm->cfg.single_step)
kvm_cpu__enable_singlestep(cpu);
while (cpu->is_running) {
if (cpu->needs_nmi) {
kvm_cpu__arch_nmi(cpu);
cpu->needs_nmi = 0;
}
if (cpu->task)
kvm_cpu__run_task(cpu);
kvm_cpu__run(cpu);
...
}
首先是设置了信号处理函数,接着复位 vcpu 的上下文、设置 nmi 以及运行前置 task, 最后通过 kvm_cpu__run 进入linux 的 kvm 子系统运行虚拟机。
其中复位 vcpu 的上下文主要是设置 vcpu 的段选择子、ip、sp 等寄存器,其中段选择子指向启动扇区的某个地址,而这个地址在初始化的时候就设置为虚拟机的起始地址即可。
KVM_RUN
通过 kvm 提供的 KVM_RUN 命令运行虚拟机:
void kvm_cpu__run(struct kvm_cpu *vcpu)
{
int err;
if (!vcpu->is_running)
return;
err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
if (err < 0 && (errno != EINTR && errno != EAGAIN))
die_perror("KVM_RUN failed");
}
结束语
可以看到,其实启动虚拟机的步骤并不复杂,复杂的是构建一个虚拟的硬件环境。启动虚拟机之后基本就不用 kvmtool 管了,kvm 子系统会维护虚拟机的运行。只有当 虚拟机出错退出时,才有可能需要 kvmtool 进行处理,这部分内容在之后的文章再聊。
现在我们基本上对 kvmtool 启动一个虚拟机的流程有了大致的了解,接下来的文章将深入到 kvm 子系统的内部吗,看看 kvm 在创建虚拟机的时候做了什么事,在运行虚拟机的时候又做了什么事,虚拟机异常退出时又需要做什么继续让虚拟机继续运行。
kvm 系列
00 : kvmtool 启动 linux 内核
01 : 制作根文件系统
02 : kvmtool 开启网络功能
03 : kvmtool 数据结构
04 : kvmtool 数据结构