Don't use the first 64KB for anything, including tramps. Move tramps and
authormlarkin <mlarkin@openbsd.org>
Sun, 5 Jan 2014 20:23:56 +0000 (20:23 +0000)
committermlarkin <mlarkin@openbsd.org>
Sun, 5 Jan 2014 20:23:56 +0000 (20:23 +0000)
hibernate goo up after 64KB to avoid posible corruption by buggy BIOS SMM
code. Diff also ensures the first 64KB doesn't get handed to UVM either.

ok deraadt@, tested by many with no regressions reported

sys/arch/amd64/amd64/acpi_wakecode.S
sys/arch/amd64/amd64/machdep.c
sys/arch/amd64/amd64/mptramp.S
sys/arch/amd64/include/hibernate_var.h
sys/arch/amd64/include/mpbiosvar.h
sys/arch/i386/i386/acpi_wakecode.S
sys/arch/i386/i386/machdep.c
sys/arch/i386/i386/mptramp.s
sys/arch/i386/include/hibernate_var.h
sys/arch/i386/include/mpbiosvar.h
sys/dev/acpi/acpivar.h

index 8e94d2c..e8c54e7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi_wakecode.S,v 1.22 2013/12/26 18:52:09 mlarkin Exp $ */
+/* $OpenBSD: acpi_wakecode.S,v 1.23 2014/01/05 20:23:56 mlarkin Exp $ */
 /*
  * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
  * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
@@ -67,7 +67,7 @@
  *
  * We wakeup in real mode, at some phys addr based on the ACPI
  * specification (cs = phys>>8, ip = phys & 0xF). For example,
- * if our phys addr is 0x4000, we'd have cs=0x0400,ip=0
+ * if our phys addr is 0x11000, we'd have cs=0x1100,ip=0
  *
  * The wakeup code needs to do the following:
  *     1. Reenable the video display
@@ -410,7 +410,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3)
        movl    %eax, %cr0
 
        /* Set up real mode segment selectors */
-       movw    $0x0400, %ax
+       movw    $0x1100, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %fs
@@ -419,7 +419,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3)
        lidtl   clean_idt
 
        /* Jump to the S3 resume vector */
-       ljmp    $0x0400, $acpi_s3_vector_real
+       ljmp    $0x1100, $acpi_s3_vector_real
 
 NENTRY(hibernate_drop_to_real_mode)
        .code64
@@ -448,7 +448,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3b)
        movl    %eax, %cr0
 
        /* Set up real mode segment selectors */
-       movw    $0x0400, %ax
+       movw    $0x1100, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %fs
@@ -456,11 +456,11 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3b)
        movl    $0x0FFE, %esp
        lidtl   clean_idt
 
-       ljmp    $0x0400, $hib_hlt_real
+       ljmp    $0x1100, $hib_hlt_real
 
 _ACPI_TRMP_OFFSET(hib_hlt_real)
        hlt
-       ljmp    $0x0400, $hib_hlt_real
+       ljmp    $0x1100, $hib_hlt_real
 
        .code64
        /* Switch to hibernate resume pagetable */
index f5f140b..f63bb38 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: machdep.c,v 1.172 2013/12/23 23:23:22 deraadt Exp $   */
+/*     $OpenBSD: machdep.c,v 1.173 2014/01/05 20:23:56 mlarkin Exp $   */
 /*     $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
 
 /*-
@@ -1228,7 +1228,6 @@ map_tramps(void) {
            VM_PROT_ALL);               /* protection */
 #endif /* MULTIPROCESSOR */
 
-
        pmap_kenter_pa((vaddr_t)ACPI_TRAMPOLINE, /* virtual */
            (paddr_t)ACPI_TRAMPOLINE,   /* physical */
            VM_PROT_ALL);               /* protection */
@@ -1309,10 +1308,12 @@ init_x86_64(paddr_t first_avail)
  *
  * first_avail - This is the first available physical page after the
  *               kernel, page tables, etc.
+ *
+ * We skip the first few pages for trampolines, hibernate, and to avoid
+ * buggy SMI implementations that could corrupt the first 64KB.
  */
+       avail_start = 16*PAGE_SIZE;
 
