Kunit test needs to check whether the pages are preserved after preservation or after unpreserve. The helper function added is only enabled when kunit is enabled. Signed-off-by: Samiullah Khawaja --- include/linux/kexec_handover.h | 5 +++ kernel/liveupdate/kexec_handover.c | 52 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index 8968c56d2d73..a3afc74cf41c 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -32,6 +32,11 @@ void kho_restore_free(void *mem); struct folio *kho_restore_folio(phys_addr_t phys); struct page *kho_restore_pages(phys_addr_t phys, unsigned long nr_pages); void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); + +#if IS_ENABLED(CONFIG_KUNIT) +bool kho_test_pages_preserved(phys_addr_t phys, unsigned long nr_pages); +#endif + int kho_add_subtree(const char *name, void *blob, size_t size); void kho_remove_subtree(void *blob); int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size); diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index 1375291d9b07..f678372b3e81 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -1771,3 +1772,54 @@ int kho_locate_mem_hole(struct kexec_buf *kbuf, return ret == 1 ? 0 : -EADDRNOTAVAIL; } + +#if IS_ENABLED(CONFIG_KUNIT) +static bool _kho_is_pfn_preserved(struct kho_radix_tree *tree, + unsigned long pfn, unsigned int order) +{ + unsigned long key = kho_radix_encode_key(PFN_PHYS(pfn), order); + struct kho_radix_node *node = tree->root; + struct kho_radix_leaf *leaf; + unsigned int i, idx; + + if (!tree->root) + return false; + + guard(mutex)(&tree->lock); + + for (i = KHO_TREE_MAX_DEPTH - 1; i > 0; i--) { + idx = kho_radix_get_table_index(key, i); + + if (!node->table[idx]) + return false; + + node = phys_to_virt(node->table[idx]); + } + + idx = kho_radix_get_bitmap_index(key); + leaf = (struct kho_radix_leaf *)node; + + return test_bit(idx, leaf->bitmap); +} + +bool kho_test_pages_preserved(phys_addr_t phys, unsigned long nr_pages) +{ + struct kho_radix_tree *tree = &kho_out.radix_tree; + unsigned long pfn = PHYS_PFN(phys); + unsigned long end_pfn; + unsigned int order; + + end_pfn = pfn + nr_pages; + while (pfn < end_pfn) { + order = min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn)); + + if (!_kho_is_pfn_preserved(tree, pfn, order)) + return false; + + pfn += 1 << order; + } + + return true; +} +EXPORT_SYMBOL_IF_KUNIT(kho_test_pages_preserved); +#endif -- 2.54.0.563.g4f69b47b94-goog