Re: [PATCH v1 1/4] PM: hibernate: Add arch specific hooks for hibernate_map/unmap_page
From: Mike Rapoport <rppt@kernel.org>
Date: 2026-09-22 05:55:17
Also in:
linux-pm, lkml
Hi Vincent, On Fri, Sep 18, 2026 at 02:16:53PM +0100, Vincent Donnefort wrote:
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.
I posted patches that remove set_direct_map usage from hibernation: https://lore.kernel.org/all/20260917-hibernation-v1-0-7f7dfae3dbe0@kernel.org (local) So I really hope this patch won't be needed :)
quoted hunk ↗ jump to hunk
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
-- Sincerely yours, Mike.