QEMU 之 CPU 虚拟化(一):CPU 虚拟化介绍
最近在阅读李强编著的《QEMU/KVM 源码解析与应用》这本书来学习 Linux 内核虚拟化相关知识,通过读书笔记的方式来提炼和归纳书中重要的知识点。本系列主要内容是关于 QEMU 中 CPU 虚拟化方面的介绍。
关注微信公众号:Linux 内核拾遗
1 CPU 虚拟化介绍
1.1 CPU 虚拟化简介
介绍 CPU 虚拟化之前,首先对下面的概念进行解释和区分:
特权指令和非特权指令
特权指令(Privileged Instructions):特权指令是只有特定特权级别的程序(例如操作系统内核)才能执行的指令。这些指令通常用于执行对底层系统资源和状态的操作,如访问硬件设备、修改内存管理和权限控制等。在 x86 体系结构中,特权指令运行在 ring0。
非特权指令(Non-privileged Instructions):非特权指令是可以由任何权限级别的程序执行的指令。这些指令通常用于一般的应用程序和用户级别代码。非特权指令提供了一组基本的操作和计算功能,但没有直接访问和控制系统底层资源的能力。在 x86 体系结构中,非特权指令运行在 ring3。
敏感指令和非敏感指令
敏感指令(Sensitive Instructions):敏感指令是那些具有一定风险或可能对系统造成影响的指令。这些指令可能会改变或获取系统的全局资源,例如修改系统状态、访问敏感数据或进行特殊处理。敏感指令可能涉及对系统的访问、操作或控制,因此在执行这些指令时需要谨慎,并遵循相应的安全策略和权限管理。
非敏感指令(Non-sensitive Instructions):非敏感指令是指那些不被认为具有风险或不会对系统产生重大影响的指令。这些指令通常是常规的操作和计算指令,不涉及对系统底层资源的直接访问或控制。非敏感指令在大多数情况下是安全的,可以由普通用户程序执行。
x86 系统的敏感指令与特权指令并不是完全相同的,存在一些属于敏感指令但不是特权指令的指令,也就是说用户程序能够运行一些可以改变/获取全局资源的指令。
在虚拟化情况下,这种特殊情况会出现问题:虚拟化平台上面会运行多个虚拟机,如果里面的操作系统都能够随意读取/修改全局数据,这会影响其他虚拟机操作系统的正常运行。
为了解决这个问题,历史上出现了几种方案:
Bochs 和(不含 KVM 的)QEMU 之类的模拟器:逐条解析和执行指令。
VMWare 早期方案:虚拟化用户态的程序直接在 CPU 上执行,但是一些特权指令会通过动态的二进制翻译去执行。
VMWare Xen 方案:修改虚拟机操作系统内核的代码,使虚拟机内核运行在 ring1,并且对虚拟机中操作系统内核的敏感指令进行替换进而使其陷入到 ring0 的 Xen 内核。
上述各方案都有缺点,随着云计算及其底层支撑的虚拟化技术的快速发展,Intel 和 AMD 都相继在硬件层面支持了虚拟化。下面将着重介绍基于硬件 CPU 虚拟化的 VT-x 技术。
1.2 VMX 架构简介
Intel 通过在原来 x86 CPU 的基础上增加 VMX 架构来实现 CPU 的硬件虚拟化。
VMX 架构下定义了两类软件的角色:
虚拟机监控器(VMM,VM Monitor):VMM 对整个系统的 CPU 和硬件有完全的控制权,它抽象出虚拟的 CPU 给各个 VM,并且能够将 VM 的 CPU 直接调度到物理 CPU 上运行。
虚拟机(VM):每个 VM 都是一个虚拟机实例,能够支持操作系统以及各种软件栈和应用程序,VM 本身不会意识到其处在虚拟化环境中。每一个 VM 都相互独立,有自己独立的 CPU、内核、中断和设备等,这些资源都是 VMM 提供的。
为了使得 VMM 能够管理各个 VM 之间的隔离和独立运行,VMM 的运行权限要高于 VM。
传统上,操作系统内核已经运行在 ring0 最高级了,所以为了让 CPU 支持 VMM 和 VM 两种软件,Intel 为 CPU 引入了一种新的模式,叫作 VMX operation。
VMM 执行的模式叫作 VMX root operation 模式,VM 执行的模式叫作 VMX non-root operation 模式,这两种模式之间的转换叫作 VMX 转换。从 VMX root 转换到 VMX non-root 叫作 VM Entry,而从 VMX non-root 转换到 VMX root 则叫作 VM Exit。
VMM 的生命周期以及和 VM 的交互如上图所示,其中包含如下的转换流程:
首先执行 VMXON 的指令让 CPU 进入 VMX operation。在执行 VMXON 之前,需要先分配并初始化一个 VMXON 的区域,以记录 VMM 本身的相关数据。
VMM 通过 VM Entry 来使一个 VM 进入到运行状态。首次进入 VM 是通过执行 VMLAUNCH 指令发起的。每一个 VM 都会有一个对应的虚拟机控制结构(Virtual Machine Control Structure,VMCS)区域与之对应,用来保存该 VM 的相关信息。所以在进行 VMLAUNCH 之前需要提前分配并初始化 VMCS。
VM 不会主动进行 VM Exit。只有当 VM 的 CPU 发生预定指令或者是在 VMCS 中配置一些事件时才会进行 VM Exit。VM 会退出到 VMM 指定的一个地址,此时 VMM 开始执行,可以对 VM 的退出进行处理。
VMM 可以通过执行 VMXOFF 指令退出 VMX operation。
1.3 VMCS 介绍
每个虚拟机的 VCPU 都有一个对应的 VMCS 区域。VMCS 用来管理 VMX non-root Operation 的转换以及控制 VCPU 的行为。
VMCS 之于 VCPU 的作用类似于进程描述符之于进程的作用:
(用于进程调度)传统上操作系统的进程会共享物理 CPU 资源,操作系统负责在多个进程之间分配 CPU,每个进程都有进程描述符来保存进程的信息,并且在进程切换时保存硬件上下文,使得进程能够在下次被调度的时候正常运行。
(用于 VCPU 调度)VCPU 之间会共享物理 CPU,VMM 负责在多个 VCPU 之间分配物理 CPU,每个 VCPU 都有自己的描述符,当 VMM 在切换 VCPU 运行时需要保存此刻的 VCPU 状态,从而在下次的 VCPU 调度中使得 VCPU 能够从被中断的那个点开始正常运行。
VMCS 内部各区域划分及字段含义如下:
参考文献
QEMU/KVM 源码解析与应用 - 李强
关注微信公众号:Linux 内核拾遗
版权声明: 本文为 InfoQ 作者【Linux内核拾遗】的原创文章。
原文链接:【http://xie.infoq.cn/article/0f3151bc0fea70f57f8928372】。文章转载请联系作者。
评论