All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 0/1] [patch 0/1] include storage keys in hibernation image
@ 2011-08-16 14:14 Martin Schwidefsky
  2011-08-16 14:14 ` [patch 1/1] [PATCH] " Martin Schwidefsky
  2011-08-16 14:14 ` Martin Schwidefsky
  0 siblings, 2 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-16 14:14 UTC (permalink / raw)
  To: linux-pm, linux-kernel, linux-s390, Rafael J. Wysocki,
	Pavel Machek, Jiri Slaby

Hi Rafael,

Version 2 of the storage key patch for hibernation on s390.
I've added the following changes as you requested:
1) moved the s390 specific code to arch/s390/kernel/suspend.c
2) introduced CONFIG_ARCH_SAVE_PAGE_KEYS and added a select to
   the main s390 Kconfig file
3) added the empty default functions to include/linux/suspend.h

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 14:14 [patch 0/1] [patch 0/1] include storage keys in hibernation image Martin Schwidefsky
  2011-08-16 14:14 ` [patch 1/1] [PATCH] " Martin Schwidefsky
@ 2011-08-16 14:14 ` Martin Schwidefsky
  2011-08-16 17:56   ` Rafael J. Wysocki
  2011-08-16 17:56   ` Rafael J. Wysocki
  1 sibling, 2 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-16 14:14 UTC (permalink / raw)
  To: linux-pm, linux-kernel, linux-s390, Rafael J. Wysocki,
	Pavel Machek, Jiri Slaby
  Cc: Martin Schwidefsky

[-- Attachment #1: 201-hibernate-storage-keys.diff --]
[-- Type: text/plain, Size: 9952 bytes --]

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

For s390 there is one additional byte associated with each page,
the storage key. This byte contains the referenced and changed
bits and needs to be included into the hibernation image.
If the storage keys are not restored to their previous state all
original pages would appear to be dirty. This can cause
inconsistencies e.g. with read-only filesystems.

Cc: Pavel Machek <pavel@ucw.cz>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: linux-pm@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-s390@vger.kernel.org
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

---

 arch/s390/Kconfig               |    1 
 arch/s390/kernel/suspend.c      |  118 ++++++++++++++++++++++++++++++++++++++++
 arch/s390/kernel/swsusp_asm64.S |    3 +
 include/linux/suspend.h         |   34 +++++++++++
 kernel/power/Kconfig            |    3 +
 kernel/power/snapshot.c         |   18 ++++++
 6 files changed, 177 insertions(+)

Index: hibernate-2.6/arch/s390/Kconfig
===================================================================
--- hibernate-2.6.orig/arch/s390/Kconfig	2011-08-09 17:40:09.220010373 +0200
+++ hibernate-2.6/arch/s390/Kconfig	2011-08-16 16:06:09.845540931 +0200
@@ -91,6 +91,7 @@
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
 	select HAVE_RCU_TABLE_FREE if SMP
+	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_INLINE_SPIN_TRYLOCK
 	select ARCH_INLINE_SPIN_TRYLOCK_BH
 	select ARCH_INLINE_SPIN_LOCK
Index: hibernate-2.6/arch/s390/kernel/suspend.c
===================================================================
--- hibernate-2.6.orig/arch/s390/kernel/suspend.c	2009-09-24 09:06:44.000000000 +0200
+++ hibernate-2.6/arch/s390/kernel/suspend.c	2011-08-16 16:06:09.845540931 +0200
@@ -7,6 +7,7 @@
  */
 
 #include <linux/pfn.h>
+#include <linux/mm.h>
 #include <asm/system.h>
 
 /*
@@ -14,6 +15,123 @@
  */
 extern const void __nosave_begin, __nosave_end;
 
+/*
+ * The restore of the saved pages in an hibernation image will set
+ * the change and referenced bits in the storage key for each page.
+ * Overindication of the referenced bits after an hibernation cycle
+ * does not cause any harm but the overindication of the change bits
+ * would cause trouble.
+ * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
+ * page to the most significant byte of the associated page frame
+ * number in the hibernation image.
+ */
+
+/*
+ * Key storage is allocated as a linked list of pages.
+ * The size of the keys array is (PAGE_SIZE - sizeof(long))
+ */
+struct page_key_data {
+	struct page_key_data *next;
+	unsigned char data[];
+};
+
+#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
+
+static struct page_key_data *page_key_data;
+static struct page_key_data *page_key_rp, *page_key_wp;
+static unsigned long page_key_rx, page_key_wx;
+
+/*
+ * For each page in the hibernation image one additional byte is
+ * stored in the most significant byte of the page frame number.
+ * On suspend no additional memory is required but on resume the
+ * keys need to be memorized until the page data has been restored.
+ * Only then can the storage keys be set to their old state.
+ */
+unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+}
+
+/*
+ * Free page_key_data list of arrays.
+ */
+void page_key_free(void)
+{
+	struct page_key_data *pkd;
+
+	while (page_key_data) {
+		pkd = page_key_data;
+		page_key_data = pkd->next;
+		free_page((unsigned long) pkd);
+	}
+}
+
+/*
+ * Allocate page_key_data list of arrays with enough room to store
+ * one byte for each page in the hibernation image.
+ */
+int page_key_alloc(unsigned long pages)
+{
+	struct page_key_data *pk;
+	unsigned long size;
+
+	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+	while (size--) {
+		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
+		if (!pk) {
+			page_key_free();
+			return -ENOMEM;
+		}
+		pk->next = page_key_data;
+		page_key_data = pk;
+	}
+	page_key_rp = page_key_wp = page_key_data;
+	page_key_rx = page_key_wx = 0;
+	return 0;
+}
+
+/*
+ * Save the storage key into the upper 8 bits of the page frame number.
+ */
+void page_key_read(unsigned long *pfn)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) page_address(pfn_to_page(*pfn));
+	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
+}
+
+/*
+ * Extract the storage key from the upper 8 bits of the page frame number
+ * and store it in the page_key_data list of arrays.
+ */
+void page_key_memorize(unsigned long *pfn)
+{
+	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
+	*(unsigned char *) pfn = 0;
+	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_wp = page_key_wp->next;
+	page_key_wx = 0;
+}
+
+/*
+ * Get the next key from the page_key_data list of arrays and set the
+ * storage key of the page referred by @address. If @address refers to
+ * a "safe" page the swsusp_arch_resume code will transfer the storage
+ * key from the buffer page to the original page.
+ */
+void page_key_write(void *address)
+{
+	page_set_storage_key((unsigned long) address,
+			     page_key_rp->data[page_key_rx], 0);
+	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_rp = page_key_rp->next;
+	page_key_rx = 0;
+}
+
 int pfn_is_nosave(unsigned long pfn)
 {
 	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
Index: hibernate-2.6/arch/s390/kernel/swsusp_asm64.S
===================================================================
--- hibernate-2.6.orig/arch/s390/kernel/swsusp_asm64.S	2011-08-09 17:40:09.228010544 +0200
+++ hibernate-2.6/arch/s390/kernel/swsusp_asm64.S	2011-08-16 16:06:09.845540931 +0200
@@ -136,11 +136,14 @@
 0:
 	lg	%r2,8(%r1)
 	lg	%r4,0(%r1)
+	iske	%r0,%r4
 	lghi	%r3,PAGE_SIZE
 	lghi	%r5,PAGE_SIZE
 1:
 	mvcle	%r2,%r4,0
 	jo	1b
+	lg	%r2,8(%r1)
+	sske	%r0,%r2
 	lg	%r1,16(%r1)
 	ltgr	%r1,%r1
 	jnz	0b
Index: hibernate-2.6/include/linux/suspend.h
===================================================================
--- hibernate-2.6.orig/include/linux/suspend.h	2011-08-09 17:40:10.164030551 +0200
+++ hibernate-2.6/include/linux/suspend.h	2011-08-16 16:06:09.845540931 +0200
@@ -334,4 +334,38 @@
 }
 #endif
 
