跳到主要内容

Axvisor 客户机地址空间设计与实现

virtualization/axaddrspace 管理 Guest Physical Address(客户机物理地址,GPA)范围、客户机 RAM 后备页策略和第二阶段地址映射。它位于通用虚拟内存区域容器与具体架构嵌套页表之间,不管理客户机进程虚拟地址,也不替代宿主 ArceOS 的第一阶段地址空间。

1. 组件边界

axaddrspace 是 Axvisor 的客户机内存策略层。虚拟区域查找、拆分与收缩由 ax-memory-set 提供,通用遍历算法由 page-table-generic 提供,具体页表项格式、宿主页来源与架构适配由 axvm 拥有。

1.1 职责划分

本组件只维护客户机地址空间特有的不变量,不把宿主分配器、架构寄存器或设备生命周期纳入自身状态。

能力负责组件axaddrspace 的边界
GPA 类型与映射权限axvm-types直接复用,不重复定义地址类型或 flags
地址区间集合ax-memory-setBackend<Npt> 实现直接 MappingBackend 操作
客户机 RAM 策略axaddrspace区分外部线性内存与自身分配后备页
第二阶段页表机制page-table-generic仅通过 NestedPageTableOps 使用
宿主页分配与地址转换axvm::HostPagingHandler由页表适配器注入,不直接依赖 ax-alloc
虚拟机布局与生命周期axvm创建、加锁、装载、停止虚拟处理器并销毁资源
架构页表根寄存器各架构虚拟处理器实现axaddrspace 只公开根物理地址和层数

axaddrspace 的生产依赖中没有具体页表实现。组件测试通过开发依赖 page-table-generic 构造 mock nested page table;生产构建由 axvm 实现第二阶段页表并组合 axaddrspace

1.2 依赖方向

依赖从虚拟机策略指向公共机制,页表和物理页能力通过 trait 注入。该方向使地址空间可使用测试页表,也避免公共页表反向绑定 ArceOS 分配器。

Axvisor 客户机地址空间组件边界

运行时真实链路是 AxVM → AddrSpace<ArchNestedPageTable> → NestedPageTableOps → page-table-genericaxaddrspace 不应增加只转发这些调用的页表 facade,也不应直接调用 ax-alloc 形成第二个宿主页入口。

2. 地址与状态模型

客户机执行一次内存访问时可能经过三种地址域。文档和源码必须区分地址语义,不能因为底层均以 usize 保存就混用。

2.1 三种地址域

Guest Virtual Address(客户机虚拟地址,GVA)由客户机自身第一阶段页表翻译;axaddrspace 从 GPA 开始工作,并把它翻译为 Host Physical Address(宿主机物理地址,HPA)。宿主软件访问内容时,再由平台直接映射把 HPA 转成 Host Virtual Address(宿主机虚拟地址,HVA)。

客户机进程访问
GVA
│ 客户机第一阶段页表:由客户机操作系统维护

GPA
│ axaddrspace + 宿主第二阶段页表

HPA
│ HostPagingHandler::phys_to_virt

HVA

AddrSpace 的查询、映射和缺页接口全部接收 GuestPhysAddr。客户机内部的 GVA、Linux 虚拟内存区域和客户机页缓存均不属于该组件。

2.2 地址空间对象

virtualization/axaddrspace/src/address_space/mod.rs 中的核心对象只保存允许的 GPA 总范围、已登记区域和一个嵌套页表实例。

pub struct AddrSpace<Npt: NestedPageTableOps> {
va_range: GuestPhysAddrRange,
areas: MemorySet<Backend<Npt>>,
pt: Npt,
}

字段名 va_range 沿用地址空间容器的历史命名,但其实际类型是 GuestPhysAddrRange。这不是客户机虚拟地址范围,单纯更名不会改变接口语义,当前没有必要为此扩大代码改动。

