Pārlūkot izejas kodu

[S390] hibernation: fix register corruption on machine checks

swsusp_arch_suspend() actually saves all cpu register contents on
hibernation.
Machine checks must be disabled since swsusp_arch_suspend() stores
register contents to their lowcore save areas. That's the same
place where register contents on machine checks would be saved.
To avoid register corruption disable machine checks.
We must also disable machine checks in the new psw mask for
program checks, since swsusp_arch_suspend() may generate program
checks.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Heiko Carstens 16 gadi atpakaļ
vecāks
revīzija
c63b196afc
2 mainītis faili ar 25 papildinājumiem un 33 dzēšanām
  1. 24 12
      arch/s390/power/swsusp.c
  2. 1 21
      arch/s390/power/swsusp_asm64.S

+ 24 - 12
arch/s390/power/swsusp.c

@@ -7,24 +7,36 @@
  *
  *
  */
  */
 
 
+#include <asm/system.h>
 
 
-/*
- * save CPU registers before creating a hibernation image and before
- * restoring the memory state from it
- */
 void save_processor_state(void)
 void save_processor_state(void)
 {
 {
-	/* implentation contained in the
-	 * swsusp_arch_suspend function
+	/* swsusp_arch_suspend() actually saves all cpu register contents.
+	 * Machine checks must be disabled since swsusp_arch_suspend() stores
+	 * register contents to their lowcore save areas. That's the same
+	 * place where register contents on machine checks would be saved.
+	 * To avoid register corruption disable machine checks.
+	 * We must also disable machine checks in the new psw mask for
+	 * program checks, since swsusp_arch_suspend() may generate program
+	 * checks. Disabling machine checks for all other new psw masks is
+	 * just paranoia.
 	 */
 	 */
+	local_mcck_disable();
+	/* Disable lowcore protection */
+	__ctl_clear_bit(0,28);
+	S390_lowcore.external_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.svc_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.io_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask &= ~PSW_MASK_MCHECK;
 }
 }
 
 
-/*
- * restore the contents of CPU registers
- */
 void restore_processor_state(void)
 void restore_processor_state(void)
 {
 {
-	/* implentation contained in the
-	 * swsusp_arch_resume function
-	 */
+	S390_lowcore.external_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.svc_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.io_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask |= PSW_MASK_MCHECK;
+	/* Enable lowcore protection */
+	__ctl_set_bit(0,28);
+	local_mcck_enable();
 }
 }

+ 1 - 21
arch/s390/power/swsusp_asm64.S

@@ -32,11 +32,6 @@ swsusp_arch_suspend:
 	/* Deactivate DAT */
 	/* Deactivate DAT */
 	stnsm	__SF_EMPTY(%r15),0xfb
 	stnsm	__SF_EMPTY(%r15),0xfb
 
 
-	/* Switch off lowcore protection */
-	stctg	%c0,%c0,__SF_EMPTY(%r15)
-	ni	__SF_EMPTY+4(%r15),0xef
-	lctlg	%c0,%c0,__SF_EMPTY(%r15)
-
 	/* Store prefix register on stack */
 	/* Store prefix register on stack */
 	stpx	__SF_EMPTY(%r15)
 	stpx	__SF_EMPTY(%r15)
 
 
@@ -88,11 +83,6 @@ swsusp_arch_suspend:
 	/* Save image */
 	/* Save image */
 	brasl	%r14,swsusp_save
 	brasl	%r14,swsusp_save
 
 
-	/* Switch on lowcore protection */
-	stctg	%c0,%c0,__SF_EMPTY(%r15)
-	oi	__SF_EMPTY+4(%r15),0x10
-	lctlg	%c0,%c0,__SF_EMPTY(%r15)
-
 	/* Restore prefix register and return */
 	/* Restore prefix register and return */
 	lghi	%r1,0x1000
 	lghi	%r1,0x1000
 	spx	0x318(%r1)
 	spx	0x318(%r1)
@@ -120,11 +110,6 @@ swsusp_arch_resume:
 	/* Deactivate DAT */
 	/* Deactivate DAT */
 	stnsm	__SF_EMPTY(%r15),0xfb
 	stnsm	__SF_EMPTY(%r15),0xfb
 
 
-	/* Switch off lowcore protection */
-	stctg	%c0,%c0,__SF_EMPTY(%r15)
-	ni	__SF_EMPTY+4(%r15),0xef
-	lctlg	%c0,%c0,__SF_EMPTY(%r15)
-
 	/* Set prefix page to zero */
 	/* Set prefix page to zero */
 	xc	__SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
 	xc	__SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
 	spx	__SF_EMPTY(%r15)
 	spx	__SF_EMPTY(%r15)
@@ -178,7 +163,7 @@ swsusp_arch_resume:
 	/* Load old stack */
 	/* Load old stack */
 	lg	%r15,0x2f8(%r13)
 	lg	%r15,0x2f8(%r13)
 
 
-	/* Pointer to save arae */
+	/* Pointer to save area */
 	lghi	%r13,0x1000
 	lghi	%r13,0x1000
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
@@ -190,11 +175,6 @@ swsusp_arch_resume:
 	/* Restore prefix register */
 	/* Restore prefix register */
 	spx	0x318(%r13)
 	spx	0x318(%r13)
 
 
-	/* Switch on lowcore protection */
-	stctg	%c0,%c0,__SF_EMPTY(%r15)
-	oi	__SF_EMPTY+4(%r15),0x10
-	lctlg	%c0,%c0,__SF_EMPTY(%r15)
-
 	/* Activate DAT */
 	/* Activate DAT */
 	stosm	__SF_EMPTY(%r15),0x04
 	stosm	__SF_EMPTY(%r15),0x04