首页 理论教育 私有云架构设计与实践:QEMU/KVM简介

私有云架构设计与实践:QEMU/KVM简介

时间:2023-10-28 理论教育 版权反馈
【摘要】:虽然VT原生支持带页面交换功能的16位保护模式,但对于型号较老的CPU而言,QEMU需要首先依靠纯软件实现实模式,待vCPU进入保护模式后再将虚拟机的执行转交给KVM处理。如果主机使用的是Westmere及其以后的处理器,且内核版本不低于2.6.32的系统,QEMU则可直接借助KVM进入vCPU的实模式和无内存页交换的保护模式。以上即是使用KVM驱动进行x86模拟的基本过程了,QEMU和KVM的组合便是在此基础上添加各种外设,以提供操作系统必需的硬件环境。

私有云架构设计与实践:QEMU/KVM简介

QEMU有两种运行模式,分别是用户模式和系统模式。用户模式下的QEMU在交叉编译环境下使用较多,值得一提的是在Linux下执行Windows程序的Wine(Wine Is Not a Emulator)也有类似功能,而后者属于包装了许多Windows系统库文件的库虚拟化;系统模式下QEMU可以模拟一个完整的系统硬件环境,甚至单独一个外设,所有执行(execution)操作全部经由软件模拟,主机硬件(Intel-VT/AMD-V)不参与辅助加速;如果服务器CPU支持硬件虚拟化,则可以使用KVM或者Xen驱动加速,此时QEMU负责模拟各种硬件外设,但虚拟机的指令执行操作由KVM或Xen驱动模块进行处理,普通系统模式与KVM系统模式如图4-1所示。

图4-1 系统模式与KVM主机模式

当QEMU运行在无硬件虚拟化加速的系统模式时,它主要依靠二进制转译(Binary Translation)技术将虚拟机CPU指令转译成主机CPU指令。自QEMU版本0.10后,引入了TCG(Tiny Code Generator)实现二进制转译。TCG在转移时包含前端操作与后端操作,其中前端操作是封装了模拟目标CPU寄存器与运算操作的函数,它将虚拟机指令转换成QEMU指令,后端操作负责将QEMU指令转换成主机CPU指令。

1.KVM API示例

KVM虚拟机并不一定要运行一个操作系统,也可以裸跑一段代码。通过KVM API,被隔离在沙箱(sandbox,又译作沙盘、沙盒,一般表示拥有基础资源且可随意改变的隔离环境)中的程序可以访问沙箱中的任意接口。为使读者对KVM的原理和过程有个大致印象,笔者将在支持Intel VT的x86主机系统中直接操作KVM API来创建一个的虚拟机,并在实模式下执行一段代码(计算“3+3”)。KVM API文档可参考https://kernel.org/doc/Documentation/virtual/kvm/,KVM测试工具可以使用novm或者kvmtool。

先将要执行的汇编转化为机器码,以便交由vCPU执行。由于这段代码是16位实模式,在支持VT的主机中运行它需要CPU支持“unrestricted guest”特性。虽然VT原生支持带页面交换功能的16位保护模式,但对于型号较老的CPU而言,QEMU需要首先依靠纯软件实现实模式,待vCPU进入保护模式后再将虚拟机的执行转交给KVM处理。如果主机使用的是Westmere及其以后的处理器(打开EPT),且内核版本不低于2.6.32的系统,QEMU则可直接借助KVM进入vCPU的实模式和无内存页交换的保护模式。

接下来的初始化操作,我们需要将这些机器码拷贝至虚拟机内存的第二页(避免与中断地址冲突),寄存器al、bl分别赋值为3,指令指针(ip)指向内存第二页开始处(0x1000),运行后将结果输出至0x3f8的模拟串口

准备工作完成后,我们开始进行模拟。首先需要打开/dev/kvm设备,此操作需要对kvm拥有可读写权限,并指定在执行exec后关闭描述符。

然后确定KVM API版本号是12,否则退出。

由于我们需要设置KVM虚拟机的内存,所以我们需要在此检查这个系统中的KVM是否支持此特性。

开始创建虚拟机,机器类型为默认。

然后给虚拟机分配一页(4 KB)内存,并将上述程序的机器码拷贝进去。

内存分配完成以后,我们需要设置虚拟机的内存拓扑

给虚拟机添加一个序号为0的vCPU。

每一个vCPU具有kvm_run结构体,以用于在内核空间和用户空间之间交换vCPU状态信息,在模拟设备意外停止工作时还可以存储设备dump信息。(www.xing528.com)

设置寄存器初始值。vCPU结构中包括标准寄存器(kvm_regs)和特殊寄存器(kvm_sregs)两种数据结构。标准寄存器包括通用集群器、指令指针和CPU标志,特殊寄存器中则主要是段寄存器和控制寄存器等,且特殊寄存器中的每个段都有完整的段描述符结构体。通用寄存器中我们只需要初始化al、bl、指令指针寄存器、标志寄存器,而特殊寄存器中我们需要将代码段寄存器的基地址base和selector(全局描述符GDT的偏移量)。

寄存器初始化完成,代码也已经载入内存,接下来开始进行模拟运算,即向vCPU循环发送KVM_RUN命令。

代码运行完之后遇到halt指令,模拟即停止(EXIT),我们需要对这个过程的停止返回值进行处理。

将以上文件保存至kvm_test.c,然后编译运行得到代码执行结果。

以上即是使用KVM驱动进行x86模拟的基本过程了,QEMU和KVM的组合便是在此基础上添加各种外设,以提供操作系统必需的硬件环境。

2.QEMU用户模式示例

在用户模式下,我们可以运行为任意CPU架构编译的二进制文件,对于非静态二进制我们需要安装对应的动态链接库文件。接下来我们以arm的交叉编译示例。

3.QEMU系统模式示例

当QEMU运行在系统模式时,它会模拟出包含CPU、内存等各种外设在内的指定型号机器模型,除此之外也有很多与主机、客户端的交互选项,比如设备重定向、内存气球、spice USB-Redir等。

每个选项的具体含义及格式请使用“man qemu-kvm”查看,每个设备的参数列表查询可以在设备选项后加“?”,形如“qemu-kvm-cpu?”。下面是一个比较精简的QEMU系统模式命令示例,我们逐行进行讲解。

系统模式下的QEMU是KVM虚拟化技术的核心之一,深入了解其参数、选择合适的设备,将会对我们的虚拟机调试工作带来极大的便利。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