首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[kvm][qemu]CPU虚拟化

[kvm][qemu]CPU虚拟化

作者头像
皮振伟
发布2018-04-09 11:14:31
2.4K0
发布2018-04-09 11:14:31
举报
文章被收录于专栏:皮振伟的专栏皮振伟的专栏

前言: 这里作者再次自不量力了,以一点微末的道行分析一下KVM的CPU虚拟化部分的代码。 分析: 1,分析具体代码逻辑之前,可以先使用strace大致看一下qemu启动的时候,和kernel的交互。 在正常启动qemu的命令之前加入strace即可:strace qemu-system-x86_64 -enable-kvm -m 2048 -drive if=virtio,file=/home/ubuntu-server-1604.qcow2,cache=none -redir :8090::80 -redir :8022::22 -cpu qemu64,+vmx -vnc :0 -smp 2

通过这段trace可以大致看出来,qemu首先打开/dev/kvm这个device,然后通过ioctl和它交互。 重点关注KVM_CREATE_VM,又创建出来了新的fd。 查看qemu打开的所有文件(包括设备,Linux上一切皆文件),可以使用lsof -p PID,或者ls -al /proc/PID/fd:

结合上述的strace,不难发现,先打开/dev/kvm作为文件描述符9,再通过ioctl 9得到文件描述符10,即anon_inode:kvm-vm;同理继续可以分析出来其他的fd。大致可以简单了解逻辑。 2,/dev/kvm 先来分析一下/dev/kvm的创建过程。代码在linux-4.0.4/virt/kvm目录。 在kvm_main.c中,kvm_init函数中会注册一个device(by misc_register(&kvm_dev)),

kvm_dev的名字就是“kvm”,即之前看到的/dev/kvm设备,KVM_MINOR是宏定义232,通过命令可以验证:file /dev/kvm /dev/kvm: character special (10/232) /dev/kvm的ioctl就是通过kvm_chardev_ops.kvm_dev_ioctl函数。 3,KVM_CREATE_VM 从kvm_dev_ioctl中选择KVM_CREATE_VM分支,即kvm_dev_ioctl_create_vm函数:

kvm_create_vm函数主要用来创建并初始化kvm数据结构,包括lock,memslot,mmu notifier等,并把数据结构加入到vm_list(双链表,用来保存本机上KVM创建的的所有vm)中; coalesced mmio不在这里分析。 anon_inode_getfd函数创建一个名为“kvm-vm”的一个新的匿名文件,即上文的文件描述符为10的anon_inode:kvm-vm,并注册这个文件的file operation-----kvm_vm_fops。 4,create vcpu 通过函数kvm_vm_fops .kvm_vm_ioctl的KVM_CREATE_VCPU分支----kvm_vm_ioctl_create_vcpu。

首先创建kvm_vcpu类型的vcpu数据结构。intel架构下,会使用linux-4.0.4/arch/x86/kvm/vmx.c中的vmx_create_vcpu函数。函数中初始化vcpu,并分配vmx数据结构,同时申请vmcs(vmcs很复杂,需要参考文档:https://software.intel.com/en-us/articles/intel-sdm,3B部分介绍intel的VMX)。 然后添加vcpu到vm中。当然,这里会根据id检查是否已经添加过了。 最后,还是会通过create_vcpu_fd函数创建匿名文件kvm-vcpu,即上文的anon_inode:kvm-vcpu。同理,用户进程可以通过这个匿名文件的描述符进行ioctl操作。 5,vcpu run anon_inode:kvm-vcpu提供了kvm_vcpu_ioctl函数进行vcpu的ioctl。 当用户进程请求了KVM_RUN之后,会通过这样的路径让CPU进入vm模式: kvm_arch_vcpu_ioctl_run(linux-4.0.4/arch/x86/kvm/x86.c)->__vcpu_run->vcpu_enter_guest->vmx_vcpu_run(linux-4.0.4/arch/x86/kvm/vmx.c) cpu进入到了vm模式,就在跑虚拟机中的代码。在虚拟机中,这就是一个cpu。如果遇到异常,比如说Guest使用了IO指令访问,那么就会让cpu退出vm模式,并把异常原因交给qemu来处理;如果qemu进程发生了缺页中断,那么host就需要给qemu进程分配page,分配之后,qemu进程继续跑,不需要qemu进程处理什么,当然,Guest中也不感知。 6,qemu KVM_CREATE_VM qemu中,init machine中,因为选择了kvm硬件加速,所以会通过kvm_init函数创建kvm的vm。下图是backtrace。

7,qemu KVM_CREATE_VCPU & KVM_RUN

pthread_create中会调用clone创建新的线程,由上图的backtrace可见,每一个vcpu都对应一个用户态的线程。用户态的多线程同时在跑,对应的就是vm中的多核心在跑。

创建完vcpu,qemu通过kvm_cpu_exec,进而进入vm模式(by kvm_vcpu_ioctl(cpu, KVM_RUN, 0))。 8,vcpu exit 如上文所说,vcpu如果遇到异常,且是需要qemu来处理的情况下,那么将会退出vm模式。qemu继续执行kvm_cpu_exec函数。 qemu从kernel的kvm中获取到exit reason,然后做出相应的逻辑:

例如,Guest中访问使用了IO指令导致了退出了vm模式,那么qemu会调用kvm_handle_io。处理完成后,继续进入vm模式执行。 后记: 水平有限,CPU过于相关的,包括一些汇编代码,都需要对照intel的开发文档来分析。这里只对整体逻辑做了简单分析。 惭愧,惭愧~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AlwaysGeek 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档