From 71ce0f956b5470f1b5ed3cd5902d41ebb25ae89c Mon Sep 17 00:00:00 2001 From: mlarkin Date: Sun, 5 Jan 2014 20:23:56 +0000 Subject: [PATCH] Don't use the first 64KB for anything, including tramps. Move tramps and 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 | 14 ++++++------- sys/arch/amd64/amd64/machdep.c | 11 +++++----- sys/arch/amd64/amd64/mptramp.S | 7 ++++--- sys/arch/amd64/include/hibernate_var.h | 28 +++++++++++++------------- sys/arch/amd64/include/mpbiosvar.h | 4 ++-- sys/arch/i386/i386/acpi_wakecode.S | 6 +++--- sys/arch/i386/i386/machdep.c | 25 ++++++++++++++++++++++- sys/arch/i386/i386/mptramp.s | 9 +++++---- sys/arch/i386/include/hibernate_var.h | 14 +++++++------ sys/arch/i386/include/mpbiosvar.h | 4 ++-- sys/dev/acpi/acpivar.h | 4 ++-- 11 files changed, 77 insertions(+), 49 deletions(-) diff --git a/sys/arch/amd64/amd64/acpi_wakecode.S b/sys/arch/amd64/amd64/acpi_wakecode.S index 8e94d2ccfd0..e8c54e7a14f 100644 --- a/sys/arch/amd64/amd64/acpi_wakecode.S +++ b/sys/arch/amd64/amd64/acpi_wakecode.S @@ -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 * Copyright (c) 2001 Mitsuru IWASAKI @@ -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 */ diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index f5f140b2a10..f63bb386144 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -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) diff --git a/sys/arch/amd64/amd64/mptramp.S b/sys/arch/amd64/amd64/mptramp.S index aece9c33443..e02cd7c00e4 100644 --- a/sys/arch/amd64/amd64/mptramp.S +++ b/sys/arch/amd64/amd64/mptramp.S @@ -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) @@ -105,7 +106,7 @@ .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 diff --git a/sys/arch/amd64/include/hibernate_var.h b/sys/arch/amd64/include/hibernate_var.h index 0c98de261ff..db8d774b4e5 100644 --- a/sys/arch/amd64/include/hibernate_var.h +++ b/sys/arch/amd64/include/hibernate_var.h @@ -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 @@ -27,41 +27,41 @@ /* * 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 diff --git a/sys/arch/amd64/include/mpbiosvar.h b/sys/arch/amd64/include/mpbiosvar.h index 8dce24cbb5e..8cf3ce0fb6d 100644 --- a/sys/arch/amd64/include/mpbiosvar.h +++ b/sys/arch/amd64/include/mpbiosvar.h @@ -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) diff --git a/sys/arch/i386/i386/acpi_wakecode.S b/sys/arch/i386/i386/acpi_wakecode.S index b53da19bac9..3e3c1f8fd56 100644 --- a/sys/arch/i386/i386/acpi_wakecode.S +++ b/sys/arch/i386/i386/acpi_wakecode.S @@ -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 */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 075b54ec348..f1c873cdf75 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -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 #endif /* NCOM > 0 */ +#ifdef HIBERNATE +#include +#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 diff --git a/sys/arch/i386/i386/mptramp.s b/sys/arch/i386/i386/mptramp.s index e7d521e52e5..10537ed2208 100644 --- a/sys/arch/i386/i386/mptramp.s +++ b/sys/arch/i386/i386/mptramp.s @@ -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 @@ -122,7 +123,7 @@ .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 diff --git a/sys/arch/i386/include/hibernate_var.h b/sys/arch/i386/include/hibernate_var.h index 41dba7b502c..34c589d37d7 100644 --- a/sys/arch/i386/include/hibernate_var.h +++ b/sys/arch/i386/include/hibernate_var.h @@ -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 @@ -24,11 +24,13 @@ #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 diff --git a/sys/arch/i386/include/mpbiosvar.h b/sys/arch/i386/include/mpbiosvar.h index 35ec69974a5..d7dfb312d4b 100644 --- a/sys/arch/i386/include/mpbiosvar.h +++ b/sys/arch/i386/include/mpbiosvar.h @@ -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) diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h index 023ced0408c..8ff3ce45f8f 100644 --- a/sys/dev/acpi/acpivar.h +++ b/sys/dev/acpi/acpivar.h @@ -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 * @@ -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 -- 2.20.1