+#ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
+/*
+ * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
+ * to save/restore additional information to/from the array of page
+ * frame numbers in the hibernation image. For s390 this is used to
+ * save and restore the storage key for each page that is included
+ * in the hibernation image.
+ */
+unsigned long page_key_additional_pages(unsigned long pages);
+int page_key_alloc(unsigned long pages);
+void page_key_free(void);
+void page_key_read(unsigned long *pfn);
+void page_key_memorize(unsigned long *pfn);
+void page_key_write(void *address);
+
+#else /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
+
+static inline unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return 0;
+}
+
+static inline int  page_key_alloc(unsigned long pages)
+{
+	return 0;
+}
+
+static inline void page_key_free(void) {}
+static inline void page_key_read(unsigned long *pfn) {}
+static inline void page_key_memorize(unsigned long *pfn) {}
+static inline void page_key_write(void *address) {}
+
+#endif /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
+
 #endif /* _LINUX_SUSPEND_H */
Index: hibernate-2.6/kernel/power/Kconfig
===================================================================
--- hibernate-2.6.orig/kernel/power/Kconfig	2011-08-09 17:40:10.192031153 +0200
+++ hibernate-2.6/kernel/power/Kconfig	2011-08-16 16:06:09.845540931 +0200
@@ -65,6 +65,9 @@
 
 	  For more information take a look at <file:Documentation/power/swsusp.txt>.
 
+config ARCH_SAVE_PAGE_KEYS
+	bool
+
 config PM_STD_PARTITION
 	string "Default resume partition"
 	depends on HIBERNATION
Index: hibernate-2.6/kernel/power/snapshot.c
===================================================================
--- hibernate-2.6.orig/kernel/power/snapshot.c	2011-07-08 11:25:06.293203483 +0200
+++ hibernate-2.6/kernel/power/snapshot.c	2011-08-16 16:06:09.845540931 +0200
@@ -1339,6 +1339,9 @@
 	count += highmem;
 	count -= totalreserve_pages;
 
+	/* Add number of pages required for page keys (s390 only). */
+	size += page_key_additional_pages(saveable);
+
 	/* Compute the maximum number of saveable pages to leave in memory. */
 	max_size = (count - (size + PAGES_FOR_IO)) / 2
 			- 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
@@ -1662,6 +1665,8 @@
 		buf[j] = memory_bm_next_pfn(bm);
 		if (unlikely(buf[j] == BM_END_OF_MAP))
 			break;
+		/* Save page key for data page (s390 only). */
+		page_key_read(buf + j);
 	}
 }
 
@@ -1821,6 +1826,9 @@
 		if (unlikely(buf[j] == BM_END_OF_MAP))
 			break;
 
+		/* Extract and buffer page key for data page (s390 only). */
+		page_key_memorize(buf + j);
+
 		if (memory_bm_pfn_present(bm, buf[j]))
 			memory_bm_set_bit(bm, buf[j]);
 		else
@@ -2223,6 +2231,11 @@
 		if (error)
 			return error;
 
