Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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);
+31 −0
Original line number Original line Diff line number Diff line
@@ -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)
	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.
+26 −3
Original line number Original line Diff line number Diff line
@@ -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)
	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:
	/* 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