Bao:一种用于现代多核嵌入式系统的轻型静态分区管理程序
个人学习过程中 Bao Hypervisor 论文翻译(借助翻译工具+个人校对),仅供学习使用,由于个人对一些技术专有名词不够熟悉,翻译不当的地方欢迎指出
论文地址:https://drops.dagstuhl.de/opus/volltexte/2020/11779/
github仓库:https://github.com/bao-project/bao-hypervisor
摘要
鉴于现代嵌入式系统日益复杂和混合临界性,虚拟化成为一种实现强大空间和时间隔离的自然解决方案。广泛使用的系统管理程序,如 KVM 和 Xen,在设计时并没有考虑到嵌入式的约束和需求。由 Jailhouse 开创的静态分区架构似乎解决了嵌入式的问题。然而,Jailhouse 仍然依赖 Linux 来启动和管理其 VMs。在本论文,我们提出了 Bao管理程序,这是一个针对 Armv8 和 RISC-V 平台的静态分区架构的最小、独立和干净的实现。关于大小 size 、启动 boot 、性能 performance 和中断延迟 interrupt latecy 的初步结果表明,这种方法只产生最小的虚拟化开销。Bao 将很快公开,希望能让业界和学术界参与改善 Bao 的安全性、保障性和实时性。
关键词:Virtualization, hypervisor, static partitioning, safety, security, real-time, embedded systems, Arm, RISC-V
1、 介绍
在诸如汽车和工业控制等领域,过去几年来功能需求的数量持续增加。随着越来越复杂且计算功耗大的应用程序数量增加,对高性能嵌入式系统的需求也在同步增长。这导致了一种范式转变,从使用运行简单裸机应用程序或实时操作系统(RTOS)的小型单核微控制器,转向了强大的多核平台,具有复杂的内存层次结构,并能够承载功能丰富的通用操作系统(GPOS)。与此同时,市场压力要求最小化体积、重量、功耗和成本,促使将多个子系统整合到同一硬件平台上。此外,这些子系统通常采用混合临界性(MCSs)系统的形式,通过集成具有不同临界级别的组件。例如,在汽车系统中,网络连接的娱乐信息系统经常与安全关键的控制系统一起部署 。因此,在整合混合临界性系统时必须非常小心,以平衡安全性和安全性所需的隔离与资源共享的冲突要求。
虚拟化是桌面和服务器中已经成熟的技术,它成为实现整合和集成的自然解决方案。它需要最少的工程投入来支持传统软件,同时保证虚拟机(VMs)之间的分离和故障隔离。将面向服务器的虚拟化程序(例如 Xen 或 KVM)适应嵌入式架构(主要是 Arm),已经取得了相当的成功。然而,考虑到目标系统的混合临界性性质,直接的逻辑隔离已被证明不足以满足严格的嵌入式约束和实时要求。此外,这些嵌入式虚拟化程序通常依赖于大型 GPOS(通常是 Linux)来引导、管理虚拟机或提供各种服务,例如设备模拟或虚拟网络 。从安全性和安全性的角度来看,这种依赖膨胀了系统的可信计算基础(TCB),并拦截了安全引导机制中的信任链,从而扩大了系统的攻击面。此外,由于这些操作系统的大小和单olithic结构,这种紧密耦合也阻碍了部署此类虚拟化程序的系统的安全认证过程。
Siemens 的 Jailhouse 静态分区虚拟化程序架构最近在学术界和工业界的混合临界性系统中越来越受欢迎。该架构利用硬件辅助虚拟化技术,使用最小的软件层静态分区所有平台资源,并将每个资源专门分配给单个 VM 实例。它假设不需要在客户之间共享硬件资源。由于每个虚拟核心都静态固定到单个物理 CPU,因此无需调度程序,也不提供复杂的语义服务,进一步降低了大小和复杂性。尽管可能阻碍高效资源使用的要求,但静态分区允许更强的隔离和实时性保证。尽管 Jailhouse 遵循其设计理念,但它仍然依赖 Linux 引导系统并管理其“cell”,面临其他虚拟化程序同样存在的安全问题。
尽管静态分区方法提供了强大的 CPU 和内存隔离,但这仍然不足以满足许多微架构资源(例如最后级缓存、互连和内存控制器)在分区之间保持共享。由此产生的争用导致缺乏时间隔离,影响性能和确定性。此外,这可能被恶意虚拟机利用,通过增加对共享资源的消耗来实施 DoS 攻击,或者通过隐含的时间侧信道间接访问其他虚拟机的数据。为解决这个问题,操作系统和虚拟化程序级别已经提出并实现了诸如缓存分区(通过锁定或着色)或内存带宽保留等技术。
本文介绍了 Bao,这是一个从头开始实现的分区虚拟化程序。尽管遵循与 Jailhouse 相同的架构,但 Bao 不依赖于任何外部依赖(除了执行低级平台管理的固件)。另外,由于机制的简单性,它提供了对缓存着色的原生支持。Bao 最初针对 Armv8 架构,也提供了对 RISC-V 架构的实验性支持。鉴于我们坚信安全不能仅依赖混淆而实现,这是大多数行业参与者遵循的方法,而且一再证明是无效的,因此 Bao 将于2019年底开源。
2、 Bao Hypervisor
Bao(源自普通话中的 “保护”,意为“保护”)是一个面向安全和安全性的轻量级裸金属(bare-metal)管理程序。专为混合关键性系统设计,其重点强调隔离以实现故障隔离和实时行为。其实现仅包括一个最小、薄层特权软件,利用 ISA 虚拟化支持来实现静态分区虚拟化程序架构(图1):资源在VM实例化时静态分区和分配;使用两级转换静态分配内存;仅支持IO的直通;虚拟中断直接映射到物理中断;实现虚拟到物理CPU的1对1映射,无需调度程序。Hypervisor 还提供了一种基本的跨VM通信机制,基于静态共享内存机制 和 以超级调用触发的异步通知形式的跨VM中断。除标准的平台管理固件外,Bao没有任何外部依赖,例如依赖特权虚拟机运行的不可信的庞大的单一内核的通用操作系统(GPOS),因此其可信计算基础(TCB)要小得多。
2.1、 平台支持
Bao目前支持Armv8架构。RISC-V 实验性支持也可用,但由于它依赖于尚未批准的虚拟化扩展,因此尚无可运行该虚拟化程序的芯片。因此, RISC-V 移植仅部署在 QEMU 模拟器上,该模拟器实现了最新版本的草案规范(在撰写本文时,版本为0.4)。因此,在本文的剩余部分,我们将仅关注Arm架构的实现。截至撰写本文时,Bao已被移植到两个Armv8平台:赛灵思的 ZCU102/4 开发板上的 Zynq-US+ 和 华为海思的 Hikey 960 上的 Kirin 960。到目前为止,Bao已能够托管多个裸金属应用程序,FreeRTOS 和 Erikav3 RTOSs,以及纯净的 Linux 和 Android 。
除了简单的串行驱动程序以执行基本控制台输出外,Bao不依赖于特定于平台的设备驱动程序,只需一个最小的平台描述(例如,CPU数量、可用内存及其位置)即可移植到新平台。因此,Bao 依赖于供应商提供的固件和/或通用引导加载程序来执行基线硬件初始化、低级管理 以及 将 Hypervisor 和客户镜像加载到主存储器中。这显著减少了移植工作。
**在支持的基于Arm的平台上,Bao依赖于标准Power State Coordination Interface (PSCI) 的实现来执行低级电源控制操作,进一步避免了对平台相关驱动程序的需求。在基于Arm的设备上,Arm Trusted Firmware (ATF)提供了此功能。**在这些平台上,Linux 本身依赖于 PSCI 进行 CPU 热插拔。当这些客户调用 PSCI 服务时,Bao仅充当调用参数的过滤器和验证器,以保证虚拟机抽象和隔离性,将实际操作延迟至ATF。尽管我们能够直接从 ATF 引导,但我们也一直在使用众所周知的 U-boot 引导加载程序来加载 Hypervisor 和客户镜像。
2.2、 时空隔离
根据隔离的主要要求,Bao 首先会设置每个核心的私有映射。通过使用递归页表映射技术,它避免了对物理内存的完整连续映射,否则这对于执行软件页表遍历将是必要的。这种方法通常在管理多个地址空间时不太适用,并且通常会增加页表查找的 TLB 占用量。然而,鉴于每个CPU仅管理单个地址空间,并且页表在初始化时已完全设置,对于我们的静态架构和设计理念来说,并非绝对如此。尽管如此,所有核心共享针对每个CPU区域的映射,用于核间通信以及 Hypervisor 图像本身。此外,只有承载相同虚拟机的核心才会映射其全局控制结构。这些设计决策遵循了最小特权原则,其中每个核心及其中的特权级别只能(至少直接)访问绝对必需的内容。通过最小化可能被利用的读/写特性器件访问的可用数据,这种方法提升了数据完整性和机密性。此外,虚拟化程序代码页标记为只读,并通过配置为不可执行来强制实施 X⊕W 策略确保虚拟化程序数据页的安全。
客户隔离本身当然从硬件虚拟化支持提供的逻辑地址空间隔离开始。为了最小化翻译开销、页表压力和 TLB 压力,Bao 在可能的情况下使用超级页(在Arm术语中称为块),这也可能通过促进 推测取回 来提高客户性能。至于时间,由于独占式CPU分配,无需调度程序,再加上由客户直接管理的每个CPU架构计时器的可用性,使得实现了完全逻辑时间隔离。
尽管这种架构固有的强大分区性以及减少现有虚拟化开销所做的努力,这还并不足以保证确定性执行并满足关键客户任务的截止期限。在共享的最后一级缓存(LLCs)和其他结构中的微架构争用仍然允许在客户分区之间发生干扰。因此,考虑到其简单性,Bao从一开始就实现了页着色机制,实现 LLC 缓存分区。然而,着色也存在几个缺点。首先,它强制使用最精细的可用页大小,排除了使用超级页的好处。其次,它还对实际物理地址空间进行了分区,导致内存浪费和碎片化。关于着色的另一个问题是,由于 Bao 依赖引导加载程序 bootloader 来加载客户镜像,这些镜像连续布置在内存中,因此它需要对它们重新着色,即将原始加载的图像中与 为特定VM分配的颜色相符的非颜色 兼容页面复制到相符合的页面中,这将增加VM的启动时间。着色可以独立启用,为每个VM选择每个颜色。
2.3、 IO 和 中断
Bao 以只允许传递方式的 IO 配置,直接将外设分配给客户。**在支持的架构中,特别是Arm架构,所有IO都是内存映射的,通过使用现有的 内存映射机制 和 虚拟化支持提供的两级转换,可以免费 for free 实现这一点。**Hypervisor 不验证特定外设的独占分配,这允许多个客户以非监督的方式共享它。
通用中断控制器(GIC)是Arm架构中的中断路由器和仲裁器。尽管它提供了一些中断虚拟化功能,但绝大多数可用的硬件平台都采用了GICv2或GICv3,它们不支持直接将中断传递给客户分区。所有中断都转发到 Hypervisor ,后者必须使用有限的待处理寄存器在VM中重新注入中断。除了特权模式切换增加了不可避免的中断延迟外,这显著增加了中断管理代码的复杂性,特别是如果要模拟中断优先级等功能。Bao 的实现确实遵循了这条路线,因为许多 RTOSs 使用中断优先级,有时甚至作为任务调度机制。这个问题在最新版本的规范中得到了解决,即GICv4,它绕过 Hypervisor 直接向客户传递中断。此外,有限的虚拟化支持要求必须使用 陷入Trap 和 模拟Emulate 来实现客户对中央分发器的访问。根据客户对分发器的访问频率和访问模式,这可能会显著降低性能。截至目前,Bao仅支持GICv2。
3、 评估
本节中,我们介绍了Bao的初始评估。首先,我们将重点关注代码大小和内存占用情况。然后我们评估启动时间、性能和中断延迟。我们将客户端的原生执行(裸机)与托管执行(独立运行)以及托管执行时的干扰情况(互相干扰)进行比较,以评估运行多个客户端时可能产生的干扰。我们还在启用缓存分区的托管场景中进行重复测试(独立运行 - 带缓存分区和干扰 - 带缓存分区),以了解这种第一级微架构分区对目标分区的影响程度,并帮助减轻干扰。
我们的测试平台是 Xilinx ZCU104,搭载了一个四核 Cortex-A53 运行在 1.2 GHz 的 Zynq-US+ SoC,每个核心有 32K 的 L1 数据和指令缓存,并且有一个共享的统一 1MB 的 L2/LLC 缓存。我们将目标测试虚拟机在一个核心中执行,而在添加干扰时,我们在另外两个虚拟机中分别执行两个额外的裸金属应用程序,每个应用程序不断地写入和读取一个大小为 512KiB 的数组,步长等于缓存行大小(64字节)。在启用着色的情况下,我们将 LLC 的一半(512 KiB)分配给运行基准测试的虚拟机,四分之一(256 KiB)分别分配给每个干扰的裸金属应用程序。虚拟化程序代码和基准应用程序均使用 Arm GNU 工具链版本 8.2.1 进行编译,并进行了 -O2 优化。
3.1、 代码大小和内存占用
Bao是一个完全从零开始的实现,没有外部依赖。在这一节中,我们评估了(i)代码复杂性,使用源代码行数(SLoC),和(ii)内存占用,通过查看最终二进制文件的大小,然后分析运行时的内存消耗。
代码分为四个主要部分:arch 和 platform 目录包含了特定于目标的功能,而 core 和 lib 目录则包含了主要的 Hypervisor 逻辑和实用工具(例如字符串操作、格式化打印代码)。每个目录的总SLoC和最终二进制文件的大小列在表1中。
表1 显示,对于目标平台,实现了总共5.6 KSLoC。这个小的代码库反映了系统总体复杂度的低水平。**大部分代码是用C语言编写的,尽管低级初始化和上下文保存/恢复(异常入口和退出)等功能必须用汇编语言实现。**我们还可以看到,架构特定的代码贡献了总SLoC的大部分。最大的罪魁祸首是 GIC 虚拟化支持,占据了几乎总体 Armv8 代码的1/3,约750 SLoC。在核心功能中,代码内存子系统,包括物理页分配和页表管理,包含了大部分复杂性,约 540 SLoC。最终二进制文件的大小详细列在表1的最右侧。静态分配的内存总量约为59 KiB。请注意,大部分 .bss 段的尺寸主要是由于根页表的静态分配。忽略它,加载的最终二进制文件总尺寸约为43 KiB。
接下来,我们评估运行时分配的内存。在启动时,每个CPU分配了一个 28 KiB 的私有结构。这个结构包括私有 CPU 堆栈和页表,以及用于 CPU 间通信的公共页。对于这个四核平台,启动时总共分配了 112 KiB。在初始化过程中,Bao 进一步分配了 4 页(16 KiB),用于基于对象池的内部最小分配机制。此外,对于每个虚拟机,虚拟化程序将分配固定的 40 KiB 用于虚拟机全局控制结构,另外每个虚拟 CPU 分配 8 KiB。对于每个虚拟机,最大的内存开销将是页表的数量,这将首先取决于分配的内存大小和内存映射的外设,其次取决于是否启用了缓存着色。表2 显示了不同分配内存大小时使用的页表数量。它突显了缓存着色机制对页表大小带来的巨大开销。在所有虚拟机初始化之后,除了使用上述对象池进行 CPU 间消息分配的微小例外情况外,不再进行内存分配。
3.2、 启动开销
在本节中,我们评估了 Bao 在启动时间上的开销(而不是系统整体的启动时间)。因此,在任何系统或虚拟机的启动阶段均未进行任何优化。在此平台上,完整的启动流程包括几个特定于平台的启动阶段:(i)BootRom 执行低级初始化并将第一阶段引导加载程序(FSBL)加载到芯片上的内存中,然后(ii)将 ATF、Bao 和客户机映像加载到主存储器中。接下来,(iii)FSBL 跳转到 ATF,然后(iv)将控制权交给了 Hypervisor。
在我们的测量中,我们使用 Arm 的自由运行架构计时器,该计时器在 ATF 的早期阶段启用。因此,这些值仅是对平台总启动时间的近似值,因为它们不考虑先前的引导阶段。我们考虑了两种情况:一个小型虚拟机(117 KiB 映像大小和 32 MiB 内存),运行FreeRTOS;以及一个大型虚拟机(39 MiB 映像大小和 512 MiB 内存),运行Linux。对于每个虚拟机,我们考虑了本地执行(裸机)场景,以及托管执行时着色关闭和启用的情况(分别 solo 和solo-col)。我们测量了(i)虚拟化程序初始化的时间,即从虚拟化程序执行的第一条指令到它将控制权交给虚拟机的时刻;和(ii)到虚拟机内的第一个应用程序开始的总启动时间。我们强调 Bao 不执行客户机映像加载,这与其他嵌入式虚拟化程序的情况不同。为此,它依赖于引导加载程序。因此,映像加载开销仅反映在总时间中。
表3 显示了每种情况下 100 个样本的平均结果。在小型虚拟机的情况下,虚拟化程序初始化开销很小(solo 和 sol-col 场景分别为 6.5 和 9.2 毫秒)。与裸机情景相比,总启动时间增加了约13(0.5%)和16(0.6%)毫秒。在运行 Linux 客户机的大型虚拟机的情况下,Bao 自身初始化和虚拟机的启动分别需要约 9.6 和 156.2 毫秒(solo 和 solo-col 场景)。与本地执行相比,总启动时间增加了约 83(0.7%)毫秒和 184(2.4%)毫秒,着色分别关闭和启用。首先要强调的是着色启用时虚拟化程序初始化时间的大幅增加。这主要是因为 Bao 需要对引导加载程序提供的平坦映像进行着色,在此过程中将映像的多个段复制到符合着色要求的页面中。对于大型客户机映像来说,这一过程更为恶化。其次,总启动时间的增加始终大于虚拟化程序初始化时间。我们认为这是在客户机初始化期间的虚拟化开销的结果(例如 2级转换 和 GIC分发器的陷阱和模拟)。
3.3、 性能开销和干扰
为了评估虚拟化性能开销和虚拟机间的干扰,我们采用了广泛使用的 MiBench 嵌入式基准套件。MiBench 是一组包含 35 个基准测试的套件,分为六个子集,每个子集针对嵌入式市场的特定领域:汽车(和工业控制)、消费类设备、办公自动化、网络、安全和电信。对于每个基准测试,MiBench 提供了两个输入数据集(小和大)。我们的评估重点放在汽车子集上,因为这是 Bao 所针对的主要应用领域之一。该子集包括三个内存密集型基准测试,因此更容易受到缓存和内存争用引起的干扰(qsort、susan corners 和 susan edges)。
图2显示了对汽车 MiBench 子集进行 1000 次运行的结果。对于每个基准测试,我们将结果表现为相对于裸机执行情况的性能规范化值,因此更高的值反映了性能较差。为了进一步研究和了解基准测试的行为,我们收集了 qsort 基准测试的 L2 缓存未命中率、数据 TLB 未命中率以及内存访问指令的停滞周期率的信息。表4 显示了每种情景下小和大 qsort 基准测试的结果。
分析图2,可以在所有基准测试中观察到相同的趋势,尽管程度有高有低。首先,注意到托管执行导致性能略微下降。表4 中反映了这一点,L2 缓存和数据 TLB 未命中率都略微增加,这反过来解释了内存访问停滞率的增加。正如预期的那样,这源于 2级地址转换的虚拟化开销。其次,当启用颜色时,性能开销进一步增加。表4 中的结果显示了所有指标已经显著增加。同样,正如预期的那样,这可以解释为只有一半的 L2 可用,并且着色排除了超级页面的使用,显著增加了 TLB 压力。在干扰情景中,性能显著下降。表4 中的结果证实,这是由于 L2 缓存未命中的激增所致。最后,我们可以看到通过着色进行的缓存分区可以显著减少干扰。表4 显示,着色可以将 L2 缓存未命中率完全降至 solo colored 情景的水平。然而,回顾图2,我们可以看到这种削减并未在观察到的性能下降中体现出来,在 interf-col 情景中,性能下降仍然高于 solo-col 情景。这可以通过从 LLC(例如写回缓冲区、MSHR、互连、内存控制器)引入的仍未解决的争用来解释,反映在内存停滞周期率的差异上。正如预期的那样,由于 basicmath 和 bitcount 的内存需求要低得多,它们受到的着色和干扰的影响明显较小。
图2 中另一个可见的趋势是性能下降在小型数据集变化的基准测试中总是更为明显。当比较小型和大型输入数据集的变体时,我们可以看到,尽管表4 中 L2 缓存未命中率的增加相似,但小型变体经历了更大的性能下降。我们认为这可能是因为对于小型输入数据集基准测试,由于其总执行时间更短,缓存未命中的惩罚会更严重。表4 中观察到的内存访问停滞周期率支持了这一观点,在小型输入数据集情况下,它导致了更高的百分比增加。
3.4、 中断延迟
为了测量中断延迟并最小化与虚拟化无关的开销,我们设计了一个极简的裸机基准测试应用程序。该应用程序连续设置了体系结构计时器,每 10ms 触发一次中断。由于知道中断触发的时刻,我们将延迟定义为预期挂钟时间与实际开始处理中断的时刻之间的差值。计时器具有 10 ns 的分辨率。对于每种情景,我们获取了 1000 个样本的结果,总结如表5 所示。
当将原生执行与独立托管执行进行比较时,我们看到平均延迟和标准偏差显著增加,分别约为 430ns 和 40ns ,最坏情况延迟增加了 1680ns 。这反映了已经预期到的 GIC 虚拟化开销,因为陷入和模式切换的成本,以及中断管理和重新注入。同时可见,着色本身并没有显著影响平均中断延迟,但略微增加了最坏情况的延迟。表5 中的结果也证实了缓存和内存争用对中断延迟的不利影响,特别是在最坏情况下。平均延迟增加了约 12ns ,标准偏差增加了约 41ns,最坏情况延迟增加了 1160ns。启用着色在平均延迟上没有显著的好处,实际上增加了标准偏差和最坏情况的延迟。我们认为这是因为在这种情况下,相关的干扰实际上不是在虚拟机之间,而是在干扰的客户和未着色的 Hypervisor 之间。
4、 相关工作
虚拟化技术始于20世纪70年代。如今,虚拟化是一项成熟的技术,有着丰富的 Hypervisor 解决方案,主要应用于各种场景,从服务器、桌面到移动设备,甚至到高端和低端嵌入式系统。
Xen 和 KVM 是代表性的开源 Hypervisor,涵盖了广泛的应用范围。Xen 是一种裸机(Type-1)Hypervisor,依赖于一个特权 VM,称为 Dom0,来管理非特权VM(DomUs)并与外设交互。KVM 采用不同的设计理念;它被设计为一个 Hosted Hypervisor,并且在 Linux 的主干版本中集成,从 2.6.20 版本开始。虽然最初是为桌面和服务器应用开发的,但这两种 Hypervisor 已经在嵌入式领域找到了自己的位置。Xen 在 Arm 架构上的实现(Xen on Arm)是首个面向 Arm 平台的 Xen 实现,而 RT-Xen 则通过实时调度框架进行了扩展。而 KVM/ARM 则提出了分离模式虚拟化的概念,并推动了 Arm 平台的硬件虚拟化规范。
另一方面,为了满足嵌入式实时应用的严格时序需求,另一类系统提出了对广泛使用的商业 RTOS 进行扩展,加入虚拟化功能。Green Hills INTEGRITY Multivisor、SysGo PikeOS 和 OKL4 MicroVisor 是利用已开发和认证的 RTOS 基础设施的优秀示例,以提供实施虚拟化能力作为服务或模块。还有一类系统利用面向安全的技术,例如 Arm TrustZone 进行虚拟化。基于 TrustZone 的 Hypervisor,比如 SafeG 和 LTZVisor 通常是双操作系统解决方案,允许两个不同的执行环境(即 RTOS 和 GPOS)进行合并。尽管这两种设计理念都致力于降低性能开销和最小化中断延迟,但它们通常在支持多个 VM 和多核配置的扩展性方面存在一些限制。
像 Xtratum、XVisor、Hellfire/prpl-Hypervisor、ACRN 和 Minos 这样的小型 Type-1 嵌入式 Hypervisor,在全功能 Hypervisor 和虚拟化增强的 RTOS 之间提供了很好的折衷方案。Xtratum 是针对 LEON 处理器设计的用于安全关键航空航天应用的 Hypervisor;如今,它也适用于 x86、PowerPC 和 Armv7 指令集。Hellfire/prplHypervisor 是专门为针对MIPS架构的实时嵌入式系统设计的(支持虚拟化模块)。XVisor 是专为在 Arm 平台上引入嵌入式虚拟化而设计的工具,吸引了很多学术界和业余爱好者。英特尔研究人员开发了 ACRN ,这是一个面向物联网领域的轻量级 Hypervisor,目前针对 x86 平台。Minos 是一个针对移动和嵌入式应用的新兴解决方案。与这些 Hypervisor 类似,Bao 也是一个针对 Arm 和 RISC-V 处理器的 Type-1 Hypervisor(并开放未来支持MIPS或其他嵌入式平台);然而,它通过遵循静态分区架构,使得 TCB 进一步减少并提高了实时性能。
Siemens 的 Jailhouse 是采用了 Bao 所采用的静态分区架构的先驱。Jailhouse 利用 Linux 内核启动系统,并使用内核模块在已运行的 Linux 下安装 Hypervisor。然后它依赖于这个 root cell 来管理其他 VM。由于静态分区在汽车等嵌入式领域的优势得到了证实,其他 Hypervisor 也在努力支持它。Xen 最近推出了 Dom0-less 执行,允许DomUs在没有Dom0的情况下启动和执行,这也消除了对Linux的依赖。我们坚信 Bao 将能够通过提供同样的静态分区优势,拥有更小的 TCB(可信计算基)以及实现清晰的安全功能,从而与 Xen 的 Dom0-less 区别开来。
最近,Google 开源了 Hafnium,一个以安全为重点的 Type-1 Hypervisor。它旨在在一组安全域之间提供内存隔离,以更好地将不受信任的代码与安全关键代码隔离开来,其中每个安全域都是一个VM。
5、 On the Road
Bao 的开发仍处于萌芽阶段。截至目前,我们正在扩展对 Arm 架构的支持,包括 SMMU(Arm 的 IOMMU)和最新的 GIC 版本(v3 和 v4)。我们还在将系统移植到一系列不同的平台,包括 NVIDIA 的 Jetson TX2 和 NXP 的 i.MX 8。此外,考虑到代码库规模较小,我们计划进行全面的重构,以符合 MISRA C 编码准则。
Bao 从一开始就实现了缓存着色,作为微架构分区和隔离的第一线。我们的目标是实现其他最新的分区机制(例如内存限流),并对 Hypervisor 镜像本身进行着色,因为我们已经验证了 VM 之间或 VM 与 Hypervisor 之间仍然存在争用问题。然而,我们认为这些问题应该由专用硬件机制支持,以避免增加代码复杂性和大小,并尽量减少开销。事实上,Arm 在 Armv8.4 上提出了 Memory System Resource Partitioning and Monitoring(MPAM) 扩展。MPAM 提供了对共享缓存、互连和内存带宽的硬件支持。然而,迄今为止尚无可用的支持这些扩展的硬件。我们计划使用 Arm Foundation Platform 模型实现对 MPAM 的支持,以便在真实硬件上进行测试,一旦这些硬件可用即可进行测试。
最后,由于 Bao 也是一个面向安全的 Hypervisor,受信执行环境(TEE)的支持也在路线图上。通常,Arm TEE 是基于 TrustZone 技术的,这是一组安全硬件扩展,将平台分为安全和普通世界。TEE 内核和应用运行在安全方面,而其他所有内容(包括 Hypervisor)在普通世界执行。目前,TrustZone 不支持多个隔离的 TEE。几种安全世界虚拟化方法已经提出,最近,Arm 在 Armv8.4 上添加了对安全世界 Hypervisor 的支持。然而,基于 TrustZone 的 TEE 的双世界方法已被证明基本上存在缺陷。此外,我们认为运行额外的安全 Hypervisor 会不必要地增加复杂性,并且安全世界应仅用于封装绝对安全原语(例如安全启动、证明、认证、密钥管理)。Bao 的方法将考虑到这一点,并利用已有的虚拟化机制,无需额外的调度逻辑,允许在普通世界的单个硬件分区中运行多个VM。TEE 将部署在辅助 VM 上,并仅在主要客户端请求时执行。此方法的另一个优点是它在不同架构之间具有可移植性和可扩展性,而不是特定于 Arm。
6、 总结
在本文中,我们介绍了 Bao Hypervisor,这是一种对现有嵌入式 Hypervisor 的轻量级替代方案,是静态分区架构的最小、独立和清晰实现。尽管开发仍处于初级阶段,初步评估显示其仅带来了极小的虚拟化开销。我们概述了 Bao 的开发路线图,其中包括扩展的平台支持和每个分区的 TEE 支持。Bao 将于 2019年 底开源,希望引起学术界和行业界对虚拟机隔离和安全性挑战的关注。