字段所有权不变量
va_rangeAddrSpace所有公开 map/unmap 请求必须完全落在半开区间内
areasAddrSpace区域不重叠;每次成功 backend 操作后更新元数据
ptAddrSpace页表根、子页表页和查询能力由具体 Npt 管理

new_empty(page_table, base, size) 使用 checked addition 验证总范围。它接收已经构造完成的页表,而不是只接收层数后在内部选择架构实现。

2.3 公共操作

公开操作围绕 GPA 区间组织。当前没有对外公开 protect;权限修改能力只存在于通用 backend 协议中,不能在文档中把它写成 AddrSpace 已提供的公共入口。

操作输入结果
map_linearGPA、已知 HPA、长度、权限建立固定偏移的第二阶段映射
map_allocGPA、长度、权限、是否立即填充建立由 adapter 分配宿主页的区域
unmapGPA 与长度直接移除相交区域和页表项
clear清空全部区域;用于重置和销毁
handle_page_faultfault GPA 与访问权限为懒分配区域补一个基础页
translateGPA查询 HPA,不建立新映射
translated_byte_bufferGPA 与长度将同一区域内的范围切成宿主可访问片段
page_table_root / page_table_levels向虚拟处理器配置层提供页表信息

map_linearmap_allocunmap 要求 GPA、HPA 和长度满足 4 KiB 对齐。范围越界、地址算术溢出、对齐错误和映射冲突均返回可匹配的 AddrSpaceError

3. 后端与内存所有权

Backend<Npt> 只有 LinearAlloc 两种。两者使用相同虚拟区域容器,但后备内存的 owner 和解除映射后的动作完全不同。

3.1 线性映射

Linear 保存 GPA - HPA 的有符号差值。使用 i128 可以同时表示 HPA 低于 GPA 和 HPA 高于 GPA 的情况,实际换算仍通过 checked subtraction 与 usize::try_from 拒绝越界。

pub enum Backend<Npt: NestedPageTableOps> {
Linear {
pa_to_va_delta: i128,
},
Alloc {
populate: bool,
_phantom: core::marker::PhantomData<Npt>,
},
}

线性映射的 HPA 由调用方拥有。unmap_linear() 只删除页表项,不调用 dealloc_frame();虚拟机销毁时,外层 VMMemoryRegion 或平台保留内存 owner 决定是否释放实际内存。

map_linear()allow_huge 设为 true,因此连续、对齐且属性一致的范围可由第二阶段页表选择大页。具体页尺寸选择和架构页表项编码见页表分层与实现

3.2 分配型映射

Alloc { populate } 通过 NestedPageTableOps::alloc_frame() 获取宿主基础页。populate = true 在 map 提交时逐页分配并映射;populate = false 只发布区域元数据,首次客户机访问再由缺页路径分配。

下面的构造调用只保存映射策略和 populate 选择,实际 frame 分配发生在 backend 的 map 或 fault 回调中;MemoryArea 本身不会预先取得宿主页。

let area = MemoryArea::new(start, size, flags, Backend::new_alloc(populate));
self.areas.map(area, &mut self.pt, false)?;

立即填充路径逐页“分配 + 映射”,当前实现在第 N 页失败时直接返回 false,不清理此前已建立的前缀映射,map 失败时刚取得的 frame 也不会归还——这是当前实现的已知遗留(已映射前缀与页帧泄漏,靠后续 clear() 或销毁回收)。懒分配路径取得 frame 后调用 remap();当前实现同样不在 remap 失败时调用 dealloc_frame

当前 AxVM 的生产内存布局先由宿主分配 VMMemoryRegion,再使用 map_linear() 建立客户机映射;仓库内 map_alloc() 的直接调用目前集中在 axaddrspace 测试。Alloc 是已实现的组件能力,但不能据此宣称现有 AxVM 默认使用按需 Guest RAM。

3.3 所有权转移

解除映射与释放内存必须分开判断。只有 Alloc 获得的 frame 才由 backend 在页表项成功移除后释放。