+		/* Allocate buffer for page keys. */
+		error = page_key_alloc(nr_copy_pages);
+		if (error)
+			return error;
+
 	} else if (handle->cur <= nr_meta_pages + 1) {
 		error = unpack_orig_pfns(buffer, &copy_bm);
 		if (error)
@@ -2243,6 +2256,8 @@
 		}
 	} else {
 		copy_last_highmem_page();
+		/* Restore page key for data page (s390 only). */
+		page_key_write(handle->buffer);
 		handle->buffer = get_buffer(&orig_bm, &ca);
 		if (IS_ERR(handle->buffer))
 			return PTR_ERR(handle->buffer);
@@ -2264,6 +2279,9 @@
 void snapshot_write_finalize(struct snapshot_handle *handle)
 {
 	copy_last_highmem_page();
+	/* Restore page key for data page (s390 only). */
+	page_key_write(handle->buffer);
+	page_key_free();
 	/* Free only if we have loaded the image entirely */
 	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
 		memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 14:14 [patch 0/1] [patch 0/1] include storage keys in hibernation image Martin Schwidefsky
@ 2011-08-16 14:14 ` Martin Schwidefsky
  2011-08-16 14:14 ` Martin Schwidefsky
  1 sibling, 0 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-16 14:14 UTC (permalink / raw)
  To: linux-pm, linux-kernel, linux-s390, Rafael J. Wysocki,
	Pavel Machek, Jiri
  Cc: Martin Schwidefsky

[-- Attachment #1: 201-hibernate-storage-keys.diff --]
[-- Type: text/plain, Size: 9951 bytes --]

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

For s390 there is one additional byte associated with each page,
the storage key. This byte contains the referenced and changed
bits and needs to be included into the hibernation image.
If the storage keys are not restored to their previous state all
original pages would appear to be dirty. This can cause
inconsistencies e.g. with read-only filesystems.

Cc: Pavel Machek <pavel@ucw.cz>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: linux-pm@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-s390@vger.kernel.org
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

---

 arch/s390/Kconfig               |    1 
 arch/s390/kernel/suspend.c      |  118 ++++++++++++++++++++++++++++++++++++++++
 arch/s390/kernel/swsusp_asm64.S |    3 +
 include/linux/suspend.h         |   34 +++++++++++
 kernel/power/Kconfig            |    3 +
 kernel/power/snapshot.c         |   18 ++++++
 6 files changed, 177 insertions(+)

Index: hibernate-2.6/arch/s390/Kconfig
===================================================================
--- hibernate-2.6.orig/arch/s390/Kconfig	2011-08-09 17:40:09.220010373 +0200
+++ hibernate-2.6/arch/s390/Kconfig	2011-08-16 16:06:09.845540931 +0200
@@ -91,6 +91,7 @@
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
 	select HAVE_RCU_TABLE_FREE if SMP
+	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_INLINE_SPIN_TRYLOCK
 	select ARCH_INLINE_SPIN_TRYLOCK_BH
 	select ARCH_INLINE_SPIN_LOCK
Index: hibernate-2.6/arch/s390/kernel/suspend.c
===================================================================
--- hibernate-2.6.orig/arch/s390/kernel/suspend.c	2009-09-24 09:06:44.000000000 +0200
+++ hibernate-2.6/arch/s390/kernel/suspend.c	2011-08-16 16:06:09.845540931 +0200
@@ -7,6 +7,7 @@
  */
 
 #include <linux/pfn.h>
+#include <linux/mm.h>
 #include <asm/system.h>
 
 /*
@@ -14,6 +15,123 @@
  */
 extern const void __nosave_begin, __nosave_end;
 
+/*
+ * The restore of the saved pages in an hibernation image will set
+ * the change and referenced bits in the storage key for each page.
+ * Overindication of the referenced bits after an hibernation cycle
+ * does not cause any harm but the overindication of the change bits
+ * would cause trouble.
+ * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
+ * page to the most significant byte of the associated page frame
+ * number in the hibernation image.
+ */
+
+/*
+ * Key storage is allocated as a linked list of pages.
+ * The size of the keys array is (PAGE_SIZE - sizeof(long))
+ */
+struct page_key_data {
+	struct page_key_data *next;
+	unsigned char data[];
+};
+
+#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
+
+static struct page_key_data *page_key_data;
+static struct page_key_data *page_key_rp, *page_key_wp;
+static unsigned long page_key_rx, page_key_wx;
+
+/*
+ * For each page in the hibernation image one additional byte is
+ * stored in the most significant byte of the page frame number.
+ * On suspend no additional memory is required but on resume the
+ * keys need to be memorized until the page data has been restored.
+ * Only then can the storage keys be set to their old state.
+ */
+unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+}
+
+/*
+ * Free page_key_data list of arrays.
+ */
+void page_key_free(void)
+{
+	struct page_key_data *pkd;
+
+	while (page_key_data) {
+		pkd = page_key_data;
+		page_key_data = pkd->next;
+		free_page((unsigned long) pkd);
+	}
+}
+
+/*
+ * Allocate page_key_data list of arrays with enough room to store
+ * one byte for each page in the hibernation image.
+ */
+int page_key_alloc(unsigned long pages)
+{
+	struct page_key_data *pk;
+	unsigned long size;
+
+	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+	while (size--) {
+		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
+		if (!pk) {
+			page_key_free();
+			return -ENOMEM;
+		}
+		pk->next = page_key_data;
+		page_key_data = pk;
+	}
+	page_key_rp = page_key_wp = page_key_data;
+	page_key_rx = page_key_wx = 0;
+	return 0;
+}
+
+/*
+ * Save the storage key into the upper 8 bits of the page frame number.
+ */
+void page_key_read(unsigned long *pfn)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) page_address(pfn_to_page(*pfn));
+	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
+}
+
+/*
+ * Extract the storage key from the upper 8 bits of the page frame number
+ * and store it in the page_key_data list of arrays.
+ */
+void page_key_memorize(unsigned long *pfn)
+{
+	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
+	*(unsigned char *) pfn = 0;
+	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_wp = page_key_wp->next;
+	page_key_wx = 0;
+}
+
+/*
+ * Get the next key from the page_key_data list of arrays and set the
+ * storage key of the page referred by @address. If @address refers to
+ * a "safe" page the swsusp_arch_resume code will transfer the storage
+ * key from the buffer page to the original page.
+ */
+void page_key_write(void *address)
+{
+	page_set_storage_key((unsigned long) address,
+			     page_key_rp->data[page_key_rx], 0);
+	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_rp = page_key_rp->next;
+	page_key_rx = 0;
+}
+
 int pfn_is_nosave(unsigned long pfn)
 {
 	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
Index: hibernate-2.6/arch/s390/kernel/swsusp_asm64.S
===================================================================
--- hibernate-2.6.orig/arch/s390/kernel/swsusp_asm64.S	2011-08-09 17:40:09.228010544 +0200
+++ hibernate-2.6/arch/s390/kernel/swsusp_asm64.S	2011-08-16 16:06:09.845540931 +0200
@@ -136,11 +136,14 @@
 0:
 	lg	%r2,8(%r1)
 	lg	%r4,0(%r1)
+	iske	%r0,%r4
 	lghi	%r3,PAGE_SIZE
 	lghi	%r5,PAGE_SIZE
 1:
 	mvcle	%r2,%r4,0
 	jo	1b
+	lg	%r2,8(%r1)
+	sske	%r0,%r2
 	lg	%r1,16(%r1)
 	ltgr	%r1,%r1
 	jnz	0b
Index: hibernate-2.6/include/linux/suspend.h
===================================================================
--- hibernate-2.6.orig/include/linux/suspend.h	2011-08-09 17:40:10.164030551 +0200
+++ hibernate-2.6/include/linux/suspend.h	2011-08-16 16:06:09.845540931 +0200
@@ -334,4 +334,38 @@
 }
 #endif
 
+#ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
+/*
+ * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
+ * to save/restore additional information to/from the array of page
+ * frame numbers in the hibernation image. For s390 this is used to
+ * save and restore the storage key for each page that is included
+ * in the hibernation image.
+ */
+unsigned long page_key_additional_pages(unsigned long pages);
+int page_key_alloc(unsigned long pages);
+void page_key_free(void);
+void page_key_read(unsigned long *pfn);
+void page_key_memorize(unsigned long *pfn);
+void page_key_write(void *address);
+
+#else /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
+
+static inline unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return 0;
+}
+
+static inline int  page_key_alloc(unsigned long pages)
+{
+	return 0;
+}
+
+static inline void page_key_free(void) {}
+static inline void page_key_read(unsigned long *pfn) {}
+static inline void page_key_memorize(unsigned long *pfn) {}
+static inline void page_key_write(void *address) {}
+
+#endif /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
+
 #endif /* _LINUX_SUSPEND_H */
Index: hibernate-2.6/kernel/power/Kconfig
===================================================================
--- hibernate-2.6.orig/kernel/power/Kconfig	2011-08-09 17:40:10.192031153 +0200
+++ hibernate-2.6/kernel/power/Kconfig	2011-08-16 16:06:09.845540931 +0200
@@ -65,6 +65,9 @@
 
 	  For more information take a look at <file:Documentation/power/swsusp.txt>.
 
+config ARCH_SAVE_PAGE_KEYS
+	bool
+
 config PM_STD_PARTITION
 	string "Default resume partition"
 	depends on HIBERNATION