-       avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */
-                                /* and VM system doesn't work with phys 0 */
 #ifdef MULTIPROCESSOR
        if (avail_start < MP_TRAMPOLINE + PAGE_SIZE)
                avail_start = MP_TRAMPOLINE + PAGE_SIZE;
@@ -1360,7 +1361,7 @@ init_x86_64(paddr_t first_avail)
                        continue;
 
                /* Check and adjust our segment(s) */
-               /* Nuke page zero */
+               /* Nuke low pages */
                if (s1 < avail_start) {
                        s1 = avail_start;
                        if (s1 > e1)
index aece9c3..e02cd7c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mptramp.S,v 1.7 2010/11/13 04:16:42 guenther Exp $    */
+/*     $OpenBSD: mptramp.S,v 1.8 2014/01/05 20:23:56 mlarkin Exp $     */
 /*     $NetBSD: mptramp.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
 
 /*-
@@ -88,6 +88,7 @@
 #define RELOC(x)        _RELOC(_C_LABEL(x))
 
 #define _TRMP_LABEL(a)  a = . - _C_LABEL(cpu_spinup_trampoline) + MP_TRAMPOLINE
+#define _TRMP_OFFSET(a)  a = . - _C_LABEL(cpu_spinup_trampoline)
 
        .globl  _C_LABEL(mpidle)
        .global _C_LABEL(cpu_spinup_trampoline)
        .code16
 _C_LABEL(cpu_spinup_trampoline):
        cli
-       xorw    %ax,%ax
+       movw    %cs, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %ss
@@ -182,7 +183,7 @@ _TRMP_LABEL(mptramp_gdt32)
        .quad 0x0000000000000000
        .quad 0x00cf9f000000ffff
        .quad 0x00cf93000000ffff
-_TRMP_LABEL(mptramp_gdt32_desc)
+_TRMP_OFFSET(mptramp_gdt32_desc)
        .word 0x17
        .long mptramp_gdt32
 
index 0c98de2..db8d774 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hibernate_var.h,v 1.6 2013/06/04 16:21:23 mlarkin Exp $       */
+/*     $OpenBSD: hibernate_var.h,v 1.7 2014/01/05 20:23:57 mlarkin Exp $       */
 
 /*
  * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
 /*
  * PML4 table for resume
  */
-#define HIBERNATE_PML4T                (PAGE_SIZE * 5)
+#define HIBERNATE_PML4T                (PAGE_SIZE * 18)
 
 /*
  * amd64 uses a PDPT to map the first 512GB phys mem plus one more
  * to map any ranges of phys mem past 512GB (if needed)
  */
-#define HIBERNATE_PDPT_LOW     (PAGE_SIZE * 6)
-#define HIBERNATE_PDPT_HI      (PAGE_SIZE * 7)
+#define HIBERNATE_PDPT_LOW     (PAGE_SIZE * 19)
+#define HIBERNATE_PDPT_HI      (PAGE_SIZE * 20)
 
 /*
  * amd64 uses one PD to map the first 1GB phys mem plus one more to map any
  * other 1GB ranges within the first 512GB phys, plus one more to map any
  * 1GB range in any subsequent 512GB range
  */
-#define HIBERNATE_PD_LOW       (PAGE_SIZE * 8)
-#define HIBERNATE_PD_LOW2      (PAGE_SIZE * 9)
-#define HIBERNATE_PD_HI                (PAGE_SIZE * 10)
+#define HIBERNATE_PD_LOW       (PAGE_SIZE * 21)
+#define HIBERNATE_PD_LOW2      (PAGE_SIZE * 22)
+#define HIBERNATE_PD_HI                (PAGE_SIZE * 23)
 
 /*
  * amd64 uses one PT to map the first 2MB phys mem plus one more to map any
  * other 2MB range within the first 1GB, plus one more to map any 2MB range
  * in any subsequent 512GB range.
  */
-#define HIBERNATE_PT_LOW       (PAGE_SIZE * 11)
-#define HIBERNATE_PT_LOW2      (PAGE_SIZE * 12)
-#define HIBERNATE_PT_HI                (PAGE_SIZE * 13)
+#define HIBERNATE_PT_LOW       (PAGE_SIZE * 24)
+#define HIBERNATE_PT_LOW2      (PAGE_SIZE * 25)
+#define HIBERNATE_PT_HI                (PAGE_SIZE * 26)
 
-#define HIBERNATE_SELTABLE     (PAGE_SIZE * 14)
+#define HIBERNATE_SELTABLE     (PAGE_SIZE * 27)
 
 /* 3 pages for stack */
-#define HIBERNATE_STACK_PAGE   (PAGE_SIZE * 17)
+#define HIBERNATE_STACK_PAGE   (PAGE_SIZE * 30)
 
-#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 18)
+#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 31)
 /* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */
-#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 19)
+#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 32)
 
 /* Use 4MB hibernation chunks */
 #define HIBERNATE_CHUNK_SIZE           0x400000
index 8dce24c..8cf3ce0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mpbiosvar.h,v 1.4 2011/03/23 16:54:34 pirofti Exp $   */
+/*     $OpenBSD: mpbiosvar.h,v 1.5 2014/01/05 20:23:57 mlarkin Exp $   */
 /* $NetBSD: mpbiosvar.h,v 1.2 2003/04/02 07:53:57 thorpej Exp $ */
 
 /*-
@@ -36,7 +36,7 @@
 #ifndef _MACHINE_MPBIOSVAR_H_
 #define _MACHINE_MPBIOSVAR_H_
 
-#define MP_TRAMPOLINE  (2 * PAGE_SIZE)
+#define MP_TRAMPOLINE  (16 * PAGE_SIZE)
 
 #if !defined(_LOCORE)
 
index b53da19..3e3c1f8 100644 (file)
@@ -70,7 +70,7 @@
  *
  * We wakeup in real mode, at some phys addr based on the ACPI
  * specification (cs = phys>>8, ip = phys & 0xF). For example,
- * if our phys addr is 0x4000, we'd have cs=0x0400,ip=0
+ * if our phys addr is 0x11000, we'd have cs=0x1100,ip=0
  *
  * The wakeup code needs to do the following:
  *     1. Reenable the video display
@@ -356,7 +356,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3)
        movl    %eax, %cr3
 
        /* Set up real mode segment selectors */
-       movw    $0x0400, %ax
+       movw    $0x1100, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %fs
@@ -365,7 +365,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3)
        lidtl   clean_idt
 
        /* Jump to the S3 resume vector */