资源创建者映射期间 owner解除映射或销毁
Linear 后备 RAMAxVM、平台或外部调用方外部 owner仅删除页表项,外部 owner 释放
Alloc 后备页NestedPageTableOps::alloc_frameBackend::Allocunmap_alloc 调用 dealloc_frame
第二阶段根和子页表页具体 Npt嵌套页表对象Npt 析构时由同一 frame provider 释放
地址区域元数据MemorySetAddrSpacebackend 操作成功后删除或拆分
设备模拟缓冲区设备模型或 DMA owner对应设备对象不由 Guest RAM backend 隐式释放

分配型 unmap 对每个存在的 4 KiB 页表项执行 unmap,成功后立即调用 dealloc_frame。当前实现的顺序是先执行 pt.unmap(addr),成功后才检查 page_size.is_huge() 并返回 false——即遇到大页首项时该页表项已被删除、frame 不释放,调用方收到失败结果;因此该路径只能安全处理纯 4 KiB 的分配型区域。公共层不保存逐页撤销日志,跨多个区域的后续失败不会恢复已经成功删除的前缀。

4. 直接映射与缺页

axaddrspace::Backend<Npt> 实现 ax_memory_set::MappingBackendMemorySet 负责区域重叠检查和边界拆分,backend 直接调用 NestedPageTableOps。公共路径没有 MappingPlan、逐页快照或 finalize 阶段。

4.1 映射调用

AddrSpace 的 map/unmap 先在客户机物理地址域验证总范围与 4 KiB 对齐,再由 MemorySet 定位区域并调用 Backend<Npt>。下图强调页表动作成功后才提交相应区域元数据,但不表示跨区域操作具备通用回滚事务。

Linear map 直接调用 map_region(..., allow_huge = true),不为目标范围建立软件页快照。Alloc { populate: true } 按 4 KiB 页分配;中途失败时当前实现直接返回 false,不清理已安装前缀(见 3.2 节)。Alloc unmap 允许懒分配区域内存在空洞,但只在 unmap 成功后检查大页:遇到大页首项时该项已被删除且 frame 不释放并返回失败,纯 4 KiB 区域则逐项删除并立即释放 frame。

4.2 失败边界

单个分配型 map 当前不保证清理本次新建的前缀(见 3.2 节的遗留行为),审查内存压力下的失败路径时应以此为前提。跨多个 MemoryArea 的 unmap/clear 不提供全成或回滚:后续 backend 失败时,前面已经删除的页表项和 frame 不会恢复。AxVM 当前生产布局主要使用经过预验证的 Linear 映射,并在停止虚拟处理器后销毁;如果未来需要面向不可信动态请求的原子客户机重映射,应在 AxVM 策略层增加专用预检,而不是恢复通用逐页快照。

4.3 懒分配缺页

AddrSpace::handle_page_fault() 先验证 fault GPA 位于总范围和某个已登记区域内,再检查原区域权限是否包含本次访问。只有 Alloc { populate: false } 会尝试补页。

let Some(frame) = pt.alloc_frame() else {
return false;
};
pt.remap(vaddr, frame, orig_flags)

remap() 失败时当前实现不归还刚取得的 frame,与立即填充路径的遗留行为一致。缺页路径一次只处理一个 4 KiB 页,不执行回收、阻塞或内部重试。宿主分配失败直接返回 false,上层虚拟处理器异常处理决定如何终止、注入异常或采取其他策略。

5. 第二阶段页表适配

NestedPageTableOpsaxaddrspace 与具体架构之间的最小能力边界。它同时提供页表操作和 allocation-backed Guest RAM 所需的宿主页能力,但不暴露具体页表项类型。

5.1 能力接口

virtualization/axaddrspace/src/paging.rs 定义的接口可分为页表身份、frame provider、单项操作和范围操作四组。

