[PATCH v1 1/4] PM: hibernate: Add arch specific hooks for hibernate_map/unmap_page
flat view
COLD18d
From: Vincent Donnefort <hidden>
Date: 2026-09-18 13:19:03
Also in:
linux-pm, lkml
Subsystem:
hibernation (aka software suspend, aka swsusp), suspend to ram, the rest · Maintainers:
"Rafael J. Wysocki", Linus Torvalds
hibernate_map_page() is called from an atomic context. This is problematic for Arm BBML3 systems where the linear map may contain blocks and is allowed to split as splitting is a sleepable operation. Add arch hook so arm64 can define its own implementation without relying on the direct map. Signed-off-by: Vincent Donnefort <redacted> --- include/linux/suspend.h | 2 ++ kernel/power/snapshot.c | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index b02876f1ae38..10fe2298d94e 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h@@ -401,6 +401,8 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data); int hibernate_resume_nonboot_cpu_disable(void); int arch_hibernation_header_save(void *addr, unsigned int max_size); int arch_hibernation_header_restore(void *addr); +void *hibernate_map_page(struct page *page); +void hibernate_unmap_page(struct page *page); #else /* CONFIG_HIBERNATION */ static inline void register_nosave_region(unsigned long b, unsigned long e) {}
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index b209712cb2c3..b41952f1de2a 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c@@ -85,7 +85,7 @@ static inline int hibernate_restore_unprotect_page(void *page_address) {return 0 * It is still worth to have a warning here if something changes and this * will no longer be the case. */ -static inline void hibernate_map_page(struct page *page) +void * __weak hibernate_map_page(struct page *page) { if (IS_ENABLED(CONFIG_ARCH_HAS_SET_DIRECT_MAP)) { int ret = set_direct_map_default_noflush(page);
@@ -95,9 +95,10 @@ static inline void hibernate_map_page(struct page *page) } else { debug_pagealloc_map_pages(page, 1); } + return page_address(page); } -static inline void hibernate_unmap_page(struct page *page) +void __weak hibernate_unmap_page(struct page *page) { if (IS_ENABLED(CONFIG_ARCH_HAS_SET_DIRECT_MAP)) { unsigned long addr = (unsigned long)page_address(page);
@@ -1456,8 +1457,9 @@ static bool safe_copy_page(void *dst, struct page *s_page) if (kernel_page_present(s_page)) { zeros_only = do_copy_page(dst, page_address(s_page)); } else { - hibernate_map_page(s_page); - zeros_only = do_copy_page(dst, page_address(s_page)); + void *src = hibernate_map_page(s_page); + + zeros_only = do_copy_page(dst, src); hibernate_unmap_page(s_page); } return zeros_only;
--
2.55.0.1082.g2b9226bbc0-goog