Skip to content

arm64: kernel: Add support for hibernate/suspend-to-disk

Will Deacon linux-arm-kernel 2 versions New

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v9 Latest posting 2/20 of 14 patches 0 repliesNew
  2. v9 posting 1/22 of 14 patches 0 repliesSuperseded

Patches in v9 posting 2/2 No applies recorded yet

None of the 14 patches the cover letter announces are in this archive.

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v9 yet.

Read the v9 thread

Cover letter [PATCH v9 00/14] arm64: kernel: Add support for hibernate/suspend-to-disk
Quoted 32 lines · James Morse
Quoted 6 lines · Will Deacon
Quoted 3 lines · James Morse

This is the today's version of hibernate for arm64, based on arm64's for-next/core with latest commit 6a1f54711447 ("arm64: acpi: add acpi=on cmdline option to prefer ACPI boot over DT").

I've queued this locally, but it breaks an allmodconfig build:

... I should have tested that ...

Quoted 7 lines

kernel/built-in.o: In function `saveable_page':
memremap.c:(.text+0x100f90): undefined reference to kernel_page_present' kernel/built-in.o: In function swsusp_save':
memremap.c:(.text+0x1026f0): undefined reference to `kernel_page_present'
make: *** [vmlinux] Error 1

Can you take a look, please?

This is caused by DEBUG_PAGEALLOC, which clears the PTE_VALID bit from 'free' pages. Hibernate uses it as a hint that it shouldn't save/access that page. This function is used to test whether the PTE_VALID bit has been cleared by kernel_map_pages(), hibernate is the only user.

Fixing this exposes a bigger problem with that configuration though: if the resume kernel has cut free pages out of the linear map, we copy this swiss-cheese view of memory, and try to use it to restore...

We can fixup the copy of the linear map, but it then explodes in my lazy 'clean the whole kernel to PoC' after resume, as now both the kernel and linear map have holes in them.

Quoted 5 lines

For now I think forbidding this configuration is best. ARCH_HIBERNATION_POSSIBLE depends on !DEBUG_PAGEALLOC would be best, but we can't do that, as DEBUG_PAGEALLOC has:

Quoted 1 line

depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC

which causes kconfig to winge about loops in its dependencies.

That dependency looks really fishy. It's saying that, if we disable HIBERNATION, then DEBUG_PAGEALLOC will work regardless of ARCH_SUPPORTS_DEBUGALLOC.

So I tried disabling ARCH_SUPPORTS_DEBUGALLOC for arm64 and removing our definition of __kernel_map_pages from arch/arm64/mm/pageattr.c and...

... it bloody linked.

Turns out mm/page_poison.c has this gem:

#ifndef CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)

{
	/* This function does nothing, all work is done via poison pages */
}

#endif

and DEBUG_PAGEALLOC selects PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC. Maybe somebody understands all of this crazy config indirection but, for the time being, I'm happy to take your patch.

We should probably look at making this all work with the debug options for 4.8, however.

Will

Quoted 20 lines

-----------------------%<-----------------------

arch/arm64/Kconfig +1 -1
index b87f303765d4..0a7ff709a851 100644
@@ -579,6 +579,7 @@ source kernel/Kconfig.hz
 
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
+       depends on !HIBERNATION
 
 config ARCH_HAS_HOLES_MEMORYMODEL
        def_bool y if SPARSEMEM
-----------------------%<-----------------------

Thanks,

James