方法组方法用途
页表身份root_paddr()levels()创建虚拟处理器硬件配置
宿主页能力alloc_frame()dealloc_frame()phys_to_virt()Alloc 后备页与宿主访问
单项操作map()unmap()remap()query()缺页、恢复和地址翻译
范围操作map_region()unmap_region()protect_region()Linear 范围映射与权限修改

PageSize 当前表达 4 KiB、1 MiB、2 MiB 和 1 GiB。adapter 根据页表查询得到的层级和大页位转换尺寸,backend 回滚时使用实际尺寸,不自行推断架构几何。

5.2 通用适配器

virtualization/axvm/src/npt.rsGenericFrameAllocator<H>HostPagingHandler 接到 page_table_generic::FrameAllocator,再由 LeveledPageTable 实现 NestedPageTableOps。这个适配器同时保持页表帧来源、主机物理地址转换和架构几何的类型关系,不让 axaddrspace 直接依赖某个宿主 allocator。

HostPagingHandler
│ alloc_frame / dealloc_frame / phys_to_virt

GenericFrameAllocator<H>
│ FrameAllocator

page_table_generic::PageTable
│ map / unmap / query / protect

LeveledPageTable
│ NestedPageTableOps

axaddrspace::AddrSpace

HostPagingHandler 最终调用 AxVM 私有 ArceOS host adapter 的 HostMemory 能力。axaddrspace 因此只知道“可申请一个宿主页”,不知道 Buddy section、内存 zone 或 GlobalPage 的具体表示。

5.3 架构差异

所有架构向 AddrSpace 暴露同一 NestedPageTableOps,差异留在 axvm/src/arch/<arch>/npt.rs 或 x86 嵌套分页运行时中。这样 GPA 区域策略只处理统一的页尺寸与权限结果,页表项编码、根寄存器和失效指令仍由相应架构所有者维护。

架构AxVM 具体类型本层可见差异
AArch64LeveledPageTable<A64HVPagingMetaDataL3, A64HVPagingMetaDataL4, HostPagingHandler, true>支持三层或四层,使用第二阶段页表项与对应失效操作
RISC-VLeveledPageTable<Sv39x4MetaData, Sv48x4MetaData, HostPagingHandler, true>支持 Sv39x4 或 Sv48x4 几何
LoongArch64LeveledPageTable<LoongArchPagingMetaDataL3, LoongArchPagingMetaDataL4, HostPagingHandler, true>支持三层或四层架构元数据
x86_64运行时选择 Extended Page Table(扩展页表,EPT)或 Nested Page Table(嵌套页表,NPT)CPU backend 初始化后固定页表项编码,当前使用四层表

页表项位定义、页表根寄存器和 Translation Lookaside Buffer(地址转换后备缓冲区,TLB)失效指令由多架构内存实现唯一维护。本组件只要求 adapter 在返回成功前完成页表核心规定的失效协议。

6. AxVM 集成流程

axvm 持有 AddrSpace<ArchNestedPageTable>,并把地址空间放入虚拟机生命周期资源。创建、布局发布、客户机访问和销毁都经过该 owner,普通虚拟设备不直接取得可变页表引用。

6.1 创建地址空间

AxVMResources::from_page_table() 使用架构层已创建的页表构造地址空间,当前 GPA 总范围是 [0, 0x7fff_ffff_f000)。随后读取页表根并构造架构硬件配置。

let address_space = AddrSpace::new_empty(
page_table,
GuestPhysAddr::from(VM_ASPACE_BASE),
VM_ASPACE_SIZE,
)?;
let nested_paging = build_nested_paging(address_space.page_table_root())?;

页表层数和可寻址 GPA 位数由架构 NestedPagingConfig 约束。总范围只是软件容器上限,不能绕过架构实际地址宽度校验。

6.2 发布客户机布局

virtualization/axvm/src/vm/prepare/address_space.rs 先由 build_address_layout() 合并客户机 RAM、启动描述、保留区、直通范围和模拟设备资源,再逐项调用 map_linear()

