aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-02-19 19:47:44 -0500
committerLen Brown <len.brown@intel.com>2008-02-21 02:15:28 -0500
commit8a235efad548abd2ab5ebea45a9ffa750c814375 (patch)
tree9b8c6c1fa3d2e28d9bb198d7019cba8883d5299e /kernel
parente80af3a8dbbbf431b2070cc760699f01c5a6ac69 (diff)
Hibernation: Handle DEBUG_PAGEALLOC on x86
Make hibernation work with CONFIG_DEBUG_PAGEALLOC set on x86, by checking if the pages to be copied are marked as present in the kernel mapping and temporarily marking them as present if that's not the case. No functional modifications are introduced if CONFIG_DEBUG_PAGEALLOC is unset. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/snapshot.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 95250d7c8d91..72a020cabb4c 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -875,8 +875,8 @@ static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; }
875#endif /* CONFIG_HIGHMEM */ 875#endif /* CONFIG_HIGHMEM */
876 876
877/** 877/**
878 * saveable - Determine whether a non-highmem page should be included in 878 * saveable_page - Determine whether a non-highmem page should be included
879 * the suspend image. 879 * in the suspend image.
880 * 880 *
881 * We should save the page if it isn't Nosave, and is not in the range 881 * We should save the page if it isn't Nosave, and is not in the range
882 * of pages statically defined as 'unsaveable', and it isn't a part of 882 * of pages statically defined as 'unsaveable', and it isn't a part of
@@ -897,7 +897,8 @@ static struct page *saveable_page(unsigned long pfn)
897 if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page)) 897 if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
898 return NULL; 898 return NULL;
899 899
900 if (PageReserved(page) && pfn_is_nosave(pfn)) 900 if (PageReserved(page)
901 && (!kernel_page_present(page) || pfn_is_nosave(pfn)))
901 return NULL; 902 return NULL;
902 903
903 return page; 904 return page;
@@ -938,6 +939,25 @@ static inline void do_copy_page(long *dst, long *src)
938 *dst++ = *src++; 939 *dst++ = *src++;
939} 940}
940 941
942
943/**
944 * safe_copy_page - check if the page we are going to copy is marked as
945 * present in the kernel page tables (this always is the case if
946 * CONFIG_DEBUG_PAGEALLOC is not set and in that case
947 * kernel_page_present() always returns 'true').
948 */
949static void safe_copy_page(void *dst, struct page *s_page)
950{
951 if (kernel_page_present(s_page)) {
952 do_copy_page(dst, page_address(s_page));
953 } else {
954 kernel_map_pages(s_page, 1, 1);
955 do_copy_page(dst, page_address(s_page));
956 kernel_map_pages(s_page, 1, 0);
957 }
958}
959
960
941#ifdef CONFIG_HIGHMEM 961#ifdef CONFIG_HIGHMEM
942static inline struct page * 962static inline struct page *
943page_is_saveable(struct zone *zone, unsigned long pfn) 963page_is_saveable(struct zone *zone, unsigned long pfn)
@@ -946,8 +966,7 @@ page_is_saveable(struct zone *zone, unsigned long pfn)
946 saveable_highmem_page(pfn) : saveable_page(pfn); 966 saveable_highmem_page(pfn) : saveable_page(pfn);
947} 967}
948 968
949static inline void 969static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
950copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
951{ 970{
952 struct page *s_page, *d_page; 971 struct page *s_page, *d_page;
953 void *src, *dst; 972 void *src, *dst;
@@ -961,29 +980,26 @@ copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
961 kunmap_atomic(src, KM_USER0); 980 kunmap_atomic(src, KM_USER0);
962 kunmap_atomic(dst, KM_USER1); 981 kunmap_atomic(dst, KM_USER1);
963 } else { 982 } else {
964 src = page_address(s_page);
965 if (PageHighMem(d_page)) { 983 if (PageHighMem(d_page)) {
966 /* Page pointed to by src may contain some kernel 984 /* Page pointed to by src may contain some kernel
967 * data modified by kmap_atomic() 985 * data modified by kmap_atomic()
968 */ 986 */
969 do_copy_page(buffer, src); 987 safe_copy_page(buffer, s_page);
970 dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0); 988 dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0);
971 memcpy(dst, buffer, PAGE_SIZE); 989 memcpy(dst, buffer, PAGE_SIZE);
972 kunmap_atomic(dst, KM_USER0); 990 kunmap_atomic(dst, KM_USER0);
973 } else { 991 } else {
974 dst = page_address(d_page); 992 safe_copy_page(page_address(d_page), s_page);
975 do_copy_page(dst, src);
976 } 993 }
977 } 994 }
978} 995}
979#else 996#else
980#define page_is_saveable(zone, pfn) saveable_page(pfn) 997#define page_is_saveable(zone, pfn) saveable_page(pfn)
981 998
982static inline void 999static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
983copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
984{ 1000{
985 do_copy_page(page_address(pfn_to_page(dst_pfn)), 1001 safe_copy_page(page_address(pfn_to_page(dst_pfn)),
986 page_address(pfn_to_page(src_pfn))); 1002 pfn_to_page(src_pfn));
987} 1003}
988#endif /* CONFIG_HIGHMEM */ 1004#endif /* CONFIG_HIGHMEM */
989 1005