Skip to content

Commit d64b037

Browse files
georgejguorppt
authored andcommitted
kho: fix KHO_TREE_MAX_DEPTH for non-4KB page sizes
KHO_TREE_MAX_DEPTH is calculated as: DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2, KHO_TABLE_SIZE_LOG2) + 1 For systems with 16KB pages (e.g. arm64 with CONFIG_ARM64_16K_PAGES=y or LoongArch), this gives a depth of 4. Since levels are 0 based, with depth = 4 the effective top level is 3 and the top-level shift at bit 39. PAGE_SHIFT = 14 KHO_BITMAP_SIZE_LOG2 = PAGE_SHIFT + 3 = 17 KHO_TABLE_SIZE_LOG2 = log(2; (1 << PAGE_SHIFT) / 8) = 11 shift = ((3 - 1) * KHO_TABLE_SIZE_LOG2) + KHO_BITMAP_SIZE_LOG2 = 39 The order-0 bit sits at bit 50 (KHO_ORDER_0_LOG2 = 64 - PAGE_SHIFT = 50). When inserting or reading a key, the index extracted at the top level is: (1 << 50) >> 39 = 2048 2048 is exactly the table size (PAGE_SIZE / sizeof(phys_addr_t) = 2048 for 16KB pages), so it wraps to 0, aliasing the order bit to index 0 and losing it silently. On the second kernel, kho_radix_decode_key() sees a key without the order bit, calls fls64() on the wrong bit, computes a wrong order and thus a garbage physical address. phys_to_page() of that address faults in kho_preserved_memory_reserve(), causing a kernel panic early in boot. Fix by adding +1 to the DIV_ROUND_UP numerator so the formula accounts for the order bit itself, giving depth 5 for 16KB pages. The top-level shift becomes 50, and (1 << 50) >> 50 = 1, which is nonzero and unambiguous. For 4KB and 64KB page sizes the depth is unchanged. Link: https://patch.msgid.link/20260509024415.33190-1-dongtai.guo@linux.dev Fixes: 3f2ad90 ("kho: adopt radix tree for preserved memory tracking") Tested-by: Kexin Liu <liukexin@kylinos.cn> Signed-off-by: George Guo <guodongtai@kylinos.cn> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> [rppt: added actual math to the changelog] Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
1 parent e7ae89a commit d64b037

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

include/linux/kho/abi/kexec_handover.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ enum kho_radix_consts {
274274
* and 1 bitmap level.
275275
*/
276276
KHO_TREE_MAX_DEPTH =
277-
DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2,
277+
DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2 + 1,
278278
KHO_TABLE_SIZE_LOG2) + 1,
279279
};
280280

0 commit comments

Comments
 (0)