-       ljmp    $0x0400, $acpi_s3_vector_real
+       ljmp    $0x1100, $acpi_s3_vector_real
 
        .code32
        /* Switch to hibernate resume pagetable */
index 075b54e..f1c873c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: machdep.c,v 1.530 2013/12/27 21:40:57 deraadt Exp $   */
+/*     $OpenBSD: machdep.c,v 1.531 2014/01/05 20:23:57 mlarkin Exp $   */
 /*     $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $    */
 
 /*-
@@ -165,6 +165,11 @@ extern struct proc *npxproc;
 #include <dev/ic/comvar.h>
 #endif /* NCOM > 0 */
 
+#ifdef HIBERNATE
+#include <machine/hibernate_var.h>
+#endif /* HIBERNATE */
+
+
 void   replacesmap(void);
 int     intr_handler(struct intrframe *, struct intrhand *);
 
@@ -3224,6 +3229,24 @@ init386(paddr_t first_avail)
                        if (a < 16 * NBPG)
                                a = 16 * NBPG;
 
+#ifdef MULTIPROCESSOR
+                       /* skip MP trampoline code page */
+                       if (a < MP_TRAMPOLINE + NBPG)
+                               a = MP_TRAMPOLINE + NBPG;
+#endif /* MULTIPROCESSOR */
+
+#if NACPI > 0 && !defined(SMALL_KERNEL)
+                       /* skip ACPI resume trampoline code page */
+                       if (a < ACPI_TRAMPOLINE + NBPG)
+                               a = ACPI_TRAMPOLINE + NBPG;
+#endif /* ACPI */
+
+#ifdef HIBERNATE
+                       /* skip hibernate reserved pages */
+                       if (a < HIBERNATE_HIBALLOC_PAGE + PAGE_SIZE)
+                               a = HIBERNATE_HIBALLOC_PAGE + PAGE_SIZE;
+#endif /* HIBERNATE */
+
                        /* skip shorter than page regions */
                        if (a >= e || (e - a) < NBPG) {
 #ifdef DEBUG
index e7d521e..10537ed 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mptramp.s,v 1.13 2010/04/01 19:48:50 kettenis Exp $   */
+/*     $OpenBSD: mptramp.s,v 1.14 2014/01/05 20:23:57 mlarkin Exp $    */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -89,6 +89,7 @@
 #define RELOC(x)       _RELOC(_C_LABEL(x))
 
 #define _TRMP_LABEL(a)  a = . - _C_LABEL(cpu_spinup_trampoline) + MP_TRAMPOLINE
+#define _TRMP_OFFSET(a)  a = . - _C_LABEL(cpu_spinup_trampoline)
 
 /*
  * Debug code to stop aux. processors in various stages based on the
        .code16
 _C_LABEL(cpu_spinup_trampoline):
        cli
-       xorw    %ax, %ax
+       movw    %cs, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %ss
@@ -130,7 +131,7 @@ _C_LABEL(cpu_spinup_trampoline):
        movl    %cr0, %eax      # get cr0
        orl     $0x1, %eax      # enable protected mode
        movl    %eax, %cr0      # doit
-       ljmp    $0x8, $mp_startup
+       ljmpl   $0x8, $mp_startup
 
 _TRMP_LABEL(mp_startup)
        .code32
@@ -213,7 +214,7 @@ _TRMP_LABEL(gdt_table)
        .word   0x0,0x0,0x0,0x0                 # null GDTE
         GDTE(0x9f,0xcf)                        # Kernel text
         GDTE(0x93,0xcf)                        # Kernel data
-_TRMP_LABEL(gdt_desc)
+_TRMP_OFFSET(gdt_desc)
        .word   0x17                            # limit 3 entries
        .long   gdt_table                       # where is gdt
 
index 41dba7b..34c589d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hibernate_var.h,v 1.8 2013/06/04 16:21:24 mlarkin Exp $       */
+/*     $OpenBSD: hibernate_var.h,v 1.9 2014/01/05 20:23:57 mlarkin Exp $       */
 
 /*
  * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
 
 #define PIGLET_PAGE_MASK ~((paddr_t)PAGE_MASK_4M)
 
-#define HIBERNATE_PD_PAGE      (PAGE_SIZE * 5)
-#define HIBERNATE_PT_PAGE      (PAGE_SIZE * 6)
-#define HIBERNATE_STACK_PAGE   (PAGE_SIZE * 8)
-#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 9)
-#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 10)
+#define HIBERNATE_PD_PAGE      (PAGE_SIZE * 18)
+#define HIBERNATE_PT_PAGE      (PAGE_SIZE * 19)
+/* 2 pages for stack */
+#define HIBERNATE_STACK_PAGE   (PAGE_SIZE * 21)
+#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 22)
+/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */
+#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 23)
 
 /* Use 4MB hibernation chunks */
 #define HIBERNATE_CHUNK_SIZE           0x400000
index 35ec699..d7dfb31 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mpbiosvar.h,v 1.10 2011/10/21 18:16:13 kettenis Exp $ */
+/*     $OpenBSD: mpbiosvar.h,v 1.11 2014/01/05 20:23:57 mlarkin Exp $  */
 /* $NetBSD: mpbiosvar.h,v 1.1.2.3 2000/02/29 13:17:20 sommerfeld Exp $ */
 
 /*-
@@ -36,7 +36,7 @@
 #ifndef _MACHINE_MPBIOSVAR_H_
 #define _MACHINE_MPBIOSVAR_H_
 
-#define MP_TRAMPOLINE  (7 * PAGE_SIZE)
+#define MP_TRAMPOLINE  (16 * PAGE_SIZE)
 
 #if !defined(_LOCORE)
 
index 023ced0..8ff3ce4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpivar.h,v 1.76 2013/11/06 10:40:36 mpi Exp $        */
+/*     $OpenBSD: acpivar.h,v 1.77 2014/01/05 20:23:57 mlarkin Exp $    */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
@@ -18,7 +18,7 @@
 #ifndef _DEV_ACPI_ACPIVAR_H_
 #define _DEV_ACPI_ACPIVAR_H_
 
-#define ACPI_TRAMPOLINE                (NBPG*4)
+#define ACPI_TRAMPOLINE                (17 * NBPG)
 
 #ifndef _ACPI_WAKECODE