arm寄存器虚拟化分析
在 ARM 架构中,当异常(如中断、系统调用、数据中止等)发生时,处理器必须立即停止当前正在执行的程序,并跳转到一个特定的位置去执行对应的异常处理程序。
这些处理程序的集合就是异常向量表。VBAR_EL1 寄存器的作用就是指向这个异常向量表在内存中的起始位置。每个异常级别(EL1, EL2, EL3)都有自己独立的 VBAR_ELx 寄存器。
如果 Hypervisor 不干预,让 Guest OS 直接写入物理的 VBAR_EL1 寄存器,会导致严重问题:
破坏异常注入机制:这是最主要的原因。当 Hypervisor 需要向 Guest OS 注入一个虚拟中断(vIRQ) 或虚拟异常(vSError) 时,它需要将 vCPU 的程序计数器(PC)设置为 VBAR_EL1 + 对应的异常偏移量。如果 Guest OS 随意更改了 VBAR_EL1,这个跳转地址可能就是错误的,导致注入失败,虚拟机行为异常。
失去控制和可见性:Hypervisor 需要知道 Guest OS 的异常处理程序位于何处,以便进行调试、监控(Profiling)或在某些情况下进行模拟。
安全风险:恶意 Guest OS 可能将 VBAR_EL1 指向一个非法的或恶意的地址,从而破坏 Hypervisor 的稳定性和安全性。
功能:当发生异常(如中断、系统调用、页错误)时,处理器自动将发生异常时正在执行的指令的地址(即返回地址)保存到 ELR_ELx 中(x 对应于目标异常级别)。
使用:当异常处理程序执行完毕,通过 ERET 指令返回时,处理器会从 ELR_ELx 中取出地址,并恢复执行。
简单来说,ELR_ELx 记住了“从哪里打断,就回到哪里”的位置。
在虚拟化环境中,ELR_EL1 的复杂性急剧增加,原因如下:
真实异常:在 Guest OS 执行时发生的真实硬件事件(例如,Guest OS 内的一个页错误)。
虚拟异常:由 Hypervisor 注入 到 Guest OS 的事件(例如,一个虚拟定时器中断)。
从 真实异常 返回,需要回到被该异常打断的 Guest OS 指令。
从 虚拟异常 返回,需要“开始执行”该异常的处理程序,就好像它自然发生一样。
如果让 Guest OS 直接控制物理 ELR_EL1,它将无法区分这两种情况,也无法正确设置返回地址。
SPSR 用于在发生异常时,保存异常发生前的处理器状态(PSTATE)。当从异常返回时,用 SPSR 来恢复之前的处理器状态。
如果让 Guest OS 自由读写物理 SPSR_EL1,会造成严重问题:
破坏异常注入:当 Hypervisor 需要向 Guest OS 注入一个虚拟异常(如虚拟中断)时,它需要精心构造一个“假的”异常现场,其中包括 vSPSR_EL1。
如果 Guest OS 能随意修改物理 SPSR_EL1,这个构造的现场就会被破坏。
破坏隔离性与安全性:Guest OS 可能通过设置一个高特权的 SPSR(例如,使能EL2位)来尝试提升自己的权限,在异常返回时破坏 Hypervisor。
状态不一致:在 vCPU 被调度出去时,它的 SPSR 状态必须被保存,以便下次调度时能无缝恢复。
CNTP_CTL CNTP_TVAL CNTP_CVAL 作用 及虚拟化
CNTP_CTL_EL0 就像一个开关面板,负责启动/停止定时器,以及管理其中断。
CNTP_TVAL_EL0 设置一个一次性的定时器超时。其值代表距离超时还有多少个定时器计数器周期。这是一个相对值寄存器,基于当前时间点设置一个未来的时间偏移量。
CNTP_CVAL 软件向此寄存器写入一个绝对的时间点(例如 Y)。这个值会与不断递增的 CNTPCT(物理计数器)进行比较。读取则返回当前设置的比较值。它比 TVAL 更精确,尤其适合设置周期性的定时器(只需在当前 CVAL 上加上一个间隔即可)。
时间隔离:每个 VM 都应有自己独立的“时间视图”,一个 VM 的定时器操作不应影响另一个。
中断路由:物理定时器中断是固定的,但需要将其转换为每个 VM 独有的虚拟定时器中断。
调度影响:当 vCPU 被 Hypervisor 调度出去时,它的定时器必须被“冻结”,否则会在其未运行时错误超时。
CNTP_CTL CNTP_TVAL CNTP_CVA 所控制的物理定时器是 Per-cpu 的,如果透传CPU,则可以不虚拟化上面3个寄存器
VBAR_EL1、ELR_EL1 和 SPSR_EL1 都是 Per-CPU 的寄存器,如果透传CPU,则可以不虚拟化上面3个寄存器
GIC 是 ARM 架构中的通用中断控制器,它负责管理所有来自外设的中断,并将其分发给合适的 CPU 核心进行处理。
GIC Distributor 是中断控制的大脑和总调度中心。它是系统全局的,通常只有一个。
优先级仲裁:当多个中断同时发生时,根据预设的优先级决定哪个中断最先被处理。
GIC CPU Interface 是每个 CPU 核心与 GICD 通信的本地代理。它是 Per-CPU 的,每个 CPU 核心都有一个独立的 GICC
应答中断:CPU 通过 GICC 来告知 GICD 它已经开始处理某个中断。
中断完成通知:CPU 处理完中断后,通过 GICC 通知 GICD,以便 GICD 可以再次发送该中断。
优先级掩码:允许 CPU 设置一个优先级阈值,只有更高优先级的中断才能打断当前处理程序。
在虚拟化环境中,中断问题变得异常复杂:物理中断只有一个,但需要让多个 Guest OS 都感觉自己独占了中断控制器。GICC:CPU 本地接口,是每个核心一个
透明性:Guest OS 的驱动程序无需修改就能继续使用中断。
设备模拟:Hypervisor 模拟的虚拟设备需要向 Guest OS 产生中断。
直通设备:分配给某个虚拟机的物理设备,其中断必须能直接送达该虚拟机。
硬件为每个物理 GICC 提供了一组 GICH 和 GICV 寄存器。
GICH 由 Hypervisor 使用,用于管理虚拟中断。
GICV 由 Guest OS 直接访问,无需陷入,极大提升了性能。
Hypervisor 通过写入 GICH 寄存器列表,向 Guest OS 注入虚拟中断。
当虚拟中断挂起时,硬件会自动将其与物理中断一起呈现给 Guest OS。
Hypervisor 判断这个网络设备被分配给了 VM A。
Hypervisor 通过 CPU 0 的 GICH 寄存器,向正在运行的 VM A 的 vCPU 注入一个虚拟中断。
VM A 的 Guest OS 直接通过 GICV 接口看到并处理这个虚拟中断,完全感知不到 Hypervisor 的介入。
这是 EL1 最核心的控制寄存器之一,定义了系统在 EL1 和 EL0 级别的基本行为。可以把它看作是 EL1/EL0 阶段的“总控制开关面板”。
SCTLR_EL1.M:MMU 使能位。这是最重要的位。置 1 启用 EL1&0 阶段的地址转换(MMU);清 0 则禁用,CPU 直接访问物理地址。
SCTLR_EL1.C:数据缓存使能位。控制 EL1 阶段的数据缓存是否启用。
SCTLR_EL1.I:指令缓存使能位。控制 EL1 阶段的指令缓存是否启用。
SCTLR_EL1.A:对齐检查使能位。置 1 时,启用数据访问的对齐错误检查。
SCTLR_EL1.SA0:SP 对齐检查使能位(EL0)。置 1 时,检查 EL0 下栈指针(SP)的对齐。
SCTLR_EL1.SA:SP 对齐检查使能位(EL1)。置 1 时,检查 EL1 下栈指针(SP)的对齐。
SCTLR_EL1.WXN:写执行从不。置 1 时,标记为可写的内存区域自动变为不可执行,这是重要的安全特性。
SCTLR_EL1.EE:异常字节序。控制 EL1 异常进入时的数据字节序(大端/小端)。
总结:SCTLR_EL1 控制着 CPU 核心的基础运行环境,如内存管理、缓存、安全策略等。
这个寄存器用于控制对特定协处理器和架构特性的访问权限,特别是浮点单元和 SIMD 单元。
CPACR_EL1.FPEN:浮点/SIMD 单元使能位。这是最常用的字段。
控制在 EL1 和 EL0 执行时,是否可以访问浮点/SIMD 寄存器(V0-V31, FPSR, FPCR)。
CPACR_EL1.TTA:通用跟踪访问控制。置 1 时,允许在 EL0 访问跟踪系统寄存器,否则会产生陷阱。
控制 MMU:这是最核心的原因。Guest OS 试图开启或关闭 MMU 必须由 Hypervisor 管理。Hypervisor 需要确保第二阶段地址转换 始终处于有效状态,以维持虚拟机之间的内存隔离。如果 Guest 禁用了 MMU,第二阶段转换会失效,破坏隔离性。
安全与一致性:错误的 SCTLR_EL1 配置(如禁用缓存、禁用对齐检查)可能导致性能急剧下降或产生不可预知的行为,影响整个系统的稳定性。
策略执行:Hypervisor 可能希望强制启用某些安全策略(如 WXN),无论 Guest OS 如何配置。
资源虚拟化:浮点/SIMD 单元是共享资源。如果一个 Guest OS 无限制地使用并破坏了 FP/SIMD 状态,会影响到随后在同一个物理核心上运行的另一个虚拟机。
状态保存/恢复:当 vCPU 被调度出去时,Hypervisor 必须保存其 FP/SIMD 寄存器状态;当它被调度回来时,再恢复。这要求 Hypervisor 知道 Guest 何时使用了这些寄存器。
特性隐藏:Hypervisor 可能想向 Guest OS 隐藏某些硬件特性,或者模拟它们。
SCTLR_EL1 和 CPACR_EL1 都是严格的 Per-CPU 寄存器。
PMCR_EL0 是 性能监控控制寄存器。它是 ARM 架构中整个性能监控单元的性能监控单元的性能监控单元的总控制中心和配置入口点。
总结:PMCR_EL0 是性能监控的“总闸门”,负责启用/禁用整个 PMU、复位计数器、配置计数器的基本行为。通过读取它,软件还可以了解硬件支持的 PMU 功能。
虚拟化 PMCR
资源隔离与公平性:PMU 是共享的硬件资源。如果一个 Guest OS 无限制地使用并配置 PMU,可能会:
Guest OS 期望的性能事件是基于其自身的“虚拟时间”和“虚拟执行”的。如果直接使用物理 PMU,计数值会包含其他虚拟机甚至 Hypervisor 的执行,导致数据完全失真。
恶意 Guest OS 可能通过 PMU 进行侧信道攻击,探测其他虚拟机的活动。
虚拟化感知的性能分析:云提供商可能希望向租户提供虚拟机内部的性能监控服务,这需要为每个虚拟机提供独立的、虚拟化的性能计数器视图。
