Commit 91c15a95 authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky

s390/hibernate: Save and restore absolute zero pages

Since commit 5f954c34 ([S390] hibernation: fix lowcore handling)
the absolute zero lowcore is lost during suspend/resume.
For example, this leads to the problem that the re-IPL device
for kdump is no longer set after resume.

With this patch during suspend a buffer is allocated in the new PM
notifier "suspend_pm_cb" and then the absolute zero lowcore is saved
to that buffer. The resume code then copies back this buffer to
absolute zero and afterwards the PM notifier releases the memory.
Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 5294ee00
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <asm/cputime.h> #include <asm/cputime.h>
extern void *restart_stack; extern void *restart_stack;
extern unsigned long suspend_zero_pages;
void system_call(void); void system_call(void);
void pgm_check_handler(void); void pgm_check_handler(void);
......
...@@ -41,6 +41,7 @@ struct page_key_data { ...@@ -41,6 +41,7 @@ struct page_key_data {
static struct page_key_data *page_key_data; static struct page_key_data *page_key_data;
static struct page_key_data *page_key_rp, *page_key_wp; static struct page_key_data *page_key_rp, *page_key_wp;
static unsigned long page_key_rx, page_key_wx; static unsigned long page_key_rx, page_key_wx;
unsigned long suspend_zero_pages;
/* /*
* For each page in the hibernation image one additional byte is * For each page in the hibernation image one additional byte is
...@@ -149,6 +150,36 @@ int pfn_is_nosave(unsigned long pfn) ...@@ -149,6 +150,36 @@ int pfn_is_nosave(unsigned long pfn)
return 0; return 0;
} }
/*
* PM notifier callback for suspend
*/
static int suspend_pm_cb(struct notifier_block *nb, unsigned long action,
void *ptr)
{
switch (action) {
case PM_SUSPEND_PREPARE:
case PM_HIBERNATION_PREPARE:
suspend_zero_pages = __get_free_pages(GFP_KERNEL, LC_ORDER);
if (!suspend_zero_pages)
return NOTIFY_BAD;
break;
case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:
free_pages(suspend_zero_pages, LC_ORDER);
break;
default:
return NOTIFY_DONE;
}
return NOTIFY_OK;
}
static int __init suspend_pm_init(void)
{
pm_notifier(suspend_pm_cb, 0);
return 0;
}
arch_initcall(suspend_pm_init);
void save_processor_state(void) void save_processor_state(void)
{ {
/* swsusp_arch_suspend() actually saves all cpu register contents. /* swsusp_arch_suspend() actually saves all cpu register contents.
......
...@@ -36,8 +36,8 @@ ENTRY(swsusp_arch_suspend) ...@@ -36,8 +36,8 @@ ENTRY(swsusp_arch_suspend)
/* Store prefix register on stack */ /* Store prefix register on stack */
stpx __SF_EMPTY(%r15) stpx __SF_EMPTY(%r15)
/* Save prefix register contents for lowcore */ /* Save prefix register contents for lowcore copy */
llgf %r4,__SF_EMPTY(%r15) llgf %r10,__SF_EMPTY(%r15)
/* Get pointer to save area */ /* Get pointer to save area */
lghi %r1,0x1000 lghi %r1,0x1000
...@@ -91,7 +91,18 @@ ENTRY(swsusp_arch_suspend) ...@@ -91,7 +91,18 @@ ENTRY(swsusp_arch_suspend)
xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15) xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
spx __SF_EMPTY(%r15) spx __SF_EMPTY(%r15)
/* Save absolute zero pages */
larl %r2,suspend_zero_pages
lg %r2,0(%r2)
lghi %r4,0
lghi %r3,2*PAGE_SIZE
lghi %r5,2*PAGE_SIZE
1: mvcle %r2,%r4,0
jo 1b
/* Copy lowcore to absolute zero lowcore */
lghi %r2,0 lghi %r2,0
lgr %r4,%r10
lghi %r3,2*PAGE_SIZE lghi %r3,2*PAGE_SIZE
lghi %r5,2*PAGE_SIZE lghi %r5,2*PAGE_SIZE
1: mvcle %r2,%r4,0 1: mvcle %r2,%r4,0
...@@ -248,8 +259,20 @@ restore_registers: ...@@ -248,8 +259,20 @@ restore_registers:
/* Load old stack */ /* Load old stack */
lg %r15,0x2f8(%r13) lg %r15,0x2f8(%r13)
/* Save prefix register */
mvc __SF_EMPTY(4,%r15),0x318(%r13)
/* Restore absolute zero pages */
lghi %r2,0
larl %r4,suspend_zero_pages
lg %r4,0(%r4)
lghi %r3,2*PAGE_SIZE
lghi %r5,2*PAGE_SIZE
1: mvcle %r2,%r4,0
jo 1b
/* Restore prefix register */ /* Restore prefix register */
spx 0x318(%r13) spx __SF_EMPTY(%r15)
/* Activate DAT */ /* Activate DAT */
stosm __SF_EMPTY(%r15),0x04 stosm __SF_EMPTY(%r15),0x04
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment