11 Star 4 Fork 6

openEuler / capsule

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
design.md 11.56 KB
一键复制 编辑 原始数据 按行查看 历史

本文档包含了Capsule Hypervisor的顶层设计思路。

1. 功能性

Capsule Hypervisor基于软硬结合的思路,采用一套架构支持通用虚拟机(Common Virtual Machine)、安全容器(Micro-VM)、逻辑分区(Logical Partition)三种运行形态。

1.1. 虚拟机

对虚拟机的支持是Capsule Hypervisor的基本功能。为了让虚拟机能够以无差别方式运行为真实机器开发的软件,虚拟机就必须像真实的机器一样包含CPU、内存、IO设备、IO总线和其它系统组件。

虚拟CPU

虚拟CPU是一台虚拟机的核心部件,而执行指令是它的核心功能。借助硬件辅助虚拟化技术(如Intel的VT-x技术),虚拟机内部的指令可以直接在物理CPU上执行,从而提升执行性能。因此,物理CPU需要为宿主机软件和虚拟机软件准备不同的执行环境或模式。对于支持VT-x特性的Intel CPU,根模式(Root Operation)用来执行宿主机软件,而非根模式(Non-Root Operation)用来执行虚拟机软件。类似地,ARM架构的CPU使用EL0/EL2模式来执行宿主机软件,使用EL0/EL1模式来执行虚拟机软件。 尽管不同CPU体系统架构具有不同的硬件辅助虚拟化实现方式,但是基本流程是相似的,如下图所示:

对于每个虚拟CPU来说,它是宿主机上的一个普通线程,具备宿主机状态。经过一系统的初始化动作后,宿主机上的虚拟CPU线程会进入到(entry)虚拟机模式,开始按虚拟机状态发生变化。此时,大部分的虚拟机指令可以在此模式直接运行,只有当某些特殊情况发生时(如X86架构下端口操作指令访问的端口并不真实存在),物理CPU会退出(exit)回到宿主机模式,退出前虚拟机的状态会被保存,而退出后宿主机状态被恢复,物理CPU重新进入虚拟CPU线程开始仿真(emulate)虚拟机的指令(与CPU体系架构相关,需要一个个单点分析)。仿真动作完成后,物理CPU又继续回到虚拟机模式并恢复虚拟机的状态开始执行,直到下一次退出的发生。

除了指令执行,虚拟CPU同样需要处理中断和异常。异常通常被认为是伴随指令执行同步发生的,往往是由于指令并不具备正常完成条件时产生;;而中断是由于外部事件异部产生的,如IO设备完成IO请求时发出的中断事件。中断和异常发生时需要CPU能够暂时停止当前任务的执行,转而执行中断或异常处理任务;等到中断或异常处理任务结束后,CPU再恢复被打断的任务继续执行。硬件辅助虚拟化技术下,虚拟机异常也往往在虚拟机模式被处理,除非不适合在虚拟机中处理的才会退出到宿主机模式处理。虚拟机中断分为发生、路由、注入、处理几个部分:发生动作通常由虚拟设备模拟程序触发,路由动作是模拟目标CPU寻找过程,而注入动作往往发生在目标CPU的entry阶段,处理则是CPU进入虚拟机模式后立刻开始执行中断处理任务。另外,当物理CPU处理虚拟机模式时,对于接收到的物理中断,会促使物理CPU退出到宿主机模式进行中断的处理,除非该物理中断本来就是发给虚拟机处理的,此时不会退出,如直通设备产生的中断。

每个虚拟CPU还需要模拟一个本地时钟,作为时钟源和时钟事件源:时钟源用于获取时间,类似现实生活中的手表;时钟事件源用于经过特定时间段后产生中断,类似现实生活中的闹钟。这部分功能往往也通过硬件辅助方式实现。

