1.背景
CPU 权限级别控制当前在处理器上运行的程序对资源(如内存区域、I/O 端口和特殊指令)的访问。Guest OS 以低于虚拟机管理程序微内核的特权运行,而在Guest OS中运行的应用程序以更低的特权运行。
虚拟机管理程序(Hypervisor)包括一个虚拟机管理程序微内核和一个或多个 qvm 进程实例
2. 架构
QNX 虚拟机管理程序架构的示意图,以及可用于访问虚拟和物理设备的一些配置。部分配置和部分设备
Guest OS实际上并不在 VM 中运行。虚拟机管理程序不会转换Guest 在物理CPU 的指令。VM 将定义的虚拟硬件和直通硬件呈现给Guest OS,当Guest 在物理 CPU 上执行指令是,就像没有虚拟机管理程序一样。只有Guest执行不被允许的指令,或访问被Hypervisor监控的客户机内存和虚拟化硬件是,Hypervisor才会捕获异常并强制Guest退出。
trap发生时硬件通知虚拟机管理程序,Hypervisor保存Guest的上下文(Guest退出)并完成Guest已开始但无法自行完成的任务。任务完成后,Hypervisor将还原Guest上下文,并将执行权交还给Guest(Guest重新进入)。
下面的 Lahav Line 展示了Hypervisor与Guest之间交互的更动态视图。假定单个 CPU 上
3.虚拟机(QVM)
在 QNX 虚拟机管理程序环境中,虚拟机体现为qvm进程。qvm 进程是在内核外部的Hypervisor中运行的操作系统进程。。
从Guest OS 的角度来看,托管该Guest的 VM 是硬件。就像在物理板上运行的操作系统需要某些硬件特征(体系结构、板特定、内存和 CPU、设备等)一样,在 VM 中运行的操作系统也需要这些特征
配置 VM 时,将组装硬件平台。不同之处在于,您不是组装物理存储卡,CPU等,而是指定机器的虚拟组件,qvm进程将根据您的规范创建和配置这些组件。
QVM 创建、配置、操作、启动、关闭
创建Guest OS可以运行的虚拟环境,qvm进程实例在启动时执行以下操作:
- 在启动时使用进程命令行读取、解析和验证 VM 配置文件 (*.qvmconf) 和配置信息输入,如果配置无效,则退出,并将有意义的错误消息打印到日志中。
- 设置中间阶段表(如ARM:阶段 2 页表)。
-
创建并配置其 VM,包括:
- 将 RAM (r/w) 和 ROM(仅 r)分配给客户机
- 为它提供给来宾的每个虚拟 CPU 预配一个线程
- 预配直通设备,使其可供Guest使用
- 定义和配置虚拟设备 (vdevs)
操作
- 捕获Guest访问异常并确定如何处理它们(即,如果地址是 vdev,则调用 vdev 代码;如果地址确实超出边界,则将其视为已)。
- 在放弃物理 CPU 之前保存其Guest的上下文。
- 还原其来宾的上下文。
- 负责任何故障处理。
- 执行确保 VM 完整性所需的任何维护活动。
启动
VM 中的Guest可以像在硬件上一样启动。但是, CPU 实际上是一个 qvm vCPU 线程。Guest可以使能其中断,就像真实硬件环境中运行时一样。
当客户机虚拟机中的第一个 vCPU 线程开始执行时,虚拟机可以知道该客户机已引导。
关闭
Guest关机是Guest的责任。qvm 进程检测通过常用方法(如 PSCI 或 ACPI)启动的关机。
在虚拟化环境中,CPU 虚拟化扩展负责从Guest的操作中识别Guest何时需要退出。但是,当 CPU 触发Guest退出时,是托管Guest的 qvm 进程实例(即 VM)保存Guest的上下文。qvm 流程实例完成客户机启动的操作,然后在允许客户机重新进入之前恢复客户机的上下文
Guest的权限级别管理
qvm 进程实例管理Guest进入和退出的权限级别,以确保Guest可以运行,并且系统免受错误代码的影响。
在入口上,qvm 实例要求 CPU 向Guest提供运行所需的权限级别,但仅此而已。在客户机退出时,qvm 实例要求 CPU 返回到在虚拟机管理程序主机中运行所需的权限级别。
只有 CPU 硬件可以更改权限级别。qvm 进程执行使 CPU 更改权限级别所需的操作。此机制是特定于体系结构的。
访问虚拟和物理资源
每个 qvm 进程实例管理其托管Guest对虚拟和物理资源的访问。
当客户机尝试访问其客户机物理内存中的地址时,qvm 进程会检查访问尝试并按所述进行响应:
来宾正在尝试访问它拥有的内存区域--PASS。
Guest尝试访问分配给物理设备的内存,并且Guest的 VM 配置为可以直接访问的设备(直通设备)--PASS。
虚拟设备--模拟响应
来宾正在尝试访问分配给虚拟设备(虚拟或半虚拟)的地址。
qvm 进程实例请求适当的权限级别更改,并将执行传递给其请求设备的代码。例如,Guest CPUID 请求触发 qvm 进程实例来模拟硬件并响应Guest,就像真实硬件的响应一样。
尝试访问它没有权限的内存--qvm 进程实例向Guest返回相应的错误。