Skip to content

Commit

Permalink
PM / Hibernate: allow hibernation with PAGE_POISONING_ZERO
Browse files Browse the repository at this point in the history
PAGE_POISONING_ZERO disables zeroing new pages on alloc, they are
poisoned (zeroed) as they become available.
In the hibernate use case, free pages will appear in the system without
being cleared, left there by the loading kernel.

This patch will make sure free pages are cleared on resume when
PAGE_POISONING_ZERO is enabled. We free the pages just after resume
because we can't do it later: going through any device resume code might
allocate some memory and invalidate the free pages bitmap.

Thus we don't need to disable hibernation when PAGE_POISONING_ZERO is
enabled.

Signed-off-by: Anisse Astier <anisse@astier.eu>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Anisse Astier authored and Rafael J. Wysocki committed Sep 13, 2016
1 parent fa7fd6f commit 1ad1410
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 20 deletions.
21 changes: 3 additions & 18 deletions kernel/power/hibernate.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,10 @@ static int create_image(int platform_mode)
if (error)
printk(KERN_ERR "PM: Error %d creating hibernation image\n",
error);
if (!in_suspend)
if (!in_suspend) {
events_check_enabled = false;
clear_free_pages();
}

platform_leave(platform_mode);

Expand Down Expand Up @@ -1189,27 +1191,10 @@ static int __init nohibernate_setup(char *str)
return 1;
}

static int __init page_poison_nohibernate_setup(char *str)
{
#ifdef CONFIG_PAGE_POISONING_ZERO
/*
* The zeroing option for page poison skips the checks on alloc.
* since hibernation doesn't save free pages there's no way to
* guarantee the pages will still be zeroed.
*/
if (!strcmp(str, "on")) {
pr_info("Disabling hibernation due to page poisoning\n");
return nohibernate_setup(str);
}
#endif
return 1;
}

__setup("noresume", noresume_setup);
__setup("resume_offset=", resume_offset_setup);
__setup("resume=", resume_setup);
__setup("hibernate=", hibernate_setup);
__setup("resumewait", resumewait_setup);
__setup("resumedelay=", resumedelay_setup);
__setup("nohibernate", nohibernate_setup);
__setup("page_poison=", page_poison_nohibernate_setup);
2 changes: 2 additions & 0 deletions kernel/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ extern int create_basic_memory_bitmaps(void);
extern void free_basic_memory_bitmaps(void);
extern int hibernate_preallocate_memory(void);

extern void clear_free_pages(void);

/**
* Auxiliary structure used for reading the snapshot image data and
* metadata from and writing them to the list of page backup entries
Expand Down
22 changes: 22 additions & 0 deletions kernel/power/snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,28 @@ void free_basic_memory_bitmaps(void)
pr_debug("PM: Basic memory bitmaps freed\n");
}

void clear_free_pages(void)
{
#ifdef CONFIG_PAGE_POISONING_ZERO
struct memory_bitmap *bm = free_pages_map;
unsigned long pfn;

if (WARN_ON(!(free_pages_map)))
return;

memory_bm_position_reset(bm);
pfn = memory_bm_next_pfn(bm);
while (pfn != BM_END_OF_MAP) {
if (pfn_valid(pfn))
clear_highpage(pfn_to_page(pfn));

pfn = memory_bm_next_pfn(bm);
}
memory_bm_position_reset(bm);
pr_info("PM: free pages cleared after restore\n");
#endif /* PAGE_POISONING_ZERO */
}

/**
* snapshot_additional_pages - Estimate the number of extra pages needed.
* @zone: Memory zone to carry out the computation for.
Expand Down
2 changes: 0 additions & 2 deletions mm/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ config PAGE_POISONING_ZERO
no longer necessary to write zeros when GFP_ZERO is used on
allocation.

Enabling page poisoning with this option will disable hibernation

If unsure, say N
bool

Expand Down

0 comments on commit 1ad1410

Please sign in to comment.