Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch The MSR EFER state is not saved and restored when s...



details:   https://anonhg.NetBSD.org/src/rev/1631d23c4bd5
branches:  trunk
changeset: 816780:1631d23c4bd5
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Jul 24 14:09:22 2016 +0000

description:
The MSR EFER state is not saved and restored when sleeping on i386. On PAE,
the CPU crashes right after waking up, since it needs to access NOX-ed
pages, which are to be enabled in an MSR.

Fix this by properly saving and restoring the EFER MSR. It's a little
tricky since the wakeup code uses %edx, but rdmsr overwrites it. We just
save it in %esi.

Now, the CPU sleeps properly on PAE kernels.

diffstat:

 sys/arch/i386/acpi/acpi_wakecode.S   |  20 +++++++++++++++++++-
 sys/arch/i386/acpi/acpi_wakeup_low.S |  17 +++++++++++++++--
 sys/arch/x86/acpi/acpi_wakeup.c      |  10 ++++------
 3 files changed, 38 insertions(+), 9 deletions(-)

diffs (135 lines):

diff -r 47f8bbc2c427 -r 1631d23c4bd5 sys/arch/i386/acpi/acpi_wakecode.S
--- a/sys/arch/i386/acpi/acpi_wakecode.S        Sun Jul 24 13:23:25 2016 +0000
+++ b/sys/arch/i386/acpi/acpi_wakecode.S        Sun Jul 24 14:09:22 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi_wakecode.S,v 1.17 2016/07/24 13:04:58 maxv Exp $  */
+/*     $NetBSD: acpi_wakecode.S,v 1.18 2016/07/24 14:09:22 maxv Exp $  */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -159,6 +159,13 @@
        movl    WAKEUP_r_cr4 + ACPI_WAKEUP_ADDR,%eax
        movl    %eax,%cr4
 
+       /*
+        * Load the correct MSR EFER value now to not depend on the
+        * data segment register. After this point, no instruction is
+        * allowed to clobber %ebx until wrmsr.
+        */
+       movl    WAKEUP_efer + ACPI_WAKEUP_ADDR,%ebx
+
        /* Load temporary page table, we will switch to full page table later */
        movl    WAKEUP_r_cr3 + ACPI_WAKEUP_ADDR,%eax
        movl    %eax,%cr3
@@ -175,6 +182,15 @@
 
        nop
 
+       /*
+        * Load the normal system value of MSR EFER.  This includes
+        * enabling NXE (if supported).
+        */
+       movl    %ebx,%eax
+       movl    $0,%edx
+       movl    $MSR_EFER,%ecx
+       wrmsr
+
        /* Restore registers */
        movl    WAKEUP_curcpu + ACPI_WAKEUP_ADDR,%edx
        movl    WAKEUP_restorecpu + ACPI_WAKEUP_ADDR,%ebx
@@ -209,6 +225,8 @@
 WAKEUP_curcpu:         .long 0
        .global WAKEUP_restorecpu
 WAKEUP_restorecpu:     .long 0
+       .global WAKEUP_efer
+WAKEUP_efer:           .long 0
 
        .global WAKEUP_vbios_reset
 WAKEUP_vbios_reset:    .byte 0
diff -r 47f8bbc2c427 -r 1631d23c4bd5 sys/arch/i386/acpi/acpi_wakeup_low.S
--- a/sys/arch/i386/acpi/acpi_wakeup_low.S      Sun Jul 24 13:23:25 2016 +0000
+++ b/sys/arch/i386/acpi/acpi_wakeup_low.S      Sun Jul 24 14:09:22 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi_wakeup_low.S,v 1.6 2016/07/24 13:04:58 maxv Exp $ */
+/*     $NetBSD: acpi_wakeup_low.S,v 1.7 2016/07/24 14:09:22 maxv Exp $ */
 
 /*-
  * Copyright (c) 2007 Joerg Sonnenberger <joerg%netbsd.org@localhost>
@@ -29,10 +29,11 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup_low.S,v 1.6 2016/07/24 13:04:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup_low.S,v 1.7 2016/07/24 14:09:22 maxv Exp $");
 
 #include "assym.h"
 #include <machine/segments.h>
+#include <machine/specialreg.h>
 
        .text
        .p2align 2, 0x90
@@ -51,6 +52,13 @@
        movw    ACPI_SUSPEND_GS(%edx),%ax
        movw    %ax,%gs
 
+       movl    $MSR_EFER,%ecx
+       movl    ACPI_SUSPEND_EFER(%edx),%eax
+       movl    %edx,%esi
+       movl    $0,%edx
+       wrmsr
+       movl    %esi,%edx
+
        movl    ACPI_SUSPEND_CR2(%edx),%eax
        movl    %eax,%cr2
        movl    ACPI_SUSPEND_CR4(%edx),%eax
@@ -96,6 +104,11 @@
        movl    %ebp,ACPI_SUSPEND_REG+(3*4)(%edx)
        movl    %esp,ACPI_SUSPEND_REG+(4*4)(%edx)
 
+       movl    $MSR_EFER,%ecx
+       rdmsr
+       movl    CPUVAR(SELF),%edx
+       movl    %eax,ACPI_SUSPEND_EFER(%edx)
+
        movl    %cr0,%eax
        movl    %eax,ACPI_SUSPEND_CR0(%edx)
        movl    %cr2,%eax
diff -r 47f8bbc2c427 -r 1631d23c4bd5 sys/arch/x86/acpi/acpi_wakeup.c
--- a/sys/arch/x86/acpi/acpi_wakeup.c   Sun Jul 24 13:23:25 2016 +0000
+++ b/sys/arch/x86/acpi/acpi_wakeup.c   Sun Jul 24 14:09:22 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi_wakeup.c,v 1.39 2015/08/18 10:42:41 christos Exp $        */
+/*     $NetBSD: acpi_wakeup.c,v 1.40 2016/07/24 14:09:22 maxv Exp $    */
 
 /*-
  * Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.39 2015/08/18 10:42:41 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.40 2016/07/24 14:09:22 maxv Exp $");
 
 /*-
  * Copyright (c) 2001 Takanori Watanabe <takawata%jp.freebsd.org@localhost>
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.39 2015/08/18 10:42:41 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.40 2016/07/24 14:09:22 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -165,10 +165,8 @@
 
 #ifdef __i386__
        WAKECODE_FIXUP(WAKEUP_r_cr4, uint32_t, ci->ci_suspend_cr4);
-#else
+#endif
        WAKECODE_FIXUP(WAKEUP_efer, uint32_t, ci->ci_suspend_efer);
-#endif
-
        WAKECODE_FIXUP(WAKEUP_curcpu, void *, ci);
 #ifdef __i386__
        WAKECODE_FIXUP(WAKEUP_r_cr3, uint32_t, tmp_pdir);



Home | Main Index | Thread Index | Old Index