mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
kernel/power: allow hibernation with page_poison sanity checking
Page poisoning used to be incompatible with hibernation, as the state of poisoned pages was lost after resume, thus enabling CONFIG_HIBERNATION forces CONFIG_PAGE_POISONING_NO_SANITY. For the same reason, the poisoning with zeroes variant CONFIG_PAGE_POISONING_ZERO used to disable hibernation. The latter restriction was removed by commit1ad1410f63
("PM / Hibernate: allow hibernation with PAGE_POISONING_ZERO") and similarly for init_on_free by commit18451f9f9e
("PM: hibernate: fix crashes with init_on_free=1") by making sure free pages are cleared after resume. We can use the same mechanism to instead poison free pages with PAGE_POISON after resume. This covers both zero and 0xAA patterns. Thus we can remove the Kconfig restriction that disables page poison sanity checking when hibernation is enabled. Link: https://lkml.kernel.org/r/20201113104033.22907-4-vbabka@suse.cz Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> [hibernation] Reviewed-by: David Hildenbrand <david@redhat.com> Cc: Mike Rapoport <rppt@linux.ibm.com> Cc: Alexander Potapenko <glider@google.com> Cc: Kees Cook <keescook@chromium.org> Cc: Laura Abbott <labbott@kernel.org> Cc: Mateusz Nosek <mateusznosek0@gmail.com> Cc: Michal Hocko <mhocko@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
8db26a3d47
commit
03b6c9a3e8
@@ -2903,6 +2903,7 @@ static inline void kernel_unpoison_pages(struct page *page, int numpages)
|
|||||||
#else
|
#else
|
||||||
static inline bool page_poisoning_enabled(void) { return false; }
|
static inline bool page_poisoning_enabled(void) { return false; }
|
||||||
static inline bool page_poisoning_enabled_static(void) { return false; }
|
static inline bool page_poisoning_enabled_static(void) { return false; }
|
||||||
|
static inline void __kernel_poison_pages(struct page *page, int nunmpages) { }
|
||||||
static inline void kernel_poison_pages(struct page *page, int numpages) { }
|
static inline void kernel_poison_pages(struct page *page, int numpages) { }
|
||||||
static inline void kernel_unpoison_pages(struct page *page, int numpages) { }
|
static inline void kernel_unpoison_pages(struct page *page, int numpages) { }
|
||||||
#endif
|
#endif
|
||||||
|
@@ -326,7 +326,7 @@ static int create_image(int platform_mode)
|
|||||||
|
|
||||||
if (!in_suspend) {
|
if (!in_suspend) {
|
||||||
events_check_enabled = false;
|
events_check_enabled = false;
|
||||||
clear_free_pages();
|
clear_or_poison_free_pages();
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_leave(platform_mode);
|
platform_leave(platform_mode);
|
||||||
|
@@ -106,7 +106,7 @@ extern int create_basic_memory_bitmaps(void);
|
|||||||
extern void free_basic_memory_bitmaps(void);
|
extern void free_basic_memory_bitmaps(void);
|
||||||
extern int hibernate_preallocate_memory(void);
|
extern int hibernate_preallocate_memory(void);
|
||||||
|
|
||||||
extern void clear_free_pages(void);
|
extern void clear_or_poison_free_pages(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auxiliary structure used for reading the snapshot image data and
|
* Auxiliary structure used for reading the snapshot image data and
|
||||||
|
@@ -1178,7 +1178,15 @@ void free_basic_memory_bitmaps(void)
|
|||||||
pr_debug("Basic memory bitmaps freed\n");
|
pr_debug("Basic memory bitmaps freed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_free_pages(void)
|
static void clear_or_poison_free_page(struct page *page)
|
||||||
|
{
|
||||||
|
if (page_poisoning_enabled_static())
|
||||||
|
__kernel_poison_pages(page, 1);
|
||||||
|
else if (want_init_on_free())
|
||||||
|
clear_highpage(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_or_poison_free_pages(void)
|
||||||
{
|
{
|
||||||
struct memory_bitmap *bm = free_pages_map;
|
struct memory_bitmap *bm = free_pages_map;
|
||||||
unsigned long pfn;
|
unsigned long pfn;
|
||||||
@@ -1186,12 +1194,12 @@ void clear_free_pages(void)
|
|||||||
if (WARN_ON(!(free_pages_map)))
|
if (WARN_ON(!(free_pages_map)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) || want_init_on_free()) {
|
if (page_poisoning_enabled() || want_init_on_free()) {
|
||||||
memory_bm_position_reset(bm);
|
memory_bm_position_reset(bm);
|
||||||
pfn = memory_bm_next_pfn(bm);
|
pfn = memory_bm_next_pfn(bm);
|
||||||
while (pfn != BM_END_OF_MAP) {
|
while (pfn != BM_END_OF_MAP) {
|
||||||
if (pfn_valid(pfn))
|
if (pfn_valid(pfn))
|
||||||
clear_highpage(pfn_to_page(pfn));
|
clear_or_poison_free_page(pfn_to_page(pfn));
|
||||||
|
|
||||||
pfn = memory_bm_next_pfn(bm);
|
pfn = memory_bm_next_pfn(bm);
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,6 @@ config PAGE_OWNER
|
|||||||
|
|
||||||
config PAGE_POISONING
|
config PAGE_POISONING
|
||||||
bool "Poison pages after freeing"
|
bool "Poison pages after freeing"
|
||||||
select PAGE_POISONING_NO_SANITY if HIBERNATION
|
|
||||||
help
|
help
|
||||||
Fill the pages with poison patterns after free_pages() and verify
|
Fill the pages with poison patterns after free_pages() and verify
|
||||||
the patterns before alloc_pages. The filling of the memory helps
|
the patterns before alloc_pages. The filling of the memory helps
|
||||||
|
Reference in New Issue
Block a user