上篇博文中我们分析了kvm_cmd_run_init函数,该函数主要是用于创建VM以及创建VCPU的。
这篇博文主要分析kvm_cmd_run_work

kvm_cmd_run_work

为每个vcpu 创建了一个线程,并利用pthread_join阻塞等待vpcu0
所以核心就要看线程函数

kvm_cpu_thread

注意这个current_kvm_cpu变量,这是个被__thread关键字修饰的全局变量,所以虽然是全局变量,但却是每个线程一份。
关键函数是kvm_cpu_start

kvm_cpu_start

将vcpu中的变量初始化,内核使用了ioctrl来真正设置VCPU

核心是kvm_cpu_run

通过ioctrl执行KVM_RUN, 该函数会阻塞一直到guest因某种原因产生来vm_exit 且该exit不能被KVM模块自身解决。

当kvm_cpu_run退出时,KVM模块会将退出的原因以及相关数据放在kvm_run中,回忆一下,kvm_run是通过mmap得到的一块内存区域。
然后根据退出原因进行不同的处理

如果是退出的原因是IO,则进行IO模拟,具体的模拟不是我们现在所关心的,不深入研究。

注意这段代码在switch外面,也就是每次处理完kvm退出事件都要处理coalesced_mmio。

整个kvm_cpu__run和退出事件处理都被包裹在一个while循环中,只要cpu-
>
is_running满足,就会一直进行kvm_cpu__run和退出事件处理。。

kvm_cmd_run_work总结

这篇博文主要分析了kvm_cmd_run_work函数,该函数主要做的事情就是创建vcpu线程,有KVM学习经验的朋友一定知道,一个vcpu线程就代表一个虚拟机CPU。在线程中,主要完成以下
1. 初始化vcpu寄存器
2. 利用ioctrl进入guest
3. 针对KVM_EXIT的原因进行设备模拟
4. 处理coalesced_mmio
5. 回到2

所用到的核心ioctrl主要有
ioctl(vcpu-
>
kvm-
>
sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid)
ioctl(vcpu-
>
vcpu_fd, KVM_SET_CPUID2, kvm_cpuid)
ioctl(vcpu-
>
vcpu_fd, KVM_GET_SREGS, 
&
vcpu-
>
sregs)
ioctl(vcpu-
>
vcpu_fd, KVM_SET_SREGS, 
&
vcpu-
>
sregs)
ioctl(vcpu-
>
vcpu_fd, KVM_SET_REGS, 
&
vcpu-
>
regs) 
ioctl(vcpu-
>
vcpu_fd, KVM_SET_FPU, 
&
vcpu-
>
fpu)
ioctl(vcpu-
>
vcpu_fd, KVM_SET_MSRS, vcpu-
>
msrs)

ioctl(vcpu-
>
vcpu_fd, KVM_RUN, 0)

results matching ""

    No results matching ""