当前生产布局使用 Linear 的原因是宿主侧 VMMemoryRegion 已持有连续 HVA/HPA 和 Layout,映射层不能再次取得同一内存的所有权。若未来生产路径使用 map_alloc(),必须同时定义如何向装载器、设备和销毁流程暴露非连续后备页,不能只替换一个调用。

6.3 客户机内存访问

AxVM 的 read_from_guest()write_to_guest() 和镜像装载路径在持有虚拟机资源锁的闭包内调用 translated_byte_buffer()。该方法逐次查询第二阶段页表,将一个区域内的访问切成不跨页表映射边界的宿主 slice。

translated_byte_buffer() 不允许访问跨越两个 MemoryArea,即使两个区域地址相邻;范围终点超过当前区域就返回 None。它也不会为懒分配区域自动触发缺页,未建立页表项时查询失败。

crate 还导出 GuestMemoryAccessor,为实现者提供对象和跨翻译区间的 buffer 读写默认方法。当前生产 AxVM 没有为 AddrSpace 实现该 trait,而是直接使用上述分片接口,因此两条能力不能混写成同一调用链。

6.4 销毁顺序

虚拟机销毁先停止并等待虚拟处理器任务,再清除地址空间,最后释放外部 VMMemoryRegion 和设备对象。该顺序防止硬件继续使用已经解除映射或归还分配器的内存。

AxVM::destroy
-> stop_and_join_runtime
-> cleanup_resource_set
-> address_space.clear()
-> remove Stage-2 entries
-> finalize Alloc-owned frames
-> dealloc VMMemoryRegion with needs_dealloc = true
-> drop devices / vCPU list / interrupt fabric
-> drop nested page table

AddrSpace::drop() 也会调用 clear() 作为最后防线;clear() 内部对区域删除使用 unwrap(),清理失败会直接 panic 而不是记录后吞掉。clear() 本身返回 (),调用方无法在其返回值上处理错误,正常生命周期必须在 Drop 前显式完成清理并保证条件成立。

7. 锁、并发与安全边界

AddrSpaceMemorySet 和具体页表都不为单个实例内置全局锁。可变操作要求 &mut self,生产环境由 AxVM 的虚拟机资源 owner 提供串行化。

7.1 外层锁

virtualization/axvm/src/vm/mod.rs 通过 use ax_std::os::arceos::sync::IrqSafeMutex as Mutex 引入关中断自旋锁,并以 Mutex<Machine<AxVMResources, Arc<VmRuntimeHandle>>> 保护地址空间和生命周期状态。映射、缺页、客户机缓冲区访问与 clear 都必须在这个 VM owner 下串行化,避免 slice 或页表查询跨越资源销毁。

fn with_resources_mut<F, R>(&self, f: F) -> AxVmResult<R>
where
F: FnOnce(&mut AxVMResources) -> AxVmResult<R>,
{
let mut machine = self.machine.lock();
let resources = machine
.resources_mut()
.ok_or_else(|| ax_err_type!(BadState, "VM resources are not available"))?;
f(resources)
}

map_region()unmap_region()、缺页处理和客户机内存读写均通过 with_resources()with_resources_mut() 执行。单次区域操作期间锁不会释放,另一个虚拟处理器或设备处理路径不能并发修改同一页表。

7.2 禁止中断临界区

IrqSafeMutex(基于 ax_sync::SpinLock + lock_irqsave)表示地址空间操作期间本 CPU 中断关闭。页表遍历、页表页建立和宿主页分配都可能发生在该临界区,因此它保证一致性但不保证硬实时延迟。

