From 8fec6d62030e2276bfce869dbcdaa5e78ef26741 Mon Sep 17 00:00:00 2001 From: Nehckl <56144911+Inquisitor-201@users.noreply.github.com> Date: Sat, 20 Jul 2024 19:09:37 +0800 Subject: [PATCH] Add Documentation for zone config, hvisor structure, percpu struct, and ARM-GIC (#15) --- src/SUMMARY.md | 4 +- src/chap03/ZoneConfig.md | 59 +++++++++++++++++++++++ src/chap03/subchap01/PassThrough.md | 0 src/chap03/subchap01/ZoneConfig.md | 0 src/chap04/Structure.md | 17 +++++++ src/chap04/subchap01/ARMVirtualization.md | 29 +++++++++++ src/chap04/subchap01/PerCPU.md | 51 ++++++++++++++++++++ src/chap04/subchap02/ARM-GIC.md | 51 ++++++++++++++++++++ 8 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/chap03/ZoneConfig.md delete mode 100644 src/chap03/subchap01/PassThrough.md delete mode 100644 src/chap03/subchap01/ZoneConfig.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7cba434..8d26183 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -33,9 +33,7 @@ - [启动两个VM:Linux 和 RTOS](./chap03/BootNonRootRTOS.md) -- [ZONE的配置与管理](./chap03/subchap01/ZoneConfig.md) - - - [设备直通](./chap03/subchap01/PassThrough.md) +- [ZONE的配置与管理](./chap03/ZoneConfig.md) - [命令行工具](./chap03/CMDTools.md) diff --git a/src/chap03/ZoneConfig.md b/src/chap03/ZoneConfig.md new file mode 100644 index 0000000..477f500 --- /dev/null +++ b/src/chap03/ZoneConfig.md @@ -0,0 +1,59 @@ +# Zone的配置和管理 + +hvisor项目作为一款轻量级的hypervisor,它使用了Type-1架构,允许在硬件之上直接运行多个虚拟机(zones)。下面是对zone配置和管理的关键点的详细说明: + +## 资源分配 + +资源如CPU、内存、设备和中断对每个zone都是静态分配的,这意味着一旦分配,这些资源就不会在zones之间动态调度。 + +## Root Zone配置 + +根zone的配置是硬编码在hvisor内部的,以Rust语言编写,并表现为一个C风格的结构体HvZoneConfig。这个结构体包含了zone ID、CPU数量、内存区域、中断信息、内核和设备树二进制(DTB)的物理地址与大小等关键信息。 + +## Non-root Zones配置 + +非root zones的配置则存储在root linux的文件系统中,通常以JSON格式表示。例如: + +```json + { + "arch": "arm64", + "zone_id": 1, + "cpus": [2, 3], + "memory_regions": [ + { + "type": "ram", + "physical_start": "0x50000000", + "virtual_start": "0x50000000", + "size": "0x30000000" + }, + { + "type": "io", + "physical_start": "0x30a60000", + "virtual_start": "0x30a60000", + "size": "0x1000" + }, + { + "type": "virtio", + "physical_start": "0xa003c00", + "virtual_start": "0xa003c00", + "size": "0x200" + } + ], + "interrupts": [61, 75, 76, 78], + "kernel_filepath": "./Image", + "dtb_filepath": "./linux2.dtb", + "kernel_load_paddr": "0x50400000", + "dtb_load_paddr": "0x50000000", + "entry_point": "0x50400000" + } +``` + +- `arch`字段指定了目标架构(例如arm64)。 +- `cpus`是一个列表,指明了分配给该zone的CPU核心ID。 +- `memory_regions`描述了不同类型的内存区域及其物理和虚拟起始地址与大小。 +- `interrupts`列出了分配给zone的中断号。 +- `kernel_filepath`和`dtb_filepath`分别指明了内核和设备树二进制文件的路径。 +- `kernel_load_paddr`和`dtb_load_paddr`则是内核和设备树二进制在物理内存中的加载地址。 +- `entry_point`指定了内核的入口点地址。 + +root linux的管理工具负责读取JSON配置文件并将其转换为C风格的结构体,随后传递给hvisor以启动非root zones。 \ No newline at end of file diff --git a/src/chap03/subchap01/PassThrough.md b/src/chap03/subchap01/PassThrough.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/chap03/subchap01/ZoneConfig.md b/src/chap03/subchap01/ZoneConfig.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/chap04/Structure.md b/src/chap04/Structure.md index e69de29..86b34f2 100644 --- a/src/chap04/Structure.md +++ b/src/chap04/Structure.md @@ -0,0 +1,17 @@ +# hvisor总体架构 + +- CPU虚拟化 + - 架构兼容性:支持aarch64, riscv64, 和loongarch等架构,每种架构有专门的CPU虚拟化组件。 + - CPU分配:采用静态分配方式,预先决定每个虚拟机的CPU资源。 + +- 内存虚拟化 + - 二阶段页表:利用二阶段页表技术,优化内存虚拟化过程。 + +- 中断虚拟化 + - 中断控制器虚拟化:支持ARM GIC、RISC-V PLIC等不同架构的中断控制器虚拟化。 + - 中断处理:管理中断信号的传递和处理流程。 + +- I/O虚拟化 + - IOMMU集成:支持IOMMU,增强DMA虚拟化的效率和安全性。 + - VirtIO标准:遵循VirtIO规范,提供高性能的虚拟设备。 + - PCI虚拟化:实现PCI虚拟化,确保虚拟机可以访问物理或虚拟I/O设备。 \ No newline at end of file diff --git a/src/chap04/subchap01/ARMVirtualization.md b/src/chap04/subchap01/ARMVirtualization.md index e69de29..bb097b0 100644 --- a/src/chap04/subchap01/ARMVirtualization.md +++ b/src/chap04/subchap01/ARMVirtualization.md @@ -0,0 +1,29 @@ +# AArch64下的CPU虚拟化 + +## CPU启动机制 + +在AArch64架构下,hvisor利用`psci::cpu_on()`函数唤醒指定的CPU核心,将其从关闭状态带入运行状态。该函数接收CPU的ID、启动地址以及一个不透明参数作为输入。遇到错误时,如CPU已处于唤醒状态,函数会进行适当的错误处理避免重复唤醒。 + +## CPU虚拟化初始化与运行 + +`ArchCpu`结构体封装了特定于架构的CPU信息和功能,其`reset()`方法负责将CPU设置为虚拟化模式的初始状态。这包括: + +- 设置ELR_EL2寄存器至指定的入口点 +- 配置SPSR_EL2寄存器 +- 清空通用寄存器 +- 重置虚拟机相关寄存器 +- `activate_vmm()`,激活虚拟内存管理器(VMM) + +`activate_vmm()`方法用于配置VTCR_EL2和HCR_EL2寄存器,启用虚拟化环境。 + +`ArchCpu`的`run()`和`idle()`方法分别用于启动和闲置CPU。启动时,激活zone的GPM(Guest Page Management),重置到指定的入口点和设备树二进制(DTB)地址,然后通过`vmreturn`宏跳转到EL2入口点。在闲置模式下,CPU被重置到等待状态(WFI),并准备`parking`指令页面以供闲置期间使用。 + +## EL1与EL2之间的切换 + +hvisor在AArch64架构中使用EL2作为hypervisor模式,而EL1用于guest OS。`handle_vmexit`宏处理从EL1到EL2的上下文切换(VMEXIT事件),保存用户模式寄存器上下文,调用外部函数处理退出原因,之后返回到hypervisor代码段继续执行。`vmreturn`函数用于从EL2模式回到EL1模式(VMENTRY事件),恢复用户模式寄存器上下文后,通过`eret`指令返回到guest OS的代码段。 + +## MMU配置与启用 + +为了支持虚拟化,`enable_mmu()`函数在EL2模式下配置MMU映射,包括设置MAIR_EL2、TCR_EL2和SCTLR_EL2寄存器,允许指令和数据缓存能力,并确保虚拟范围覆盖整个48位地址空间。 + +通过这些机制,hvisor在AArch64架构上实现了高效的CPU虚拟化,允许多个独立的zones在静态分配的资源下运行,同时保持系统稳定性和性能。 \ No newline at end of file diff --git a/src/chap04/subchap01/PerCPU.md b/src/chap04/subchap01/PerCPU.md index e69de29..d1b53a9 100644 --- a/src/chap04/subchap01/PerCPU.md +++ b/src/chap04/subchap01/PerCPU.md @@ -0,0 +1,51 @@ + +# PerCPU结构体 + +在hvisor的架构中,PerCpu结构体扮演着核心角色,用于实现每个CPU核心的本地状态管理以及支持CPU虚拟化。下面是对PerCpu结构体及相关函数的详细介绍: + +## PerCpu结构体定义 + +PerCpu结构体被设计为每个CPU核心存储其特定数据和状态的容器。它的布局如下: + +``` +#[repr(C)] +pub struct PerCpu { + pub id: usize, + pub cpu_on_entry: usize, + pub dtb_ipa: usize, + pub arch_cpu: ArchCpu, + pub zone: Option>>, + pub ctrl_lock: Mutex<()>, + pub boot_cpu: bool, + // percpu stack +} +``` + +各字段定义如下: + +``` + id: CPU核心的标识符。 + cpu_on_entry: 一个用于追踪CPU进入状态的地址,初始化为INVALID_ADDRESS,表示无效地址。 + dtb_ipa: 设备树二进制的物理地址,同样初始化为INVALID_ADDRESS。 + arch_cpu: 一个指向ArchCpu类型的引用,ArchCpu包含特定于架构的CPU信息和功能。 + zone: 一个可选的Arc>类型,表示当前CPU核心正在运行的虚拟机(zone)。 + ctrl_lock: 一个互斥锁,用于控制访问和同步PerCpu的数据。 + boot_cpu: 一个布尔值,指示是否为引导CPU。 +``` + +## PerCpu的构造和操作 + +``` + PerCpu::new: 此函数创建并初始化PerCpu结构体。它首先计算结构体的虚拟地址,然后安全地写入初始化数据。对于RISC-V架构,还会更新CSR_SSCRATCH寄存器来存储ArchCpu的指针。 + run_vm: 当调用此方法时,如果当前CPU不是引导CPU,则会先将其置于空闲状态,然后再运行虚拟机。 + entered_cpus: 返回已进入虚拟机运行状态的CPU核心数。 + activate_gpm: 激活所关联zone的GPM(Guest Page Management)。 +``` + +## 获取PerCpu实例 + +``` + get_cpu_data: 提供基于CPU ID获取PerCpu实例的方法。 + this_cpu_data: 返回当前执行CPU的PerCpu实例。 +``` + diff --git a/src/chap04/subchap02/ARM-GIC.md b/src/chap04/subchap02/ARM-GIC.md index e69de29..1209fa8 100644 --- a/src/chap04/subchap02/ARM-GIC.md +++ b/src/chap04/subchap02/ARM-GIC.md @@ -0,0 +1,51 @@ +# ARM GICv3模块 + +## 1. GICv3模块 + +### GICv3初始化流程 + +hvisor中的GICv3初始化流程涉及了GIC分布控制器(GICD)和GIC重新分布控制器(GICR)的初始化,以及中断处理和虚拟中断注入的机制。这一过程的关键步骤: + +- SDEI版本检查:通过smc_arg1!(0xc4000020)获取Secure Debug Extensions Interface (SDEI)的版本信息。 +- ICCs配置:设置icc_ctlr_el1以仅提供优先级下降功能,设置icc_pmr_el1以定义中断优先级掩码,使能Group 1 IRQs。 +- 清除待处理中断:调用gicv3_clear_pending_irqs函数,清除所有待处理的中断,确保系统处于干净状态。 +- VMCR和HCR配置:设置ich_vmcr_el2和ich_hcr_el2寄存器,使能虚拟化CPU接口,准备虚拟中断处理。 + +### 待处理中断处理 + +- `pending_irq`函数读取`icc_iar1_el1`寄存器,返回当前正在处理的中断ID,若值大于等于0x3fe则视为无效中断。 +- `deactivate_irq`函数通过写入`icc_eoir1_el1`和`icc_dir_el1`寄存器来清除中断标志,使能中断。 + +### 虚拟中断注入 + +- `inject_irq`函数检查是否有可用的`List Register (LR)`,并将虚拟中断信息写入其中。此函数区分硬件中断和软件生成中断,适当设置LR中的字段。 + +### GIC数据结构初始化 + +- GIC是一个全局的Once容器,用于延迟初始化Gic结构体,其中包含了GICD和GICR的基地址及其大小。 +- primary_init_early和primary_init_late函数分别在早期和后期初始化阶段配置GIC,使能中断。 + +### 区域(Zone)级别的初始化 + +在Zone结构体中,`arch_irqchip_reset`方法负责重置分配给特定zone的所有中断,通过直接写入GICD的ICENABLER和ICACTIVER寄存器来实现。 + +## 2. vGICv3模块 + +hvisor的VGICv3(Virtual Generic Interrupt Controller version 3)模块提供了对ARMv8-A架构中GICv3的虚拟化支持。它通过MMIO(Memory Mapped I/O)访问和中断比特图管理来控制和协调不同zone(虚拟机实例)间的中断请求。 + +### MMIO区域注册 + +在初始化阶段,`Zone`结构体的`vgicv3_mmio_init`方法注册了GIC分布控制器(GICD)和每个CPU的GIC重新分布控制器(GICR)的MMIO区域。MMIO区域注册是通过`mmio_region_register`函数完成的,该函数关联了特定的处理器或中断控制器地址,以及相应的处理函数`vgicv3_dist_handler`和`vgicv3_redist_handler`。 + +### 中断比特图初始化 + +`Zone`结构体的`irq_bitmap_init`方法用于初始化中断比特图,这是为了跟踪哪些中断属于当前`zone`。通过遍历提供的中断列表,每个中断都会被插入到比特图中。`insert_irq_to_bitmap`函数负责将特定的中断号映射到比特图中的相应位置。 +MMIO访问限制 + +`restrict_bitmask_access`函数用于限制对`GICD`寄存器的`MMIO`访问,确保只有属于当前`zone`的中断才能被修改。该函数检查访问是否针对当前zone的中断,如果是,则更新访问掩码,以允许或限制特定的读写操作。 + +### VGICv3 MMIO处理 + +`vgicv3_redist_handler`和`vgicv3_dist_handler`函数分别处理GICR和GICD的MMIO访问。`vgicv3_redist_handler`函数处理GICR的读写操作,检查是否访问的是当前`zone`的GICR,如果是,则允许访问;否则,忽略该访问。`vgicv3_dist_handler`函数根据不同的GICD寄存器类型,调用`vgicv3_handle_irq_ops`或`restrict_bitmask_access`函数,以适当地处理中断路由和配置寄存器的访问。 + +通过上述机制,hvisor能够有效地管理跨zone的中断,确保每个zone只能够访问和控制分配给它的中断资源,同时提供必要的隔离性。这使得在多zone环境中,VGICv3能够高效、安全地工作,支持复杂的虚拟化场景。