ZVM虚拟外设模型与开发流程

0 阅读6分钟

ZVM是一款轻量级嵌入式实时Hypervisor,除了提供精简的实时内核和虚拟化功能外,还支持多种虚拟外设。虚拟外设是Hypervisor为客户OS提供的一系列虚拟外部设备,允许客户OS像访问真实外设一样使用。虚拟外设的开发往往比内核和物理外设驱动更加复杂,尤其是在不同虚拟化模式(如直通、半虚拟化、完全虚拟化和单根虚拟化)下,虚拟外设的适配和调试工作量显著增加。为了应对这一挑战,ZVM提供了虚拟外设模型,使得开发者能够高效地构建和管理虚拟外设。

一、ZVM虚拟外设模型

ZVM虚拟外设模型是ZVM外设驱动模型的一种特殊实现(关于ZVM外设驱动模型的详细介绍见文章《ZVM外设驱动模型与开发流程》),特点在于专门为外设虚拟化功能而设计。对应ZVM外设驱动模型的配置文件、驱动框架和具体驱动代码三部分,ZVM虚拟外设模型也由三部分构成:配置文件、虚拟外设框架和具体虚拟化实现。

虚拟外设框架提供了统一的实现外设虚拟化的标准接口,具体虚拟化实现则是一些具体代码,负责为客户OS模拟真实的硬件外设行为,以及实现对多OS共享或独占设备资源的管理能力。其构成示意如图1所示。

图1 ZVM虚拟外设模型构成

理解ZVM虚拟外设模型是进行虚拟外设开发的前提,ZVM虚拟外设模型的配置文件、虚拟外设框架、具体虚拟化实现三部分主要职能如下:

①配置文件

主要包括Kconfig文件,用于控制虚拟外设的启用、分配虚拟资源(如支持的虚拟外设个数)等;Devicetree(.dts/.dtsi)和DT-Binding(.yaml)则用于描述要为客户OS模拟的虚拟设备(通常与物理节点格式一致),定义其寄存器布局、中断属性等细节,使ZVM知道应该模拟一个什么样的外设供客户OS驱动操作。

②虚拟外设框架

虚拟外设框架提供统一的虚拟外设接口,主要包括通用的外设初始化、回收以及处理客户OS对虚拟设备寄存器的读写请求。通过这一系列标准化接口,不同类型的虚拟外设可复用相同的管理逻辑,显著降低开发复杂度并提升代码一致性。在初始化阶段,开发者通过统一接口声明外设所属客户OS和虚拟外设类型(如直通、半虚拟化、完全虚拟化等)。当客户OS访问外设时,ZVM的异常处理机制会正确地交给该设备对应的处理逻辑,从而在单一虚拟外设框架下支持多种虚拟化模式。

③具体虚拟化实现

开发者需实现②虚拟外设框架中定义的虚拟外设接口,完成寄存器模拟、数据转发(如将客户OS的串口输出重定向到物理终端)等逻辑。此外,可根据需要自定义某一类虚拟外设的管理结构,例如ZVM维护了一个虚拟串口列表,用于统一管理多个客户OS的虚拟UART实例及其状态。

二、ZVM虚拟外设开发流程

在掌握上述虚拟外设模型的基础上,ZVM虚拟外设的开发可遵循以下四个步骤:

第1步:熟悉设备功能和特性

虚拟外设开发的第一步是理解所要模拟的真实外设的功能和行为。开发者需要清楚客户操作系统“看到”的是什么设备(比如 PL011 UART)期望的是什么反馈,包括它的寄存器、中断和操作方式,并了解哪些原本由硬件自动完成的行为现在需要ZVM在软件中模拟实现(完全虚拟化方式)。 建议参考真实设备的官方手册,掌握其工作原理,为准确的外设模拟打下基础。

图2 PrimeCell UART (PL011)手册节选

第2步:配置与启动虚拟外设(以虚拟PL011开发为例)

此步骤的目的是让客户OS知晓自己有这个外设、以及让ZVM知道需要模拟的外设的信息。 首先需要明确告知客户OS拥有该外设。这需要遵循客户OS各自的编译方式,如Linux,则需要添加一个pl011类型的设备树节点,这决定了客户OS启动后将要访问的地址和驱动工作模式。在ZVM中需要做的是添加虚拟外设配置项与代码(编写Kconfig、CMakeList、与具体.c .h文件),与ZVM外设驱动模型中的配置文件同理。

图3 配置与启用ZVM虚拟外设

第3步:编写具体外设虚拟化程序

配置与启动虚拟外设还不足以让ZVM在客户OS访问外设时正确地处理和模拟。接下来就要编写具体的外设虚拟化代码。

最首先要做的是,为客户OS添加虚拟外设(否则客户OS访问设备时不会进入虚拟化代码,而是因访问异常而崩溃)。ZVM提供了统一可配的接口(vm_virt_dev_add),将指定外设设置为指定类型分配给指定客户OS。如图4,虚拟串口通过Devicetree中约定的vm_console配置为完全虚拟化设备分配给指定客户OS。

图4 ZVM添加虚拟外设示例

接下来,外设虚拟化代码的核心任务就是处理客户OS对设备的访问。 具体实现方式取决于所选的虚拟化类型:如直通设备则只配权限不模拟;半虚拟化(VirtIO)则是基于ZVM内置的VirtI/O后端框架;完全虚拟化需完整模拟硬件寄存器的行为;单根虚拟化则需要支持客户OS直接访问VF(如PCIe直通)。

以完全虚拟化的虚拟串口为例,开发者需要实现以下接口并声明虚拟外设,如图5。(具体代码可参考ZVM社区版的subsys/zvm/vdev/vpl011.c,入口esnl.hnu.edu.cn/zvm/,图6)

图5 ZVM虚拟外设接口实现和虚拟外设声明示例

图6 ZVM社区版入口

第4步:测试与调试

通过代码编译与功能验证是虚拟外设开发的基本要求,更重要的是,在多客户OS场景下,ZVM需要保证多个客户OS同时访问虚拟外设时的资源隔离能力与性能表现,检查在客户OS动态创建或销毁过程中,虚拟设备能否正确初始化和释放,避免资源泄漏或状态残留。因此,虚拟外设的开发需要大量的测试,导致开发周期难以缩减。

ZVM外设驱动模型和ZVM自动化测试能有效加快ZVM虚拟外设开发周期,并可借助配套的可视化管理工具VisualZVM实现对外设状态的监控(图7)。

图7 VisualZVM虚拟外设展示

原文转自:公众号【嵌入式计算湖南省重点实验室】