路径临界区内可能发生的工作约束
Linear map区间查询、页表页分配、大范围页表建立不执行文件系统或回收 callback
Alloc populate每个 4 KiB 页分配和映射不用于硬实时路径;失败不回滚前缀(见 3.2 节)
Alloc fault一个 frame 分配与 remap不阻塞、不内部重试
unmap/clear删除映射、失效翻译、释放 Alloc frame虚拟处理器必须已停止或与更新同步
guest buffer access查询页表并复制数据slice 不得逃逸出锁保护的闭包

完整锁顺序和禁止组合只在内存管理锁与并发维护。该组件不得在持有分配器内部锁时反向获取虚拟机 machine 锁。

7.3 不安全内存访问

translated_byte_buffer() 使用 phys_to_virt() 得到的地址构造 &'static mut [u8]GuestMemoryAccessor 默认方法还使用裸指针进行 volatile 或 non-overlapping copy。这些操作的安全性依赖 adapter 和调用方共同满足以下条件。

前置条件维护者
HPA 对应有效且当前可访问的宿主直接映射HostPagingHandler::phys_to_virt 实现
slice 覆盖范围没有越过实际页表映射query() 返回的页尺寸与范围切分逻辑
同一物理内存不存在并发可变 Rust 引用AxVM 外层锁和调用方生命周期
返回 slice 不在解除映射、清理或释放后继续使用调用方必须在锁闭包内立即消费
设备或虚拟处理器不会在缺少协议时并发修改内容虚拟机生命周期和设备队列协议

'static 是当前接口表达宿主直接映射的方法,不表示数据真的可脱离虚拟机生命周期永久保存。任何把这些 slice 缓存到 AxVMResources 之外的实现都会破坏清理顺序和别名约束。

GuestMemoryAccessor 的默认实现会把 translate_and_get_limit() 返回的 PhysAddr 数值直接转换为裸指针,而不会再调用 phys_to_virt()。因此实现该 trait 的 translator 当前必须返回可被宿主直接解引用的地址表示;仓库测试通过 mock 转换满足这一前提,生产 AxVM 没有使用该 trait。不能把普通 HPA 原样返回给默认方法,除非平台明确保证物理地址与可解引用虚拟地址恒等。

AddrSpace::translate_and_get_limit() 当前返回整个 MemoryArea::size(),而不是从任意输入 GPA 到区域末尾的剩余长度;同时 AddrSpace 并未实现 GuestMemoryAccessor。在修正该语义前,不能把该方法直接接到以“剩余可访问字节数”为契约的通用 accessor。

8. 映射实例

下面的实例只展示 axaddrspace 自身可观察的状态,不重复页表核心内部逐级建表算法。地址均采用半开区间,权限用 RWX 表示读、写、执行。

8.1 线性客户机 RAM

假设 AxVM 已分配 128 MiB 宿主连续内存 HPA [0x4800_0000, 0x5000_0000),客户机希望把它作为 GPA [0x8000_0000, 0x8800_0000) 的可读写 RAM。

address_space.map_linear(
GuestPhysAddr::from_usize(0x8000_0000),
PhysAddr::from_usize(0x4800_0000),
0x0800_0000,
MappingFlags::READ | MappingFlags::WRITE,
)?;

此时 pa_to_va_delta = 0x3800_0000。查询 GPA 0x8123_4000 得到 HPA 0x4923_4000;若 GPA、HPA 和长度满足具体架构的大页条件,页表核心可用较大 block 减少页表项与 TLB 压力。

GPA 0x8000_0000 0x8800_0000
+---------------------------------------------------+
| Guest RAM 128 MiB |
+---------------------------------------------------+
│ fixed signed delta

HPA 0x4800_0000 0x5000_0000
+---------------------------------------------------+
| VMMemoryRegion owned by outer AxVM |
+---------------------------------------------------+

解除该映射只删除第二阶段页表项。之后 AxVM 根据 VMMemoryRegion::needs_dealloc 和原 Layout 释放 HVA/HPA 后备内存。

8.2 懒分配区域

