v3 2026-07-10

KHO支持启动时大页分配 · v3

使KHO机制在启动时正确分配和恢复大页,支持持久化内存状态。

原始补丁链接

子 Patch(21)

1/21
kho: generalize radix tree APIs
将 kho_radix_add/del_page 泛化为 add/del_key,直接操作 key 而非编码 PFN/order,编码逻辑移至调用方,使 radix tree 可被 KHO 其他用户复用。
2/21
kho: make radix max key width more obvious
用 KHO_RADIX_KEY_WIDTH 替代晦涩的 KHO_ORDER_0_LOG2,明确 max key width 来自 52-bit PFN + 1 bit order,简化 kho_encode/decode_radix_key 中的移位与注释。
3/21
kho: disallow wide keys in radix tree
在 kho_radix_add_key() 中校验 key 宽度,若超出当前树支持的最大宽度则返回错误,避免因未来用户误用宽 key 导致树深度增加或 ABI 破坏。
4/21
kho: return virtual address of mem_map
将 kho_get_mem_map_phys() 改为返回虚拟地址并重命名为 kho_get_mem_map(),因后续调用方均需虚拟地址,简化调用逻辑。
5/21
kho: store incoming radix tree in kho_in
将传入的 radix tree 根指针存入 kho_in 结构体,使其他函数也能访问该树;同时复用 kho_get_mem_map_phys() 避免重复解析 FDT 的代码。
6/21
kho: move all memory retrieval logic to kho_mem_retrieve()
将分散在 kho_memory_init() 和 kho_mem_retrieve() 中的内存检索逻辑全部合并到 kho_mem_retrieve() 中,包括 scratch 初始化与错误处理,使代码更清晰。
7/21
kho: add a struct for radix callbacks
引入 struct kho_radix_callbacks 收集 radix tree 的回调函数,替代分散的函数指针参数,为后续增加更多回调做准备。
8/21
kho: add callback for table pages
为 radix tree 遍历添加 table 页回调,在遇到内部节点页时调用,避免因树自身不保留表页导致的内存空洞被忽略,支持外部用户自行保留这些页。
9/21
kho: add data argument to radix walk callback
为 kho_radix_walk_cb_t 回调添加 opaque data 参数,允许调用方通过该指针传递额外上下文信息,增强回调的灵活性。
10/21
kho: allow early-boot usage of the KHO radix tree
在 kho_radix_{alloc,free}_node 中根据 slab_is_available() 选择 buddy 或 memblock 分配器,使 radix tree 可在 early boot 阶段使用,用于跟踪元数据。
11/21
kho: allow destroying KHO radix tree
新增 kho_radix_destroy_tree() 函数,递归释放 radix tree 所有节点页,用于后续 scratch 扩展机制中清理临时创建的 free block 跟踪树。
12/21
kho: add kho_radix_init_tree()
将 radix tree 初始化逻辑封装为 kho_radix_init_tree(),避免调用方重复编写初始化代码,为未来新增 radix tree 用户减少代码冗余。
13/21
kho: expose kho_scratch_overlap() to kexec_handover.h
将 kho_scratch_overlap() 从 debug 文件移至主文件并暴露到头文件,供非 debug 代码(如后续的 free block 发现机制)使用,同时删除已空的 debug 文件。
14/21
kho: initialize kho_scratch pointer earlier in boot
新增 kho_memory_init_early() 在 free_area_init() 前初始化 kho_scratch 指针,使 mm init 能通过 kho_scratch_overlap() 判断 pageblock 迁移类型。
15/21
kho: initialize preserved memory map radix tree earlier
将 preserved memory radix tree 的初始化从 kho_memory_init() 提前到 kho_memory_init_early(),使树在早期即可用于跟踪元数据;简化 kho_mem_retrieve() 错误路径。
16/21
mm/mm_init: init deferred page migratetype in deferred_init_pages()
将 deferred 页的 migratetype 设置从 deferred_free_pages() 移到 deferred_init_pages(),使页初始化更集中,为后续 KHO 更新 scratch 页迁移类型做准备。
17/21
mm/mm_init: don't rely on memblock to get KHO scratch migratetype
移除 kho_scratch_migratetype(),改为在 struct page init 时统一设为 MIGRATE_MOVABLE,再由 KHO 单独将 bootmem scratch 区域更新为 MIGRATE_CMA,避免因内存区域合并导致迁移类型错误。
18/21
kho: extend scratch
通过遍历 preserved memory radix tree 发现无保留页的内存块,将其标记为 MEMBLOCK_KHO_SCRATCH 并加入 scratch 数组,使 KHO 可在 scratch 耗尽时从这些区域分配内存。
19/21
memblock: make HugeTLB bootmem allocation work with KHO
引入 memblock_alloc_hugetlb() 使 HugeTLB 分配不标记为 RSRV_KERN,避免其计入 scratch 大小计算,防止因大页占用过多内存导致 scratch 分配失败。
20/21
memblock: add memblock_reserved_hugetlb_size()
新增 memblock_reserved_hugetlb_size() 函数,返回 memblock 中标记为 RSRV_HUGETLB 的内存总量,供后续 KHO scratch 大小计算时减去大页占用。
21/21
kho: exclude hugetlb memory from scratch size calculation
在计算 KHO scratch 大小时,从 RSRV_KERN 中减去 RSRV_HUGETLB 标记的内存,避免 HugeTLB 页(非 scratch 分配)导致 scratch 规模虚增。