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之间的关系:

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,但反之不成立。

KVM内核文档阅读笔记的更多相关文章

  1. Keras 文档阅读笔记(不定期更新)

    目录 Keras 文档阅读笔记(不定期更新) 模型 Sequential 模型方法 Model 类(函数式 API) 方法 层 关于 Keras 网络层 核心层 卷积层 池化层 循环层 融合层 高级激 ...

  2. Resin文档阅读笔记

    阅读文档对应的版本为Resin4.0,且基本只关注Standard版本的功能. 1.Resin可以注册为服务: To install the service, use C:/> resin-3. ...

  3. rocksdb wiki文档阅读笔记

    由于是英文文档,不做笔记过一阵就忘了,现在把关键点记录到这,开发的时候使用. 具体wiki地址:https://github.com/facebook/rocksdb/wiki 1)Column Fa ...

  4. webDriver文档阅读笔记

    一些雷 浏览器版本和对应的Driver的版本是一一对应的,有时候跑不起来,主要是因为driver和浏览器版本对不上. e.g: chrome和driver版本映射表:https://blog.csdn ...

  5. elasticsearch 文档阅读笔记(三)

    文档 elasticsearch是通过document的形式存储数据的,个人理解文档就是一条数据一个对象 我们添加索引文档中不仅包含了数据还包含了元数据 比如我们为一个数据添加索引 文档中不仅有jso ...

  6. mongodb官网文档阅读笔记:与写性能相关的几个因素

    Indexes 和全部db一样,索引肯定都会引起写性能的下降,mongodb也没啥特别的,相对索引对读性能的提示,这些消耗通常是能够接受的,所以该加入的索引还是要加入.当然须要慎重一些.扯点远的,以前 ...

  7. Mybatis文档阅读笔记(明日继续更新...)

    今天在编写mybatis的mapper.xml时,发现对sql的配置还不是很熟,有很多一坨一坨的东西,其实是可以抽取成服用的.不过良好的组织代码,还是更重要的.

  8. Qt文档阅读笔记-QGraphicsItem::paint中QStyleOptionGraphicsItem *option的进一步认识

    官方解析 painter : 此参数用于绘图;option : 提供了item的风格,比如item的状态,曝光度以及详细的信息:widget : 想画到哪个widget上,如果要画在缓存区上,这个参数 ...

  9. vue文档阅读笔记——计算属性和侦听器

    页面链接:https://cn.vuejs.org/v2/guide/computed.html 注意点 计算属性用于 替代模板内的表达式. 如果计算属性所依赖的属性未更新,会返回自身的缓存. 侦听器 ...

随机推荐

  1. 【一天一道LeetCode】 #3 Longest Substring Without Repeating Characters

    一天一道LeetCode (一)题目 Given a string, find the length of the longest substring without repeating charac ...

  2. jquery.query-*.js 操作url

     做的项目中需要用到通过JS获取GET参数,上网找了一下,找到如下插件: 例如 当前你的URL是: http://www.xxx.com/index.php?test=1&kk=2 如果想 ...

  3. Linux下进程通信方式(简要概述)

    http://blog.sina.com.cn/s/blog_65c209580100u0ee.html (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先 ...

  4. SharePoint&quot;在数据表中编辑&quot;不可用

    报错: 没有安装与 Windows SharePoint Services 兼容的数据表组件 浏览器不支持 ActiveX 控件 或者禁用了对 ActiveX 控件的支持 第一反应,就是什么东西没装, ...

  5. obj-c编程11:内存管理和ARC(自动引用计数)

    乖乖隆地洞,这篇文章内容可是不得了,内存管理哦!首先,这个要是搞不明白,你就等着进程莫名其妙的挂死,或是疯狂申请内存却不释放,结果被OS杀死,不管是"自杀"还是"他杀&q ...

  6. 【模板】最近公共祖先(LCA)

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  7. Android流媒体开发之路二:NDK开发Android端RTMP直播推流程序

    NDK开发Android端RTMP直播推流程序 经过一番折腾,成功把RTMP直播推流代码,通过NDK交叉编译的方式,移植到了Android下,从而实现了Android端采集摄像头和麦克缝数据,然后进行 ...

  8. webservice入门简介

    为了梦想,努力奋斗! 追求卓越,成功就会在不经意间追上你 webservice入门简介 1.什么是webservice? webservice是一种跨编程语言和跨操作系统平台的远程调用技术. 所谓的远 ...

  9. Mybatis 系列2

    上篇文章 写了一个Demo简单体现了一下Mybatis的流程.本次,将简单介绍一下Mybatis的配置文件: 上次例子中,我们以 SqlSessionFactoryBuilder 去创建 SqlSes ...

  10. javaWeb安全漏洞修复总结

    1 Web安全介绍1 2 SQL注入.盲注1 2.1 SQL注入.盲注概述 1 2.2 安全风险及原因 2 2.3 AppScan扫描建议 2 2.4 应用程序解决方案 4 3 会话标识未更新7 3. ...