假设组件调用方建立 GPA [0x4000_0000, 0x4000_4000) 的 16 KiB 懒分配区。map 成功后 MemorySet 有一个区域,但第二阶段页表暂时没有四个基础页映射。

map_alloc(populate = false)
area metadata: [0x4000_0000, 0x4000_4000) R|W
page table: unmapped, unmapped, unmapped, unmapped

guest writes GPA 0x4000_1234
-> permission check succeeds
-> alloc_frame()
-> align/remap GPA page 0x4000_1000
-> page table: unmapped, mapped, unmapped, unmapped

随后 unmap(0x4000_0000, 0x4000) 允许三个页仍未映射,只移除实际存在的第二个页,并立即释放该 frame。

8.3 大范围 Linear 映射

假设 Linear 区域 [0, 128 MiB) 满足 2 MiB 对齐与连续性,页表核心可以建立 64 个 2 MiB block。ax-memory-set 只保存一个 MemoryArea,不会为 32,768 个基础页构造软件记录。

若后续操作范围从 0x1000 开始并切入首个 2 MiB block 中部,能否拆分由具体 NestedPageTableOps 决定。axaddrspace 不维护逐页恢复日志,也不应把不支持的局部大页修改伪装成成功。

9. 源码定位与修改边界

axaddrspace 的实现文件较少,但修改任一 trait 或所有权规则都必须同时检查 AxVM adapter、虚拟机生命周期和通用 MemorySet 协议。

9.1 源码入口

以下文件构成从公共 API 到生产第二阶段页表的完整路径。审查时应沿着 AddrSpace、backend、NestedPageTableOps 和 AxVM adapter 向下核对,而不是只验证区域元数据或单个页表函数。

源码维护内容
virtualization/axaddrspace/src/address_space/mod.rsAddrSpace 状态、范围验证、公共 map/unmap/fault/query
virtualization/axaddrspace/src/address_space/backend/mod.rsLinear/Alloc dispatch 与 MappingBackend 适配
virtualization/axaddrspace/src/address_space/backend/linear.rs固定偏移换算与 Linear 范围操作
virtualization/axaddrspace/src/address_space/backend/alloc.rseager/lazy frame 分配、缺页和失败清理
virtualization/axaddrspace/src/paging.rsNestedPageTableOpsPageSize
virtualization/axaddrspace/src/memory_accessor.rs客户机对象和 buffer 访问 capability
virtualization/axaddrspace/src/error.rs类型化范围、映射和访问错误
virtualization/axvm/src/npt.rs通用 Stage-2 adapter 与 frame provider 桥接
virtualization/axvm/src/arch/*/npt.rs架构页表项元数据和失效实现
virtualization/axvm/src/vm/prepare/address_space.rs生产客户机布局到 Linear 映射的接线
virtualization/axvm/src/vm/mod.rs外层锁、内存访问和销毁顺序

巨大 Linear 映射、frame 释放和各架构构建的测试见内存管理测试

9.2 明确不负责的能力

下列能力不应塞入 axaddrspace,否则会把客户机策略、宿主机制和设备生命周期重新耦合。

非职责正确位置
客户机 GVA、进程虚拟内存区域、写时复制和文件映射客户机操作系统自身
宿主内核第一阶段地址空间ArceOS ax-mm
页表遍历算法page-table-generic
页表项编码和 TLB 指令AxVM 架构 adapter
Buddy、Slab、内存 zone 和回收策略ax-alloc 及上层系统策略
输入输出内存管理单元 domain 与设备 DMA bufferdma-api 和具体设备/domain adapter
虚拟设备地址冲突、直通窗口和启动布局axvm::layout 与设备管理层
虚拟处理器停止、暂停和销毁状态机axvm 生命周期层

扩展客户机内存能力时,应先判断变化属于“地址区域策略”“第二阶段页表机制”还是“宿主资源 owner”。只有前者进入 axaddrspace;后两者分别进入页表核心/架构 adapter 和 AxVM host/lifecycle 层。