在基本功能和特性的模拟之外,虚拟CPU线程受宿主机操作系统内核的任务调度子系统管理,只有当虚拟CPU线程被调度成为物理CPU的当前执行任务时,虚拟CPU才真正获得执行,也才真正取得物理资源。目前Capsule Hypervisor仍是复用Linux内核的调度系统,但是未来有可能会使用定制内核。因此,Capsule期望能设计一套与具体内核实现解耦的API适配层。

虚拟内存

为实现对多任务的支持,每个虚拟CPU需要模拟一个虚拟MMU(Memory Management Unit),使得虚拟CPU上的任务可以通过虚拟地址(GVA, Guest Virtual Address)访问内存。在硬件辅助虚拟化技术下,MMU要完成两级地址转换,GVA->GPA->HPA,其中GPA是Guest Physical Address,HPA是Host Physical Address。其中第一级转换过程中的缺页异常在虚拟机模式下完成,而第二级转换过程的缺页异常则退出到宿主机模式下完成,过程中需要使用Linux内核的内存按需分配能力。

虚拟IO设备与IO总线

与KVM的设计类似,Capsule是处于内核态和物理硬件打交道的一个模块,对于虚拟IO设备和总线的模拟完全由用户态的辅助程序完成,这里我们使用StratoVirt项目

虚拟IO设备包含存储、网络、图形和各类异构加速设备;IO总线主要支持常用的PCI总线,实现虚拟机的MMIO,DMA和中断路由操作。

其它虚拟组件

包含虚拟机运行过程中必需的固件和传统外设。

1.2. 逻辑分区

逻辑分区可以看成是虚拟机的一个特例,CPU、内存和外设均以独占的方式使用,无法复用和调度,实现思路如下图所示:

其中,管理分区是Capsule所运行的系统,一旦某个物理CPU被分配给一个逻辑分区后,该物理CPU就会从管理分区中下线,完全脱离管理分区的管辖(无法对分区中的CPU进行任务调度),并重新进入初始化过程,进而开始执行逻辑分区中的程序;物理内存会被划分成独立的区间供不同逻辑分区使用,通过硬件辅助虚拟化技术中的内存隔离能力可以确保不同逻辑分区不会相互干扰,但是GPA到HPA转换阶段不会产生缺页异常;此外,外部设备借助虚拟设备直通技术以独占方式被逻辑分区使用。

1.3. 顶层架构

通过对Capsule Hypervisor所支持的虚拟机和逻辑分区功能分析,可知从功能性角度,其整体架构如下图:

Capsule Hypervisor包含内核和用户态辅助程序两部分。内核部分由Linux和Capsule Core组成,Linux为正在开发的Rust for Linux分支,Capsule Core为本项目对应代码。对于普通虚拟机和安全容器,用户态辅助程序(如StratoVirt)配合内核部分实现;而对于逻辑分区即主要由内核Capsule Core支持。Capsule Core通过一套架构两种模式支持虚拟机和逻辑分区:共享模式支持虚拟机;独占模式支持逻辑分区。

线程模型(运行态)

  • 对于普通虚拟机和安全容器形态,运行线程遵循Linux线程模型。虚拟机的每个CPU对就一个vCPU线程,所有虚拟机的设备可以共用一个IO线程,也可独占线程;所有这些线程受Linux线程调度机制管理。
  • 对于逻辑分区形态,出于安全和实时性考虑,分区CPU对Linux不可见,因此需要设计一套精简的面向逻辑分区CPU的专用线程模型。

以安全容器形态为例(普通虚拟机略复杂),各组件/线程运行过程如下图所示:

安全容器形态包含用户态的StratoVirt组件和内核态的Capsule Core组件,这样划分是出于安全设计考虑,详见安全部分说明。StratoVirt组件首先运行Main Thread主线程,该线程主要进行虚拟机和各种设备的创建,过程中通过用户态与内核态接口(详见用户态与内核态接口部分)将相关信息同步给Capsule Core组件或者使用Capsule Core提供的各种能力。完成各种设备创建后,Main Thread就变成IO Thread不断等待IO事件并进行处理直到虚拟机关闭。IO Thread运行的同时,每个CPU对应的vCPU Thread也开始运行,该线程进入一个外循环,使用Capsule Core提供的硬件辅助虚拟化能力,如果Capsule Core无法处理由用户态进行模拟处理;Capsule Core的实现是一个内循环,在内核态通过硬件提供机制进入虚拟机模式执行虚拟机程序,如果不能处理先由Capsule Core模拟处理,Capsule Core也不能处理的再交由用户态处理。vCPU借助MMIO操作经由eventfd通知IO线程有事件产生;IO线程处理完成后通过irqfd以虚拟中断方式通知vCPU IO处理结果。

安全容器各个线程在运行过程中隐式地依赖Linux内核能力,也意味着可通过Linux内核对资源使用进行控制:

  • 基于物理时钟中断触发vCPU线程和IO线程的调度,通过调度才能真正获得CPU资源;
  • GPA到HPA转换过程中缺页会使用内核中内存页的动态分配能力,实现内存资源的按需使用;

代码目录结构(构建态)

capsule
|--arch: CPU体系架构相关代码
|    |--x86: x86架构相关
|    |   |--vmx: Intel的实现
|    |   |--svm: AMD的实现
|    |   |--xxx.rs: 架构公共代码
|    |--arm64: arm64架构相关
|
|--main.rs: 体系无关公共代码入口
|--vm.rs
|--cpu.rs
|--memory.rs
|--bus.rs
|--interrupt_controller.rs
|--irqfd.rs
|--eventfd.rs
|--xxx.rs

用户态与内核态接口

内核模块呈现全局唯一/dev/capsule字符设备,用户态模块通过ioctl使用全局基本功能:

  • API兼容性获取;
  • 创建虚拟机或分区;

每个虚拟机或分区对一个虚机字符设备,用户态模块通过ioctl使用虚拟机相关基本功能:

  • 设置虚拟机用户态地址区间;
  • 创建中断控制器并设置默认中断路由;
  • 为虚拟机设备申请eventfd和irqfd;
  • 创建虚拟CPU
  • 为虚拟CPU映射与内核共享数据区间

每个虚拟CPU对应一个字符设备,用户态模块通过ioctl使用虚拟CPU相关基本功能:

  • 开始执行,进入虚拟机模式;

2. 性能

Capsule Hypervisor采用硬件辅助虚拟化技术实现对虚拟机和分区的支持,很大一部分原因就是为了提升虚拟机或分区的性能。硬件辅助虚拟化技术的核心思想是把实现逻辑简单且常用的功能直接交由硬件完成,而且实现逻辑复杂但又相对使用频度较低的功能交由软件完成,使硬件和软件各自发挥所长。

整体来说硬件辅助虚拟化可分为:

  • CPU与内存相关的基础硬件辅助虚拟化能力,如Intel x86的VT-x,也叫VMX;
  • 设备中断与DMA相关IO硬件辅助虚拟化能力,如Intel x86的VT-d;

3. 安全性

对于虚拟机或逻辑分区内部的软件而言,虚拟机和逻辑分区就是一个安全沙箱。这些软件无法透过沙箱直接访问或攻击真实的物理资源。

然而Capsule Hypervisor在实现过程中如果存在缺限或漏洞,就有可能被虚拟机或逻辑分区内的软件间件利用,进而破坏Hypervisor,基至是物理硬件。在虚拟机模式下,出于权限最小化的考虑,Capsule Hypervisor并没有采用内核线程模型,而是采用普通的用户态线程模型。内核态的Capsule Core仅实现必要的部分(如执行模式切换等特权操作硬件要求只能在内核态执行)或者性能相关且逻辑简单的部分(如中断控制器的模拟),而将实现逻辑复杂的IO设备模拟放到用户态运行,并通过内核态提供的接口调用内核能力或同步状态信息。

1
https://gitee.com/openeuler/capsule.git
git@gitee.com:openeuler/capsule.git
openeuler
capsule
capsule
master

搜索帮助