前面文章中我们讲过Qemu、KVM、Guest OS这三种层次以及对应的三种模式,也知道这三种模式之间的配合,下面上一张图回顾一下。
那现在我们就从代码的角度来讲一下这三层之间具体是如何配合的。
前面我们也讲过,首先Qemu层用户发起启动虚拟机命令后会通过ioctl调用进入到kvm内核层,完成相关初始化工作之后就运行虚拟机。
在kvm内核层中,当接收到ioctl的KVM_RUN命令后,实际调用的是kvm_arch_vcpu_ioctl_run()函数。
case KVM_RUN:
r = -EINVAL;
if (arg)
goto out;
r =kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);//
trace_kvm_userspace_exit(vcpu->run->exit_reason,r);
break;
随后依次调用__vcpu_run(),vcpu_enter_guest(),kvm_x86_ops->run(),vmx_vcpu_run(),在vmx_vcpu_run()函数中有一段汇编语言被调用,这段汇编中执行了ASM_VMX_VMLAUNCH或者ASM_VMX_VMRESUME指令进入到客户模式。
asm(
.........//省略部分代码
/* Enter guest mode */
"jne 1f \n\t"
__ex(ASM_VMX_VMLAUNCH)"\n\t"
"jmp 2f \n\t"
"1: "__ex(ASM_VMX_VMRESUME) "\n\t"
........//省略部分代码
);
执行汇编指令进入到客户模式能够实现是因为KVM采用了硬件虚拟化的技术,比如Intel的芯片上提供了硬件支持并提供了相关一系列指令。再具体我也不知道了,查看Intel手册吧。那么进入到客户模式后,客户模式因为一些异常需要退出到KVM内核进行处理,这个是怎么实现的呢?
首先我们要说一下一个与异常处理相关的重要的数据结构VMCS。VMCS是虚拟机控制结