设为首页 收藏本站
查看: 1233|回复: 0

[经验分享] KVM内核文档阅读笔记

[复制链接]

尚未签到

发表于 2017-6-24 07:14:00 | 显示全部楼层 |阅读模式
  KVM在内核中有丰富的文档,位置在Documentation/virtual/kvm/。
  00-INDEX:整个目录的索引及介绍文档。
  api.txt:KVM用户空间API,所谓的API主要是通过ioctl来实现的。
  cpuid.txt:KVM的cpuid相关API。
  devices/:各种平台相关设备API。
  hypercalls.txt:KVM的hypercall介绍,介绍了X86和S390的支持的hypercall详细信息。
  locking.txt:介绍了KVM用到的锁、互斥量。
  mmu.txt:介绍了Guest X86 MMU功能。
  msr.txt:X86架构下的MSR用途。
  nested-vmx.txt:使用X86特有的VMX来更简洁高效的运行Guest OS。
  ppc-pv.txt和说90-diag.txt:针对PPC和S390架构的特殊用途,忽略。
  review-checklist.txt:KVM相关patch的review检查列表。
  timekeeping.txt:X86架构下时间虚拟化设备。
关于KVM API定义的文档(api.txt)
1.概述
  KVM API是一系列用来控制VM各方面的ioctl。它包括三个方面:
  System ioctls:这些ioctl用来查询或者设置影响整个KVM子系统的属性。并且有一个system ioctl用来创建VM。
  VM ioctls:这些ioctl用来查询或者设置影响整个VM的属性,其中一个VM ioctl用来创建vcpu。这些VM ioctl只能在用来创建此VM的进程中使用。
  vcpu ioctls:这些ioctl用来查询或者设置能够控制单个vcpu的属性。这些vcpu ioctl只能在创建此vcpu的线程中使用。
  从上面描述,可以清晰看出三者的层级关系:System ioctls(整个KVM子系统) > VM ioctls(单个VM实体) > vcpu ioctls(单个vcpu)
2.文件描述符
  KVM API是围绕文件描述符展开的。从打开/dev/kvm开始,获得操作整个KVM子系统的句柄,这个句柄用来执行System ioctls。基于此System句柄执行KVM_CREATE_VM可以创建一个VM的文件句柄,VM句柄用来执行VM ioctls。基于VM句柄的KVM_CREATE_VCPU用来创建一个vcpu句柄。vcpu句柄执行系列vcpu ioctls用来控制vcpu。
  常见的文件句柄的特性在KVM并不适用,比如fork操作等。KVM里面只支持一个VM一个进程,一个vcpu一个线程。
3.API描述
  每个API,即ioctl都包含一些信息,比如能力、所属架构、类型(System、VM、vcpu)、参数和返回值。这些ioctl非常多,并且庞杂,根据类型分为3类。有一些特殊架构专有的ioctl活在Architecture中列出,如果通用则是all。
  下面重点分析Architecture为all或者x86,Capability为basic类型的ioctl。
System ioctls
API值说明
KVM_GET_API_VERSION目前情况下返回值,只有12。如果返回12,表示所有能力为basic的ioctl都能否使用。其他值是不被允许的。
KVM_CREATE_VM创建一个VM,返回的句柄可以用来控制创建的VM。但此时VM还没有vcpu和memory。
KVM_GET_MSR_INDEX_LIST返回Guest支持的MSRs
KVM_CHECK_EXTENSION
KVM_GET_VCPU_MMAP_SIZE返回运行vcpu的KVM_RUN使用的共享Memory Region大小。
VM ioctls
API值说明
KVM_CAP_CHECK_EXTENSION_VM
KVM_CREATE_VCPU在VM里添加一个vcpu,但是总数不会超过max_cpus。vcpu的id在[0, max_vcpu_id)之间。
KVM_GET_DIRTY_LOG
KVM_SET_MEMORY_ALIAS
KVM_CREATE_IRQCHIP
KVM_GET_IRQCHIP
KVM_SET_IRQCHIP
KVM_GET_CLOCK
KVM_SET_CLOCK
KVM_GET_VCPU_EVENTS
KVM_SET_VCPU_EVENTS
KVM_SET_USER_MEMORY_REGION
KVM_CAP_ENABLE_CAP_VM不是所有的能力都被默认打开,可以使用此ioctl来扩展。
vcpu ioctls
API值说明
KVM_RUN用于运行一个Guest的vcpu。
KVM_GET_REGS返回vcpu的通用寄存器值,通过struct kvm_regs结构体返回,根据不同架构有所不同。
KVM_SET_REGS设置vcpu的通用寄存器。
KVM_GET_SREGS读取不同架构vcpu的特殊寄存器。
KVM_SET_SREGS设置不同架构vcpu的特殊寄存器。
KVM_TRANSLATE
KVM_INTERRUPT
KVM_DEBUG_GUEST
KVM_GET_MSRS
KVM_SET_MSRS
KVM_SET_CPUID
KVM_SET_SIGNAL_MASK
KVM_GET_FPU获取vcpu的FPU状态。
KVM_SET_FPU设置vcpu的FPU状态。
KVM_ENABLE_CAP不是所有的能力都被默认打开,可以使用此ioctl来扩展。

  下面一段代码很好的诠释了KVM->VM->vcpu之间的关系:
DSC0000.png

  int ret, kvmfd = -1, vmfd = -1, cpufd = -1;
  kvmfd = qemu_open("/dev/kvm", O_RDWR);
if (kvmfd < 0) {
    goto err;
}
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
if (vmfd < 0) {
    goto err;
}
cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
if (cpufd < 0) {
    goto err;
}
  4.kvm_run结构体
KVM Hypercall(hypercalls.txt)
  这里重点关注x86架构下的Hypercall。
  KVM hypercall最多支持四个参数,通过rbx、rcx、rdx、rsi。Hypercall调用号通过rax传递,返回时rax存放返回值。
  一般情况下,其他寄存器不参与Hypercall。
  适用于X86架构的Hypercall有三个:KVM_HC_VAPIC_POLL_IRQ、KVM_HC_MMU_OP、KVM_HC_KICK_CPU。
  Hypercall的定义在include/uapi/linux/kvm_para.h中:
  #define KVM_HC_VAPIC_POLL_IRQ        1
#define KVM_HC_MMU_OP            2
#define KVM_HC_FEATURES            3
#define KVM_HC_PPC_MAP_MAGIC_PAGE    4
#define KVM_HC_KICK_CPU            5
#define KVM_HC_MIPS_GET_CLOCK_FREQ    6
#define KVM_HC_MIPS_EXIT_VM        7
#define KVM_HC_MIPS_CONSOLE_OUTPUT    8
  KVM_HC_VAPIC_POLL_IRQ:Host检查关起的中断。
  KVM_HC_MMU_OP:支持MMU操作,比如PTE、flushing TLB、release PT。
  KVM_HC_KICK_CPU:唤醒HLT状态下的vcpu。如果Guest内核模式下一个vcpu等待时间超时而执行HLT指令,另一个同Guest下vcpu可以通过触发KVM_HC_KICK_CPU来唤醒。
  这些Hypercall都在kvm_emulate_hypercall中处理:
  int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
    unsigned long nr, a0, a1, a2, a3, ret;
    int op_64_bit, r = 1;
  kvm_x86_ops->skip_emulated_instruction(vcpu);
  if (kvm_hv_hypercall_enabled(vcpu->kvm))
        return kvm_hv_hypercall(vcpu);
  nr = kvm_register_read(vcpu, VCPU_REGS_RAX);  Hypercall调用号
    a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);  依次是四个参数
    a1 = kvm_register_read(vcpu, VCPU_REGS_RCX);
    a2 = kvm_register_read(vcpu, VCPU_REGS_RDX);
    a3 = kvm_register_read(vcpu, VCPU_REGS_RSI);
  …
  switch (nr) {
    case KVM_HC_VAPIC_POLL_IRQ:
        ret = 0;
        break;
    case KVM_HC_KICK_CPU:
        kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);  真正用到的也就是唤醒vcpu,a1表示vcpu的apicid。
        ret = 0;
        break;
    default:
        ret = -KVM_ENOSYS;
        break;
    }
out:
    if (!op_64_bit)
        ret = (u32)ret;
    kvm_register_write(vcpu, VCPU_REGS_RAX, ret);  返回值放在RAX中。
    ++vcpu->stat.hypercalls;
    return r;
}
  支持Guest的MMU功能(mmu.txt)
  X86 KVM的shadow MMU功能提供一个标准的MMU功能给Guest,将Guest的物理地址转换成Host物理地址。
  关于Nested VMX是一种嵌套式虚拟功能,能够使一台虚拟机具有物理机CPU特性,支持VMX/SVM硬件虚拟化。参考《Nested VMX》。这样虚拟机可以使自己成为一个Hypervisors,并在其上安装虚拟机。
  所谓Nested就是运行在Guest上的嵌套Guest,Guest作为Hypervisor。
术语

解释

  PFN
  Host page frame number
  HPA
  Host physical address
  HVA
  Host virtual address
  GFN
  Guest page frame number
  GPA
  Guest physical address
  GVA
  Guest virtual address
  NGPA
  Nested guest physical address
  NGVA
  Nested guest virtual address
  PTE
  Page table entry
  GPTE
  Guest page table entry
  SPTE
  Shadow page table entry
  TDP
  Two dimensional paging
  此处KVM MMU功能主要工作就是配置处理器的MMU以达到将Guest地址转变到Host。有下面三种不同的转变需求:
  -当Guest关闭分页功能时,将Guest物理地址转变成Host物理地址。GPA->HPA
  -当Guesst使能分页功能时,将Guest虚拟地址,转变成Guest物理地址,进而Host物理地址。GVA->GPA->HPA
  -当Guest又虚拟化一个嵌套Guest时,将嵌套的Guest虚拟地址转变成嵌套的物理地址,进而Guest物理地址,最后是Host物理地址。NGVA->NGPA->GPA-HPA
  GPA是运行KVM进程的用户地址空间的一部分。用户空间定义了Guest地址到用户空间地址的转变(GPA->HVA)。两个不同的GPA可以映射到一个HVA,但反之不成立。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-387445-1-1.html 上篇帖子: CentOS 6.5安装KVM实践 下篇帖子: 管理KVM虚拟机(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表