diff options
author | Mike Larkin <mlarkin@cvs.openbsd.org> | 2016-05-20 02:30:42 +0000 |
---|---|---|
committer | Mike Larkin <mlarkin@cvs.openbsd.org> | 2016-05-20 02:30:42 +0000 |
commit | 82fcb12f6a9b0a37a29ffb6aa7533baa876d8aed (patch) | |
tree | 648913c1b5fe52494daea94cde308ac2a6688826 /sys/arch | |
parent | b4f71af8a5425123b36243f9e752767cb4505da2 (diff) |
split the ACPI resume trampoline into code and data pages, and protect
with proper permissions. Same treatment was done on amd64 last year, i386
is catching up.
This diff has been in snaps for a few days, no regressions reported.
ok deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/i386/i386/acpi_machdep.c | 34 | ||||
-rw-r--r-- | sys/arch/i386/i386/acpi_wakecode.S | 111 | ||||
-rw-r--r-- | sys/arch/i386/i386/autoconf.c | 8 | ||||
-rw-r--r-- | sys/arch/i386/i386/hibernate_machdep.c | 21 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 6 |
5 files changed, 115 insertions, 65 deletions
diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c index b08ce6fdeb9..6d4025ec6ff 100644 --- a/sys/arch/i386/i386/acpi_machdep.c +++ b/sys/arch/i386/i386/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.59 2015/05/30 08:41:30 kettenis Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.60 2016/05/20 02:30:41 mlarkin Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -63,6 +63,7 @@ int haveacpibutusingapm; #endif extern u_char acpi_real_mode_resume[], acpi_resume_end[]; +extern u_char acpi_tramp_data_start[], acpi_tramp_data_end[]; extern int acpi_savecpu(void) __returns_twice; extern void intr_calculatemasks(void); @@ -239,12 +240,31 @@ acpi_attach_machdep(struct acpi_softc *sc) /* * Sanity check before setting up trampoline. - * Ensure the trampoline size is < PAGE_SIZE + * Ensure the trampoline page sizes are < PAGE_SIZE */ KASSERT(acpi_resume_end - acpi_real_mode_resume < PAGE_SIZE); + KASSERT(acpi_tramp_data_end - acpi_tramp_data_start < PAGE_SIZE); - bcopy(acpi_real_mode_resume, (caddr_t)ACPI_TRAMPOLINE, + /* Map ACPI tramp code and data pages RW for copy */ + pmap_kenter_pa(ACPI_TRAMPOLINE, ACPI_TRAMPOLINE, + PROT_READ | PROT_WRITE); + pmap_kenter_pa(ACPI_TRAMP_DATA, ACPI_TRAMP_DATA, + PROT_READ | PROT_WRITE); + + /* Fill the trampoline pages with int3 */ + memset((caddr_t)ACPI_TRAMPOLINE, 0xcc, PAGE_SIZE); + memset((caddr_t)ACPI_TRAMP_DATA, 0xcc, PAGE_SIZE); + + /* Copy over real trampoline pages (code and data) */ + memcpy((caddr_t)ACPI_TRAMPOLINE, acpi_real_mode_resume, acpi_resume_end - acpi_real_mode_resume); + memcpy((caddr_t)ACPI_TRAMP_DATA, acpi_tramp_data_start, + acpi_tramp_data_end - acpi_tramp_data_start); + + /* Unmap, will be remapped in acpi_sleep_cpu */ + pmap_kremove(ACPI_TRAMPOLINE, PAGE_SIZE); + pmap_kremove(ACPI_TRAMP_DATA, PAGE_SIZE); + #endif /* SMALL_KERNEL */ } @@ -318,6 +338,11 @@ acpi_sleep_cpu(struct acpi_softc *sc, int state) if (sc->sc_facs->length > 32 && sc->sc_facs->version >= 1) sc->sc_facs->x_wakeup_vector = 0; + /* Map trampoline and data page */ + pmap_kenter_pa(ACPI_TRAMPOLINE, ACPI_TRAMPOLINE, PROT_READ | PROT_EXEC); + pmap_kenter_pa(ACPI_TRAMP_DATA, ACPI_TRAMP_DATA, + PROT_READ | PROT_WRITE); + /* Copy the current cpu registers into a safe place for resume. * acpi_savecpu actually returns twice - once in the suspend * path and once in the resume path (see setjmp(3)). @@ -357,6 +382,9 @@ acpi_sleep_cpu(struct acpi_softc *sc, int state) if (sc->sc_facs->length > 32 && sc->sc_facs->version >= 1) sc->sc_facs->x_wakeup_vector = 0; + pmap_kremove(ACPI_TRAMPOLINE, PAGE_SIZE); + pmap_kremove(ACPI_TRAMP_DATA, PAGE_SIZE); + return (0); } diff --git a/sys/arch/i386/i386/acpi_wakecode.S b/sys/arch/i386/i386/acpi_wakecode.S index ae21ed92fec..1d722180278 100644 --- a/sys/arch/i386/i386/acpi_wakecode.S +++ b/sys/arch/i386/i386/acpi_wakecode.S @@ -54,7 +54,11 @@ #define _ACPI_TRMP_LABEL(a) a = . - _C_LABEL(acpi_real_mode_resume) + ACPI_TRAMPOLINE #define _ACPI_TRMP_OFFSET(a) a = . - _C_LABEL(acpi_real_mode_resume) -#define _ACPI_RM_SEGMENT (ACPI_TRAMPOLINE >> 4) +#define _ACPI_TRMP_DATA_LABEL(a) a = . - _C_LABEL(acpi_tramp_data_start) + \ + ACPI_TRAMP_DATA +#define _ACPI_TRMP_DATA_OFFSET(a) a = . - _C_LABEL(acpi_tramp_data_start) +#define _ACPI_RM_CODE_SEG (ACPI_TRAMPOLINE >> 4) +#define _ACPI_RM_DATA_SEG (ACPI_TRAMP_DATA >> 4) #ifdef HIBERNATE #define HIBERNATE_STACK_OFFSET 0x0F00 @@ -85,6 +89,8 @@ .global _C_LABEL(acpi_real_mode_resume) .global _C_LABEL(acpi_protected_mode_resume) .global _C_LABEL(acpi_resume_end) + .global _C_LABEL(acpi_tramp_data_start) + .global _C_LABEL(acpi_tramp_data_end) _C_LABEL(acpi_real_mode_resume): _ACPI_TRMP_OFFSET(acpi_s3_vector_real) nop @@ -97,10 +103,11 @@ _ACPI_TRMP_OFFSET(acpi_s3_vector_real) * want real dependencies on data or stack, so we'll just use * the code segment for data and stack (eg, a 64k memory space). */ - movw %cs,%ax - movw %ax,%ds - movw %ax,%es - movw %ax,%ss + movw $(_ACPI_RM_DATA_SEG), %ax + movw %ax, %ds + movw %ax, %ss + movw %cs, %ax + movw %ax, %es lidtl clean_idt /* @@ -118,13 +125,6 @@ _ACPI_TRMP_OFFSET(acpi_s3_vector_real) popfl /* - * Set up esi to point to start of current routine's CS. - */ - xorl %esi,%esi - movw %cs,%si - shll $4,%esi - - /* * Flush instruction prefetch queue */ jmp 1f @@ -184,9 +184,7 @@ _C_LABEL(acpi_protected_mode_resume): * because we haven't put anything on the stack via a * call or push that we haven't cleaned up already. */ - movl %esi, %esp - addl $0x0FFE, %esp - + addl $(ACPI_TRAMP_DATA), %esp /* * Reset our page size extension (via restoring cr4) to what @@ -337,8 +335,9 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3) movl %eax, %cr3 /* Set up real mode segment selectors */ - movw $0x1300, %ax + movw $(_ACPI_RM_DATA_SEG), %ax movw %ax, %ds + movw %ax, %ss movw %ax, %es movw %ax, %fs movw %ax, %gs @@ -346,7 +345,7 @@ _ACPI_TRMP_LABEL(hibernate_resume_vector_3) lidtl clean_idt /* Jump to the S3 resume vector */ - ljmp $0x1300, $acpi_s3_vector_real + ljmp $(_ACPI_RM_CODE_SEG), $acpi_s3_vector_real .code32 /* Switch to hibernate resume pagetable */ @@ -400,14 +399,23 @@ NENTRY(hibernate_flush) ret #endif /* HIBERNATE */ - .code16 - .align 8, 0xcc -_ACPI_TRMP_OFFSET(tmp_gdt) + /* + * End of resume code (code copied to ACPI_TRAMPOLINE) + */ +_C_LABEL(acpi_resume_end): + + /* + * Initial copy of this data gets placed in .rodata, kernel makes + * RW copy of it in the tramp data page. + */ + .section .rodata +_C_LABEL(acpi_tramp_data_start): +_ACPI_TRMP_DATA_OFFSET(tmp_gdt) .word tmp_gdt_end - tmp_gdtable .long tmp_gdtable .align 8, 0xcc -_ACPI_TRMP_LABEL(tmp_gdtable) +_ACPI_TRMP_DATA_LABEL(tmp_gdtable) /* * null */ @@ -444,10 +452,10 @@ _ACPI_TRMP_LABEL(tmp_gdtable) */ .word 0xffff, 0 .byte 0, 0x93, 0xcf, 0 -_ACPI_TRMP_LABEL(tmp_gdt_end) +_ACPI_TRMP_DATA_LABEL(tmp_gdt_end) .align 8, 0xcc -_ACPI_TRMP_OFFSET(clean_idt) +_ACPI_TRMP_DATA_OFFSET(clean_idt) .word 0xffff .long 0 .word 0 @@ -457,12 +465,12 @@ _ACPI_TRMP_OFFSET(clean_idt) * reads/writes (sets up a 16 bit segment) */ .align 8, 0xcc -_ACPI_TRMP_LABEL(gdt_16) +_ACPI_TRMP_DATA_LABEL(gdt_16) .word gdt_16_end - gdt_16_table .long gdt_16_table .align 8, 0xcc -_ACPI_TRMP_LABEL(gdt_16_table) +_ACPI_TRMP_DATA_LABEL(gdt_16_table) /* * null */ @@ -500,66 +508,63 @@ _ACPI_TRMP_LABEL(gdt_16_table) .word 0xffff, 0 .byte 0, 0x93, 0x8f, 0 -_ACPI_TRMP_LABEL(gdt_16_end) +_ACPI_TRMP_DATA_LABEL(gdt_16_end) .align 4, 0xcc -_ACPI_TRMP_LABEL(acpi_saved_ebx) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ebx) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_ecx) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ecx) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_edx) +_ACPI_TRMP_DATA_LABEL(acpi_saved_edx) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_ebp) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ebp) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_esi) +_ACPI_TRMP_DATA_LABEL(acpi_saved_esi) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_edi) +_ACPI_TRMP_DATA_LABEL(acpi_saved_edi) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_esp) +_ACPI_TRMP_DATA_LABEL(acpi_saved_esp) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_fl) +_ACPI_TRMP_DATA_LABEL(acpi_saved_fl) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_cr0) +_ACPI_TRMP_DATA_LABEL(acpi_saved_cr0) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_cr2) +_ACPI_TRMP_DATA_LABEL(acpi_saved_cr2) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_cr3) +_ACPI_TRMP_DATA_LABEL(acpi_saved_cr3) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_cr4) +_ACPI_TRMP_DATA_LABEL(acpi_saved_cr4) .long 0 -_ACPI_TRMP_LABEL(acpi_saved_ret) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ret) .long 0 .align 16, 0xcc -_ACPI_TRMP_LABEL(acpi_saved_idt) +_ACPI_TRMP_DATA_LABEL(acpi_saved_idt) .space 6 .align 16, 0xcc -_ACPI_TRMP_LABEL(acpi_saved_gdt) +_ACPI_TRMP_DATA_LABEL(acpi_saved_gdt) .space 6 .align 16, 0xcc -_ACPI_TRMP_LABEL(acpi_saved_ldt) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ldt) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_cs) +_ACPI_TRMP_DATA_LABEL(acpi_saved_cs) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_ds) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ds) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_es) +_ACPI_TRMP_DATA_LABEL(acpi_saved_es) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_fs) +_ACPI_TRMP_DATA_LABEL(acpi_saved_fs) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_gs) +_ACPI_TRMP_DATA_LABEL(acpi_saved_gs) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_ss) +_ACPI_TRMP_DATA_LABEL(acpi_saved_ss) .short 0 -_ACPI_TRMP_LABEL(acpi_saved_tr) +_ACPI_TRMP_DATA_LABEL(acpi_saved_tr) .short 0 - /* - * End of resume code (code copied to ACPI_TRAMPOLINE) - */ -_C_LABEL(acpi_resume_end): +_C_LABEL(acpi_tramp_data_end): /* * acpi_savecpu saves the processor's registers and flags diff --git a/sys/arch/i386/i386/autoconf.c b/sys/arch/i386/i386/autoconf.c index 2037862de79..72d9499dfe2 100644 --- a/sys/arch/i386/i386/autoconf.c +++ b/sys/arch/i386/i386/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.99 2016/05/18 03:45:11 mlarkin Exp $ */ +/* $OpenBSD: autoconf.c,v 1.100 2016/05/20 02:30:41 mlarkin Exp $ */ /* $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $ */ /*- @@ -145,12 +145,6 @@ cpu_configure(void) PROT_READ | PROT_WRITE); /* protection */ #endif -#if NACPI > 0 && !defined(SMALL_KERNEL) - pmap_kenter_pa((vaddr_t)ACPI_TRAMPOLINE, /* virtual */ - (paddr_t)ACPI_TRAMPOLINE, /* physical */ - PROT_READ | PROT_WRITE | PROT_EXEC); /* protection */ -#endif - if (config_rootfound("mainbus", NULL) == NULL) panic("cpu_configure: mainbus not configured"); diff --git a/sys/arch/i386/i386/hibernate_machdep.c b/sys/arch/i386/i386/hibernate_machdep.c index fbb6f05492d..da0f1251ded 100644 --- a/sys/arch/i386/i386/hibernate_machdep.c +++ b/sys/arch/i386/i386/hibernate_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hibernate_machdep.c,v 1.48 2016/05/18 03:45:11 mlarkin Exp $ */ +/* $OpenBSD: hibernate_machdep.c,v 1.49 2016/05/20 02:30:41 mlarkin Exp $ */ /* * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org> @@ -136,7 +136,17 @@ get_hibernate_info_md(union hibernate_info *hiber_info) hiber_info->ranges[i].base; } + /* Record lowmem PTP page */ + if (hiber_info->nranges >= VM_PHYSSEG_MAX) + return (1); + hiber_info->ranges[hiber_info->nranges].base = PTP0_PA; + hiber_info->ranges[hiber_info->nranges].end = + hiber_info->ranges[hiber_info->nranges].base + PAGE_SIZE; + hiber_info->image_size += PAGE_SIZE; + hiber_info->nranges++; + #if NACPI > 0 + /* Record ACPI trampoline code page */ if (hiber_info->nranges >= VM_PHYSSEG_MAX) return (1); hiber_info->ranges[hiber_info->nranges].base = ACPI_TRAMPOLINE; @@ -144,6 +154,15 @@ get_hibernate_info_md(union hibernate_info *hiber_info) hiber_info->ranges[hiber_info->nranges].base + PAGE_SIZE; hiber_info->image_size += PAGE_SIZE; hiber_info->nranges++; + + /* Record ACPI trampoline data page */ + if (hiber_info->nranges >= VM_PHYSSEG_MAX) + return (1); + hiber_info->ranges[hiber_info->nranges].base = ACPI_TRAMP_DATA; + hiber_info->ranges[hiber_info->nranges].end = + hiber_info->ranges[hiber_info->nranges].base + PAGE_SIZE; + hiber_info->image_size += PAGE_SIZE; + hiber_info->nranges++; #endif #ifdef MULTIPROCESSOR /* Record MP trampoline code page */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 7c737ba5b5b..81d98efa0d2 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.585 2016/05/18 03:45:11 mlarkin Exp $ */ +/* $OpenBSD: machdep.c,v 1.586 2016/05/20 02:30:41 mlarkin Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -3238,6 +3238,10 @@ init386(paddr_t first_avail) /* skip ACPI resume trampoline code page */ if (a < ACPI_TRAMPOLINE + NBPG) a = ACPI_TRAMPOLINE + NBPG; + + /* skip ACPI resume trampoline data page */ + if (a < ACPI_TRAMP_DATA + NBPG) + a = ACPI_TRAMP_DATA + NBPG; #endif /* ACPI */ #ifdef HIBERNATE |