Index: hibernate-2.6/kernel/power/snapshot.c
===================================================================
--- hibernate-2.6.orig/kernel/power/snapshot.c	2011-07-08 11:25:06.293203483 +0200
+++ hibernate-2.6/kernel/power/snapshot.c	2011-08-16 16:06:09.845540931 +0200
@@ -1339,6 +1339,9 @@
 	count += highmem;
 	count -= totalreserve_pages;
 
+	/* Add number of pages required for page keys (s390 only). */
+	size += page_key_additional_pages(saveable);
+
 	/* Compute the maximum number of saveable pages to leave in memory. */
 	max_size = (count - (size + PAGES_FOR_IO)) / 2
 			- 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
@@ -1662,6 +1665,8 @@
 		buf[j] = memory_bm_next_pfn(bm);
 		if (unlikely(buf[j] == BM_END_OF_MAP))
 			break;
+		/* Save page key for data page (s390 only). */
+		page_key_read(buf + j);
 	}
 }
 
@@ -1821,6 +1826,9 @@
 		if (unlikely(buf[j] == BM_END_OF_MAP))
 			break;
 
+		/* Extract and buffer page key for data page (s390 only). */
+		page_key_memorize(buf + j);
+
 		if (memory_bm_pfn_present(bm, buf[j]))
 			memory_bm_set_bit(bm, buf[j]);
 		else
@@ -2223,6 +2231,11 @@
 		if (error)
 			return error;
 
+		/* Allocate buffer for page keys. */
+		error = page_key_alloc(nr_copy_pages);
+		if (error)
+			return error;
+
 	} else if (handle->cur <= nr_meta_pages + 1) {
 		error = unpack_orig_pfns(buffer, &copy_bm);
 		if (error)
@@ -2243,6 +2256,8 @@
 		}
 	} else {
 		copy_last_highmem_page();
+		/* Restore page key for data page (s390 only). */
+		page_key_write(handle->buffer);
 		handle->buffer = get_buffer(&orig_bm, &ca);
 		if (IS_ERR(handle->buffer))
 			return PTR_ERR(handle->buffer);
@@ -2264,6 +2279,9 @@
 void snapshot_write_finalize(struct snapshot_handle *handle)
 {
 	copy_last_highmem_page();
+	/* Restore page key for data page (s390 only). */
+	page_key_write(handle->buffer);
+	page_key_free();
 	/* Free only if we have loaded the image entirely */
 	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
 		memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 14:14 ` Martin Schwidefsky
  2011-08-16 17:56   ` Rafael J. Wysocki
@ 2011-08-16 17:56   ` Rafael J. Wysocki
  2011-08-17  7:43     ` Martin Schwidefsky
  2011-08-17  7:43     ` Martin Schwidefsky
  1 sibling, 2 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2011-08-16 17:56 UTC (permalink / raw)
  To: Martin Schwidefsky
  Cc: linux-pm, linux-kernel, linux-s390, Pavel Machek, Jiri Slaby

On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> 
> For s390 there is one additional byte associated with each page,
> the storage key. This byte contains the referenced and changed
> bits and needs to be included into the hibernation image.
> If the storage keys are not restored to their previous state all
> original pages would appear to be dirty. This can cause
> inconsistencies e.g. with read-only filesystems.
> 
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Rafael J. Wysocki <rjw@sisk.pl>
> Cc: Jiri Slaby <jslaby@suse.cz>
> Cc: linux-pm@lists.linux-foundation.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-s390@vger.kernel.org
> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

OK, I don't have any complaints.  Do you want me to take this
patch or do you want to push it through the s390 tree?

Rafael


> ---
> 
>  arch/s390/Kconfig               |    1 
>  arch/s390/kernel/suspend.c      |  118 ++++++++++++++++++++++++++++++++++++++++
>  arch/s390/kernel/swsusp_asm64.S |    3 +
>  include/linux/suspend.h         |   34 +++++++++++
>  kernel/power/Kconfig            |    3 +
>  kernel/power/snapshot.c         |   18 ++++++
>  6 files changed, 177 insertions(+)
> 
> Index: hibernate-2.6/arch/s390/Kconfig
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/Kconfig	2011-08-09 17:40:09.220010373 +0200
> +++ hibernate-2.6/arch/s390/Kconfig	2011-08-16 16:06:09.845540931 +0200
> @@ -91,6 +91,7 @@
>  	select HAVE_ARCH_MUTEX_CPU_RELAX
>  	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
>  	select HAVE_RCU_TABLE_FREE if SMP
> +	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
>  	select ARCH_INLINE_SPIN_TRYLOCK
>  	select ARCH_INLINE_SPIN_TRYLOCK_BH
>  	select ARCH_INLINE_SPIN_LOCK
> Index: hibernate-2.6/arch/s390/kernel/suspend.c
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/kernel/suspend.c	2009-09-24 09:06:44.000000000 +0200
> +++ hibernate-2.6/arch/s390/kernel/suspend.c	2011-08-16 16:06:09.845540931 +0200
> @@ -7,6 +7,7 @@
>   */
>  
>  #include <linux/pfn.h>
> +#include <linux/mm.h>
>  #include <asm/system.h>
>  
>  /*
> @@ -14,6 +15,123 @@
>   */
>  extern const void __nosave_begin, __nosave_end;
>  
> +/*
> + * The restore of the saved pages in an hibernation image will set
> + * the change and referenced bits in the storage key for each page.
> + * Overindication of the referenced bits after an hibernation cycle
> + * does not cause any harm but the overindication of the change bits
> + * would cause trouble.
> + * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
> + * page to the most significant byte of the associated page frame
> + * number in the hibernation image.
> + */
> +
> +/*
> + * Key storage is allocated as a linked list of pages.
> + * The size of the keys array is (PAGE_SIZE - sizeof(long))
> + */
> +struct page_key_data {
> +	struct page_key_data *next;
> +	unsigned char data[];
> +};
> +
> +#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
> +
> +static struct page_key_data *page_key_data;
> +static struct page_key_data *page_key_rp, *page_key_wp;
> +static unsigned long page_key_rx, page_key_wx;
> +
> +/*
> + * For each page in the hibernation image one additional byte is
> + * stored in the most significant byte of the page frame number.
> + * On suspend no additional memory is required but on resume the
> + * keys need to be memorized until the page data has been restored.
> + * Only then can the storage keys be set to their old state.
> + */
> +unsigned long page_key_additional_pages(unsigned long pages)
> +{
> +	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
> +}
> +
> +/*
> + * Free page_key_data list of arrays.
> + */
> +void page_key_free(void)
> +{
> +	struct page_key_data *pkd;
> +
> +	while (page_key_data) {
> +		pkd = page_key_data;
> +		page_key_data = pkd->next;
> +		free_page((unsigned long) pkd);
> +	}
> +}
> +
> +/*
> + * Allocate page_key_data list of arrays with enough room to store
> + * one byte for each page in the hibernation image.
> + */
> +int page_key_alloc(unsigned long pages)
> +{
> +	struct page_key_data *pk;
> +	unsigned long size;
> +
> +	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
> +	while (size--) {
> +		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
> +		if (!pk) {
> +			page_key_free();
> +			return -ENOMEM;
> +		}
> +		pk->next = page_key_data;
> +		page_key_data = pk;
> +	}
> +	page_key_rp = page_key_wp = page_key_data;
> +	page_key_rx = page_key_wx = 0;
> +	return 0;
> +}
> +
> +/*
> + * Save the storage key into the upper 8 bits of the page frame number.
> + */
> +void page_key_read(unsigned long *pfn)
> +{
> +	unsigned long addr;
> +
> +	addr = (unsigned long) page_address(pfn_to_page(*pfn));
> +	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
> +}
> +
> +/*
> + * Extract the storage key from the upper 8 bits of the page frame number
> + * and store it in the page_key_data list of arrays.
> + */
> +void page_key_memorize(unsigned long *pfn)
> +{
> +	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
> +	*(unsigned char *) pfn = 0;
> +	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
> +		return;
> +	page_key_wp = page_key_wp->next;
> +	page_key_wx = 0;
> +}
> +
> +/*
> + * Get the next key from the page_key_data list of arrays and set the
> + * storage key of the page referred by @address. If @address refers to
> + * a "safe" page the swsusp_arch_resume code will transfer the storage
> + * key from the buffer page to the original page.
> + */
> +void page_key_write(void *address)
> +{
> +	page_set_storage_key((unsigned long) address,
> +			     page_key_rp->data[page_key_rx], 0);
> +	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
> +		return;
> +	page_key_rp = page_key_rp->next;
> +	page_key_rx = 0;
> +}
> +
>  int pfn_is_nosave(unsigned long pfn)
>  {
>  	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
> Index: hibernate-2.6/arch/s390/kernel/swsusp_asm64.S
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/kernel/swsusp_asm64.S	2011-08-09 17:40:09.228010544 +0200
> +++ hibernate-2.6/arch/s390/kernel/swsusp_asm64.S	2011-08-16 16:06:09.845540931 +0200
> @@ -136,11 +136,14 @@
>  0:
>  	lg	%r2,8(%r1)
>  	lg	%r4,0(%r1)
> +	iske	%r0,%r4
>  	lghi	%r3,PAGE_SIZE
>  	lghi	%r5,PAGE_SIZE
>  1:
>  	mvcle	%r2,%r4,0
>  	jo	1b
> +	lg	%r2,8(%r1)
> +	sske	%r0,%r2
>  	lg	%r1,16(%r1)
>  	ltgr	%r1,%r1
>  	jnz	0b
> Index: hibernate-2.6/include/linux/suspend.h
> ===================================================================
> --- hibernate-2.6.orig/include/linux/suspend.h	2011-08-09 17:40:10.164030551 +0200
> +++ hibernate-2.6/include/linux/suspend.h	2011-08-16 16:06:09.845540931 +0200
> @@ -334,4 +334,38 @@
>  }
>  #endif
>  
> +#ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
> +/*
> + * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
> + * to save/restore additional information to/from the array of page
> + * frame numbers in the hibernation image. For s390 this is used to
> + * save and restore the storage key for each page that is included
> + * in the hibernation image.
> + */
> +unsigned long page_key_additional_pages(unsigned long pages);
> +int page_key_alloc(unsigned long pages);
> +void page_key_free(void);
> +void page_key_read(unsigned long *pfn);
> +void page_key_memorize(unsigned long *pfn);
> +void page_key_write(void *address);
> +
> +#else /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
> +
> +static inline unsigned long page_key_additional_pages(unsigned long pages)
> +{
> +	return 0;
> +}
> +
> +static inline int  page_key_alloc(unsigned long pages)
> +{
> +	return 0;
> +}
> +
> +static inline void page_key_free(void) {}
> +static inline void page_key_read(unsigned long *pfn) {}
> +static inline void page_key_memorize(unsigned long *pfn) {}
> +static inline void page_key_write(void *address) {}
> +
> +#endif /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
> +
>  #endif /* _LINUX_SUSPEND_H */
> Index: hibernate-2.6/kernel/power/Kconfig
> ===================================================================
> --- hibernate-2.6.orig/kernel/power/Kconfig	2011-08-09 17:40:10.192031153 +0200
> +++ hibernate-2.6/kernel/power/Kconfig	2011-08-16 16:06:09.845540931 +0200
> @@ -65,6 +65,9 @@
>  
>  	  For more information take a look at <file:Documentation/power/swsusp.txt>.
>  
> +config ARCH_SAVE_PAGE_KEYS
> +	bool
> +
>  config PM_STD_PARTITION
>  	string "Default resume partition"
>  	depends on HIBERNATION
> Index: hibernate-2.6/kernel/power/snapshot.c
> ===================================================================
> --- hibernate-2.6.orig/kernel/power/snapshot.c	2011-07-08 11:25:06.293203483 +0200
> +++ hibernate-2.6/kernel/power/snapshot.c	2011-08-16 16:06:09.845540931 +0200
> @@ -1339,6 +1339,9 @@
>  	count += highmem;
>  	count -= totalreserve_pages;
>  
> +	/* Add number of pages required for page keys (s390 only). */
> +	size += page_key_additional_pages(saveable);
> +
>  	/* Compute the maximum number of saveable pages to leave in memory. */
>  	max_size = (count - (size + PAGES_FOR_IO)) / 2
>  			- 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
> @@ -1662,6 +1665,8 @@
>  		buf[j] = memory_bm_next_pfn(bm);
>  		if (unlikely(buf[j] == BM_END_OF_MAP))
>  			break;
> +		/* Save page key for data page (s390 only). */
> +		page_key_read(buf + j);
>  	}
>  }
>  
> @@ -1821,6 +1826,9 @@
>  		if (unlikely(buf[j] == BM_END_OF_MAP))
>  			break;
>  
> +		/* Extract and buffer page key for data page (s390 only). */
> +		page_key_memorize(buf + j);
> +
>  		if (memory_bm_pfn_present(bm, buf[j]))
>  			memory_bm_set_bit(bm, buf[j]);
>  		else
> @@ -2223,6 +2231,11 @@
>  		if (error)
>  			return error;
>  
> +		/* Allocate buffer for page keys. */
> +		error = page_key_alloc(nr_copy_pages);
> +		if (error)
> +			return error;
> +
>  	} else if (handle->cur <= nr_meta_pages + 1) {
>  		error = unpack_orig_pfns(buffer, &copy_bm);
>  		if (error)
> @@ -2243,6 +2256,8 @@
>  		}
>  	} else {
>  		copy_last_highmem_page();
> +		/* Restore page key for data page (s390 only). */
> +		page_key_write(handle->buffer);
>  		handle->buffer = get_buffer(&orig_bm, &ca);
>  		if (IS_ERR(handle->buffer))
>  			return PTR_ERR(handle->buffer);
> @@ -2264,6 +2279,9 @@
>  void snapshot_write_finalize(struct snapshot_handle *handle)
>  {
>  	copy_last_highmem_page();
> +	/* Restore page key for data page (s390 only). */
> +	page_key_write(handle->buffer);
> +	page_key_free();
>  	/* Free only if we have loaded the image entirely */
>  	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
>  		memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
> 
> 
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 14:14 ` Martin Schwidefsky
@ 2011-08-16 17:56   ` Rafael J. Wysocki
  2011-08-16 17:56   ` Rafael J. Wysocki
  1 sibling, 0 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2011-08-16 17:56 UTC (permalink / raw)
  To: Martin Schwidefsky; +Cc: linux-s390, linux-pm, Jiri Slaby, linux-kernel

On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> 
> For s390 there is one additional byte associated with each page,
> the storage key. This byte contains the referenced and changed
> bits and needs to be included into the hibernation image.
> If the storage keys are not restored to their previous state all
> original pages would appear to be dirty. This can cause
> inconsistencies e.g. with read-only filesystems.
> 
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Rafael J. Wysocki <rjw@sisk.pl>
> Cc: Jiri Slaby <jslaby@suse.cz>
> Cc: linux-pm@lists.linux-foundation.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-s390@vger.kernel.org
> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

OK, I don't have any complaints.  Do you want me to take this
patch or do you want to push it through the s390 tree?

Rafael


> ---
> 
>  arch/s390/Kconfig               |    1 
>  arch/s390/kernel/suspend.c      |  118 ++++++++++++++++++++++++++++++++++++++++
>  arch/s390/kernel/swsusp_asm64.S |    3 +
>  include/linux/suspend.h         |   34 +++++++++++
>  kernel/power/Kconfig            |    3 +
>  kernel/power/snapshot.c         |   18 ++++++
>  6 files changed, 177 insertions(+)
> 
> Index: hibernate-2.6/arch/s390/Kconfig
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/Kconfig	2011-08-09 17:40:09.220010373 +0200
> +++ hibernate-2.6/arch/s390/Kconfig	2011-08-16 16:06:09.845540931 +0200
> @@ -91,6 +91,7 @@
>  	select HAVE_ARCH_MUTEX_CPU_RELAX
>  	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
>  	select HAVE_RCU_TABLE_FREE if SMP
> +	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
>  	select ARCH_INLINE_SPIN_TRYLOCK
>  	select ARCH_INLINE_SPIN_TRYLOCK_BH
>  	select ARCH_INLINE_SPIN_LOCK
> Index: hibernate-2.6/arch/s390/kernel/suspend.c
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/kernel/suspend.c	2009-09-24 09:06:44.000000000 +0200
> +++ hibernate-2.6/arch/s390/kernel/suspend.c	2011-08-16 16:06:09.845540931 +0200
> @@ -7,6 +7,7 @@
>   */
>  
>  #include <linux/pfn.h>
> +#include <linux/mm.h>
>  #include <asm/system.h>
>  
>  /*
> @@ -14,6 +15,123 @@
>   */
>  extern const void __nosave_begin, __nosave_end;
>  
> +/*
> + * The restore of the saved pages in an hibernation image will set
> + * the change and referenced bits in the storage key for each page.
> + * Overindication of the referenced bits after an hibernation cycle
> + * does not cause any harm but the overindication of the change bits
> + * would cause trouble.
> + * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
> + * page to the most significant byte of the associated page frame
> + * number in the hibernation image.
> + */
> +
> +/*
> + * Key storage is allocated as a linked list of pages.
> + * The size of the keys array is (PAGE_SIZE - sizeof(long))
> + */
> +struct page_key_data {
> +	struct page_key_data *next;
> +	unsigned char data[];
> +};
> +
> +#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
> +
> +static struct page_key_data *page_key_data;
> +static struct page_key_data *page_key_rp, *page_key_wp;
> +static unsigned long page_key_rx, page_key_wx;
> +
> +/*
> + * For each page in the hibernation image one additional byte is
> + * stored in the most significant byte of the page frame number.
> + * On suspend no additional memory is required but on resume the
> + * keys need to be memorized until the page data has been restored.
> + * Only then can the storage keys be set to their old state.
> + */
> +unsigned long page_key_additional_pages(unsigned long pages)
> +{
> +	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
> +}
> +
> +/*
> + * Free page_key_data list of arrays.
> + */
> +void page_key_free(void)
> +{
> +	struct page_key_data *pkd;
> +
> +	while (page_key_data) {
> +		pkd = page_key_data;
> +		page_key_data = pkd->next;
> +		free_page((unsigned long) pkd);
> +	}
> +}
> +
> +/*
> + * Allocate page_key_data list of arrays with enough room to store
> + * one byte for each page in the hibernation image.
> + */
> +int page_key_alloc(unsigned long pages)
> +{
> +	struct page_key_data *pk;
> +	unsigned long size;
> +
> +	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
> +	while (size--) {
> +		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
> +		if (!pk) {
> +			page_key_free();
> +			return -ENOMEM;
> +		}
> +		pk->next = page_key_data;
> +		page_key_data = pk;
> +	}
> +	page_key_rp = page_key_wp = page_key_data;
> +	page_key_rx = page_key_wx = 0;
> +	return 0;
> +}
> +
> +/*
> + * Save the storage key into the upper 8 bits of the page frame number.
> + */
> +void page_key_read(unsigned long *pfn)
> +{
> +	unsigned long addr;
> +
> +	addr = (unsigned long) page_address(pfn_to_page(*pfn));
> +	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
> +}
> +
> +/*
> + * Extract the storage key from the upper 8 bits of the page frame number
> + * and store it in the page_key_data list of arrays.
> + */
> +void page_key_memorize(unsigned long *pfn)
> +{
> +	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
> +	*(unsigned char *) pfn = 0;
> +	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
> +		return;
> +	page_key_wp = page_key_wp->next;
> +	page_key_wx = 0;
> +}
> +
> +/*
> + * Get the next key from the page_key_data list of arrays and set the
> + * storage key of the page referred by @address. If @address refers to
> + * a "safe" page the swsusp_arch_resume code will transfer the storage
> + * key from the buffer page to the original page.
> + */
> +void page_key_write(void *address)
> +{
> +	page_set_storage_key((unsigned long) address,
> +			     page_key_rp->data[page_key_rx], 0);
> +	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
> +		return;
> +	page_key_rp = page_key_rp->next;
> +	page_key_rx = 0;
> +}
> +
>  int pfn_is_nosave(unsigned long pfn)
>  {
>  	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
> Index: hibernate-2.6/arch/s390/kernel/swsusp_asm64.S
> ===================================================================
> --- hibernate-2.6.orig/arch/s390/kernel/swsusp_asm64.S	2011-08-09 17:40:09.228010544 +0200
> +++ hibernate-2.6/arch/s390/kernel/swsusp_asm64.S	2011-08-16 16:06:09.845540931 +0200
> @@ -136,11 +136,14 @@
>  0:
>  	lg	%r2,8(%r1)
>  	lg	%r4,0(%r1)
> +	iske	%r0,%r4
>  	lghi	%r3,PAGE_SIZE
>  	lghi	%r5,PAGE_SIZE
>  1:
>  	mvcle	%r2,%r4,0
>  	jo	1b
> +	lg	%r2,8(%r1)
> +	sske	%r0,%r2
>  	lg	%r1,16(%r1)
>  	ltgr	%r1,%r1
>  	jnz	0b
> Index: hibernate-2.6/include/linux/suspend.h
> ===================================================================
> --- hibernate-2.6.orig/include/linux/suspend.h	2011-08-09 17:40:10.164030551 +0200
> +++ hibernate-2.6/include/linux/suspend.h	2011-08-16 16:06:09.845540931 +0200
> @@ -334,4 +334,38 @@
>  }
>  #endif
>  
> +#ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
> +/*
> + * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
> + * to save/restore additional information to/from the array of page
> + * frame numbers in the hibernation image. For s390 this is used to
> + * save and restore the storage key for each page that is included
> + * in the hibernation image.
> + */
> +unsigned long page_key_additional_pages(unsigned long pages);
> +int page_key_alloc(unsigned long pages);
> +void page_key_free(void);
> +void page_key_read(unsigned long *pfn);
> +void page_key_memorize(unsigned long *pfn);
> +void page_key_write(void *address);
> +
> +#else /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
> +
> +static inline unsigned long page_key_additional_pages(unsigned long pages)
> +{
> +	return 0;
> +}
> +
> +static inline int  page_key_alloc(unsigned long pages)
> +{
> +	return 0;
> +}
> +
> +static inline void page_key_free(void) {}
> +static inline void page_key_read(unsigned long *pfn) {}
> +static inline void page_key_memorize(unsigned long *pfn) {}
> +static inline void page_key_write(void *address) {}
> +
> +#endif /* !CONFIG_ARCH_SAVE_PAGE_KEYS */
> +
>  #endif /* _LINUX_SUSPEND_H */
> Index: hibernate-2.6/kernel/power/Kconfig
> ===================================================================
> --- hibernate-2.6.orig/kernel/power/Kconfig	2011-08-09 17:40:10.192031153 +0200
> +++ hibernate-2.6/kernel/power/Kconfig	2011-08-16 16:06:09.845540931 +0200
> @@ -65,6 +65,9 @@
>  
>  	  For more information take a look at <file:Documentation/power/swsusp.txt>.
>  
> +config ARCH_SAVE_PAGE_KEYS
> +	bool
> +
>  config PM_STD_PARTITION
>  	string "Default resume partition"
>  	depends on HIBERNATION
> Index: hibernate-2.6/kernel/power/snapshot.c
> ===================================================================
> --- hibernate-2.6.orig/kernel/power/snapshot.c	2011-07-08 11:25:06.293203483 +0200
> +++ hibernate-2.6/kernel/power/snapshot.c	2011-08-16 16:06:09.845540931 +0200
> @@ -1339,6 +1339,9 @@
>  	count += highmem;
>  	count -= totalreserve_pages;
>  
> +	/* Add number of pages required for page keys (s390 only). */
> +	size += page_key_additional_pages(saveable);
> +
>  	/* Compute the maximum number of saveable pages to leave in memory. */
>  	max_size = (count - (size + PAGES_FOR_IO)) / 2
>  			- 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
> @@ -1662,6 +1665,8 @@
>  		buf[j] = memory_bm_next_pfn(bm);
>  		if (unlikely(buf[j] == BM_END_OF_MAP))
>  			break;
> +		/* Save page key for data page (s390 only). */
> +		page_key_read(buf + j);
>  	}
>  }
>  
> @@ -1821,6 +1826,9 @@
>  		if (unlikely(buf[j] == BM_END_OF_MAP))
>  			break;
>  
> +		/* Extract and buffer page key for data page (s390 only). */
> +		page_key_memorize(buf + j);
> +
>  		if (memory_bm_pfn_present(bm, buf[j]))
>  			memory_bm_set_bit(bm, buf[j]);
>  		else
> @@ -2223,6 +2231,11 @@
>  		if (error)
>  			return error;
>  
> +		/* Allocate buffer for page keys. */
> +		error = page_key_alloc(nr_copy_pages);
> +		if (error)
> +			return error;
> +
>  	} else if (handle->cur <= nr_meta_pages + 1) {
>  		error = unpack_orig_pfns(buffer, &copy_bm);
>  		if (error)
> @@ -2243,6 +2256,8 @@
>  		}
>  	} else {
>  		copy_last_highmem_page();
> +		/* Restore page key for data page (s390 only). */
> +		page_key_write(handle->buffer);
>  		handle->buffer = get_buffer(&orig_bm, &ca);
>  		if (IS_ERR(handle->buffer))
>  			return PTR_ERR(handle->buffer);
> @@ -2264,6 +2279,9 @@
>  void snapshot_write_finalize(struct snapshot_handle *handle)
>  {
>  	copy_last_highmem_page();
> +	/* Restore page key for data page (s390 only). */
> +	page_key_write(handle->buffer);
> +	page_key_free();
>  	/* Free only if we have loaded the image entirely */
>  	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
>  		memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
> 
> 
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 17:56   ` Rafael J. Wysocki
  2011-08-17  7:43     ` Martin Schwidefsky
@ 2011-08-17  7:43     ` Martin Schwidefsky
  2011-08-17  9:15       ` Rafael J. Wysocki
  2011-08-17  9:15       ` Rafael J. Wysocki
  1 sibling, 2 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-17  7:43 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-pm, linux-kernel, linux-s390, Pavel Machek, Jiri Slaby

On Tue, 16 Aug 2011 19:56:47 +0200
"Rafael J. Wysocki" <rjw@sisk.pl> wrote:

> On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> > From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > 
> > For s390 there is one additional byte associated with each page,
> > the storage key. This byte contains the referenced and changed
> > bits and needs to be included into the hibernation image.
> > If the storage keys are not restored to their previous state all
> > original pages would appear to be dirty. This can cause
> > inconsistencies e.g. with read-only filesystems.
> > 
> > Cc: Pavel Machek <pavel@ucw.cz>
> > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > Cc: Jiri Slaby <jslaby@suse.cz>
> > Cc: linux-pm@lists.linux-foundation.org
> > Cc: linux-kernel@vger.kernel.org
> > Cc: linux-s390@vger.kernel.org
> > Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
> 
> OK, I don't have any complaints.  Do you want me to take this
> patch or do you want to push it through the s390 tree?

The patch affects the common power management code. At minimum I
would like an acked-by to take it into the s390 tree. I would feel
more comfortable if you'd take it via the power management tree
though.

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-16 17:56   ` Rafael J. Wysocki
@ 2011-08-17  7:43     ` Martin Schwidefsky
  2011-08-17  7:43     ` Martin Schwidefsky
  1 sibling, 0 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-17  7:43 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: linux-s390, linux-pm, Jiri Slaby, linux-kernel

On Tue, 16 Aug 2011 19:56:47 +0200
"Rafael J. Wysocki" <rjw@sisk.pl> wrote:

> On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> > From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > 
> > For s390 there is one additional byte associated with each page,
> > the storage key. This byte contains the referenced and changed
> > bits and needs to be included into the hibernation image.
> > If the storage keys are not restored to their previous state all
> > original pages would appear to be dirty. This can cause
> > inconsistencies e.g. with read-only filesystems.
> > 
> > Cc: Pavel Machek <pavel@ucw.cz>
> > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > Cc: Jiri Slaby <jslaby@suse.cz>
> > Cc: linux-pm@lists.linux-foundation.org
> > Cc: linux-kernel@vger.kernel.org
> > Cc: linux-s390@vger.kernel.org
> > Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
> 
> OK, I don't have any complaints.  Do you want me to take this
> patch or do you want to push it through the s390 tree?

The patch affects the common power management code. At minimum I
would like an acked-by to take it into the s390 tree. I would feel
more comfortable if you'd take it via the power management tree
though.

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-17  7:43     ` Martin Schwidefsky
@ 2011-08-17  9:15       ` Rafael J. Wysocki
  2011-08-17  9:15       ` Rafael J. Wysocki
  1 sibling, 0 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2011-08-17  9:15 UTC (permalink / raw)
  To: Martin Schwidefsky
  Cc: linux-pm, linux-kernel, linux-s390, Pavel Machek, Jiri Slaby

On Wednesday, August 17, 2011, Martin Schwidefsky wrote:
> On Tue, 16 Aug 2011 19:56:47 +0200
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> 
> > On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> > > From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > > 
> > > For s390 there is one additional byte associated with each page,
> > > the storage key. This byte contains the referenced and changed
> > > bits and needs to be included into the hibernation image.
> > > If the storage keys are not restored to their previous state all
> > > original pages would appear to be dirty. This can cause
> > > inconsistencies e.g. with read-only filesystems.
> > > 
> > > Cc: Pavel Machek <pavel@ucw.cz>
> > > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > > Cc: Jiri Slaby <jslaby@suse.cz>
> > > Cc: linux-pm@lists.linux-foundation.org
> > > Cc: linux-kernel@vger.kernel.org
> > > Cc: linux-s390@vger.kernel.org
> > > Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > 
> > OK, I don't have any complaints.  Do you want me to take this
> > patch or do you want to push it through the s390 tree?
> 
> The patch affects the common power management code. At minimum I
> would like an acked-by to take it into the s390 tree. I would feel
> more comfortable if you'd take it via the power management tree
> though.

OK, I will.  Expect it to appear in 3.2. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch 1/1] [PATCH] include storage keys in hibernation image.
  2011-08-17  7:43     ` Martin Schwidefsky
  2011-08-17  9:15       ` Rafael J. Wysocki
@ 2011-08-17  9:15       ` Rafael J. Wysocki
  1 sibling, 0 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2011-08-17  9:15 UTC (permalink / raw)
  To: Martin Schwidefsky; +Cc: linux-s390, linux-pm, Jiri Slaby, linux-kernel

On Wednesday, August 17, 2011, Martin Schwidefsky wrote:
> On Tue, 16 Aug 2011 19:56:47 +0200
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> 
> > On Tuesday, August 16, 2011, Martin Schwidefsky wrote:
> > > From: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > > 
> > > For s390 there is one additional byte associated with each page,
> > > the storage key. This byte contains the referenced and changed
> > > bits and needs to be included into the hibernation image.
> > > If the storage keys are not restored to their previous state all
> > > original pages would appear to be dirty. This can cause
> > > inconsistencies e.g. with read-only filesystems.
> > > 
> > > Cc: Pavel Machek <pavel@ucw.cz>
> > > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > > Cc: Jiri Slaby <jslaby@suse.cz>
> > > Cc: linux-pm@lists.linux-foundation.org
> > > Cc: linux-kernel@vger.kernel.org
> > > Cc: linux-s390@vger.kernel.org
> > > Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
> > 
> > OK, I don't have any complaints.  Do you want me to take this
> > patch or do you want to push it through the s390 tree?
> 
> The patch affects the common power management code. At minimum I
> would like an acked-by to take it into the s390 tree. I would feel
> more comfortable if you'd take it via the power management tree
> though.

OK, I will.  Expect it to appear in 3.2. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [patch 0/1] [patch 0/1] include storage keys in hibernation image
@ 2011-08-16 14:14 Martin Schwidefsky
  0 siblings, 0 replies; 10+ messages in thread
From: Martin Schwidefsky @ 2011-08-16 14:14 UTC (permalink / raw)
  To: linux-pm, linux-kernel, linux-s390, Rafael J. Wysocki,
	Pavel Machek, Jiri

Hi Rafael,

Version 2 of the storage key patch for hibernation on s390.
I've added the following changes as you requested:
1) moved the s390 specific code to arch/s390/kernel/suspend.c
2) introduced CONFIG_ARCH_SAVE_PAGE_KEYS and added a select to
   the main s390 Kconfig file
3) added the empty default functions to include/linux/suspend.h

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-08-17  9:15 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-16 14:14 [patch 0/1] [patch 0/1] include storage keys in hibernation image Martin Schwidefsky
2011-08-16 14:14 ` [patch 1/1] [PATCH] " Martin Schwidefsky
2011-08-16 14:14 ` Martin Schwidefsky
2011-08-16 17:56   ` Rafael J. Wysocki
2011-08-16 17:56   ` Rafael J. Wysocki
2011-08-17  7:43     ` Martin Schwidefsky
2011-08-17  7:43     ` Martin Schwidefsky
2011-08-17  9:15       ` Rafael J. Wysocki
2011-08-17  9:15       ` Rafael J. Wysocki
2011-08-16 14:14 [patch 0/1] [patch 0/1] " Martin Schwidefsky

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.