From 76bb9637d53258812a3cd03d0b73a0c0fd40a1c1 Mon Sep 17 00:00:00 2001 From: Mike Larkin Date: Sat, 22 Nov 2014 18:31:47 +0000 Subject: Split the MP trampoline into two pages, one for code and one for data/stack and then protect the code page as RX and the data/stack page as RW (NX). ok deraadt@ --- sys/arch/amd64/amd64/acpi_wakecode.S | 17 ++++---- sys/arch/amd64/amd64/cpu.c | 18 ++++++-- sys/arch/amd64/amd64/hibernate_machdep.c | 13 +++++- sys/arch/amd64/amd64/machdep.c | 11 +++-- sys/arch/amd64/amd64/mptramp.S | 73 ++++++++++++++++++-------------- sys/arch/amd64/include/hibernate_var.h | 26 ++++++------ sys/arch/amd64/include/mpbiosvar.h | 3 +- 7 files changed, 101 insertions(+), 60 deletions(-) (limited to 'sys/arch') diff --git a/sys/arch/amd64/amd64/acpi_wakecode.S b/sys/arch/amd64/amd64/acpi_wakecode.S index e49aa299e5f..f30d01254ca 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.30 2014/10/16 17:37:42 mlarkin Exp $ */ +/* $OpenBSD: acpi_wakecode.S,v 1.31 2014/11/22 18:31:46 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 0x11000, we'd have cs=0x1100,ip=0 + * if our phys addr is 0x13000, we'd have cs=0x1300,ip=0 * * The wakeup code needs to do the following: * 1. Reenable the video display @@ -383,7 +383,7 @@ _ACPI_TRMP_OFFSET(hibernate_resume_vector_3) movl %eax, %cr0 /* Set up real mode segment selectors */ - movw $0x1100, %ax + movw $(ACPI_TRAMPOLINE >> 4), %ax movw %ax, %ds movw %ax, %es movw %ax, %fs @@ -392,7 +392,7 @@ _ACPI_TRMP_OFFSET(hibernate_resume_vector_3) lidtl clean_idt /* Jump to the S3 resume vector */ - ljmp $0x1100, $acpi_s3_vector_real + ljmp $(ACPI_TRAMPOLINE >> 4), $acpi_s3_vector_real NENTRY(hibernate_drop_to_real_mode) .code64 @@ -421,7 +421,7 @@ _ACPI_TRMP_OFFSET(hibernate_resume_vector_3b) movl %eax, %cr0 /* Set up real mode segment selectors */ - movw $0x1100, %ax + movw $(ACPI_TRAMPOLINE >> 4), %ax movw %ax, %ds movw %ax, %es movw %ax, %fs @@ -429,11 +429,11 @@ _ACPI_TRMP_OFFSET(hibernate_resume_vector_3b) movl $0x0FFE, %esp lidtl clean_idt - ljmp $0x1100, $hib_hlt_real + ljmp $(ACPI_TRAMPOLINE >> 4), $hib_hlt_real _ACPI_TRMP_OFFSET(hib_hlt_real) hlt - ljmp $0x1100, $hib_hlt_real + ljmp $(ACPI_TRAMPOLINE >> 4), $hib_hlt_real .code64 /* Switch to hibernate resume pagetable */ @@ -594,7 +594,8 @@ _ACPI_TRMP_LABEL(tmp_gdtable6416) .quad 0x0000000000000000 .quad 0x00af9a000000ffff .quad 0x00cf92000000ffff - .quad 0x00009a0110000fff + .word 0x0fff, (ACPI_TRAMPOLINE % 0x10000) + .byte (ACPI_TRAMPOLINE >> 16), 0x9a, 0, 0 _ACPI_TRMP_LABEL(tmp_gdt6416_end) .align 8 diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c index 3083f696fbb..d40dbdd070f 100644 --- a/sys/arch/amd64/amd64/cpu.c +++ b/sys/arch/amd64/amd64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.68 2014/11/21 07:02:11 mlarkin Exp $ */ +/* $OpenBSD: cpu.c,v 1.69 2014/11/22 18:31:46 mlarkin Exp $ */ /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */ /*- @@ -793,6 +793,8 @@ cpu_copy_trampoline(void) */ extern u_char cpu_spinup_trampoline[]; extern u_char cpu_spinup_trampoline_end[]; + extern u_char mp_tramp_data_start[]; + extern u_char mp_tramp_data_end[]; extern u_int32_t mp_pdirpa; extern paddr_t tramp_pdirpa; @@ -801,11 +803,21 @@ cpu_copy_trampoline(void) cpu_spinup_trampoline, cpu_spinup_trampoline_end-cpu_spinup_trampoline); + pmap_kenter_pa(MP_TRAMP_DATA, MP_TRAMP_DATA, + PROT_READ | PROT_WRITE); + memcpy((caddr_t)MP_TRAMP_DATA, + mp_tramp_data_start, + mp_tramp_data_end - mp_tramp_data_start); + /* - * We need to patch this after we copy the trampoline, - * the symbol points into the copied trampoline. + * We need to patch this after we copy the tramp data, + * the symbol points into the copied tramp data page. */ mp_pdirpa = tramp_pdirpa; + + /* Remap the trampoline RX */ + pmap_kenter_pa(MP_TRAMPOLINE, MP_TRAMPOLINE, + PROT_READ | PROT_EXEC); } diff --git a/sys/arch/amd64/amd64/hibernate_machdep.c b/sys/arch/amd64/amd64/hibernate_machdep.c index 265ecb758d2..2859e281885 100644 --- a/sys/arch/amd64/amd64/hibernate_machdep.c +++ b/sys/arch/amd64/amd64/hibernate_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hibernate_machdep.c,v 1.31 2014/11/16 12:30:56 deraadt Exp $ */ +/* $OpenBSD: hibernate_machdep.c,v 1.32 2014/11/22 18:31:46 mlarkin Exp $ */ /* * Copyright (c) 2012 Mike Larkin @@ -141,6 +141,7 @@ get_hibernate_info_md(union hibernate_info *hiber_info) hiber_info->nranges++; #endif #ifdef MULTIPROCESSOR + /* Record MP trampoline code page */ if (hiber_info->nranges >= VM_PHYSSEG_MAX) return (1); hiber_info->ranges[hiber_info->nranges].base = MP_TRAMPOLINE; @@ -148,6 +149,16 @@ 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 MP trampoline data page */ + if (hiber_info->nranges >= VM_PHYSSEG_MAX) + return (1); + hiber_info->ranges[hiber_info->nranges].base = + MP_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 for (bmp = bios_memmap; bmp->type != BIOS_MAP_END; bmp++) { diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index aee7f1a985d..5edeba88c3e 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.196 2014/11/18 20:51:00 krw Exp $ */ +/* $OpenBSD: machdep.c,v 1.197 2014/11/22 18:31:46 mlarkin Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -1178,7 +1178,7 @@ void map_tramps(void) { struct pmap *kmp = pmap_kernel(); - pmap_kenter_pa(lo32_vaddr, lo32_paddr, PROT_READ | PROT_WRITE | PROT_EXEC); + pmap_kenter_pa(lo32_vaddr, lo32_paddr, PROT_READ | PROT_WRITE); /* * The initial PML4 pointer must be below 4G, so if the @@ -1191,10 +1191,13 @@ map_tramps(void) { } else tramp_pdirpa = kmp->pm_pdirpa; + pmap_kremove(lo32_vaddr, PAGE_SIZE); + #ifdef MULTIPROCESSOR + /* Map trampoline code page RW (to copy code) */ pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE, /* virtual */ (paddr_t)MP_TRAMPOLINE, /* physical */ - PROT_MASK); /* protection */ + PROT_READ | PROT_WRITE); /* protection */ #endif /* MULTIPROCESSOR */ pmap_kenter_pa((vaddr_t)ACPI_TRAMPOLINE, /* virtual */ @@ -1286,6 +1289,8 @@ init_x86_64(paddr_t first_avail) #ifdef MULTIPROCESSOR if (avail_start < MP_TRAMPOLINE + PAGE_SIZE) avail_start = MP_TRAMPOLINE + PAGE_SIZE; + if (avail_start < MP_TRAMP_DATA + PAGE_SIZE) + avail_start = MP_TRAMP_DATA + PAGE_SIZE; #endif #if (NACPI > 0 && !defined(SMALL_KERNEL)) diff --git a/sys/arch/amd64/amd64/mptramp.S b/sys/arch/amd64/amd64/mptramp.S index e6abb613ab9..30d7fcd0979 100644 --- a/sys/arch/amd64/amd64/mptramp.S +++ b/sys/arch/amd64/amd64/mptramp.S @@ -1,4 +1,4 @@ -/* $OpenBSD: mptramp.S,v 1.9 2014/11/21 09:08:20 mlarkin Exp $ */ +/* $OpenBSD: mptramp.S,v 1.10 2014/11/22 18:31:46 mlarkin Exp $ */ /* $NetBSD: mptramp.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */ /*- @@ -90,11 +90,17 @@ #define _TRMP_LABEL(a) a = . - _C_LABEL(cpu_spinup_trampoline) + MP_TRAMPOLINE #define _TRMP_OFFSET(a) a = . - _C_LABEL(cpu_spinup_trampoline) +#define _TRMP_DATA_LABEL(a) a = . - _C_LABEL(mp_tramp_data_start) + \ + MP_TRAMP_DATA +#define _TRMP_DATA_OFFSET(a) a = . - _C_LABEL(mp_tramp_data_start) + .global _C_LABEL(cpu_spinup_trampoline) .global _C_LABEL(cpu_spinup_trampoline_end) .global _C_LABEL(cpu_hatch) .global _C_LABEL(local_apic) .global _C_LABEL(mp_pdirpa) + .global _C_LABEL(mp_tramp_data_start) + .global _C_LABEL(mp_tramp_data_end) .global gdt64 @@ -103,8 +109,9 @@ .code16 _C_LABEL(cpu_spinup_trampoline): cli + movw $(MP_TRAMP_DATA >> 4), %ax + movw %ax, %ds movw %cs, %ax - movw %ax, %ds movw %ax, %es movw %ax, %ss data32 addr32 lgdt (mptramp_gdt32_desc) # load flat descriptor table @@ -122,9 +129,9 @@ _TRMP_LABEL(mp_startup) movw %ax, %es movw %ax, %fs movw %ax, %gs - - movl $ (MP_TRAMPOLINE+NBPG-16),%esp # bootstrap stack end, - # with scratch space.. + + movl $(MP_TRAMP_DATA + NBPG - 16),%esp # bootstrap stack end, + # with scratch space.. /* First, reset the PSL. */ pushl $PSL_MBO @@ -164,6 +171,7 @@ _TRMP_LABEL(mp_startup) movl $mptramp_gdt64_desc,%eax lgdt (%eax) + movl $mptramp_jmp64,%eax movl %cr0,%ecx # get control word @@ -172,36 +180,10 @@ _TRMP_LABEL(mp_startup) ljmp *(%eax) -_TRMP_LABEL(mptramp_jmp64) - .long mptramp_longmode - .word GSEL(GCODE_SEL, SEL_KPL) - -_TRMP_LABEL(mptramp_gdt32) - .quad 0x0000000000000000 - .quad 0x00cf9f000000ffff - .quad 0x00cf93000000ffff -_TRMP_OFFSET(mptramp_gdt32_desc) - .word 0x17 - .long mptramp_gdt32 - -_TRMP_LABEL(mptramp_gdt64) - .quad 0x0000000000000000 - .quad 0x00af9a000000ffff - .quad 0x00cf92000000ffff -_TRMP_LABEL(mptramp_gdt64_desc) - .word 0x17 - .long mptramp_gdt64 - - .global mp_pdirpa -_TRMP_LABEL(mp_pdirpa) -_TRMP_LABEL(mp_tramp_pdirpa) - .long 0 - _TRMP_LABEL(mptramp_longmode) .code64 movabsq $_C_LABEL(cpu_spinup_trampoline_end),%rax jmp *%rax - _C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE @@ -232,3 +214,32 @@ _C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE movq %rax,%cr0 call _C_LABEL(cpu_hatch) /* NOTREACHED */ + + +_C_LABEL(mp_tramp_data_start): +_TRMP_DATA_LABEL(mptramp_jmp64) + .long mptramp_longmode + .word GSEL(GCODE_SEL, SEL_KPL) + + .global mp_pdirpa +_TRMP_DATA_LABEL(mp_pdirpa) +_TRMP_DATA_LABEL(mp_tramp_pdirpa) + .long 0 + + +_TRMP_DATA_LABEL(mptramp_gdt32) + .quad 0x0000000000000000 + .quad 0x00cf9f000000ffff + .quad 0x00cf93000000ffff +_TRMP_DATA_OFFSET(mptramp_gdt32_desc) + .word 0x17 + .long mptramp_gdt32 + +_TRMP_DATA_LABEL(mptramp_gdt64) + .quad 0x0000000000000000 + .quad 0x00af9a000000ffff + .quad 0x00cf92000000ffff +_TRMP_DATA_LABEL(mptramp_gdt64_desc) + .word 0x17 + .long mptramp_gdt64 +_C_LABEL(mp_tramp_data_end): diff --git a/sys/arch/amd64/include/hibernate_var.h b/sys/arch/amd64/include/hibernate_var.h index bc63cff9b59..83943b7fc4b 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.9 2014/10/01 19:41:06 mlarkin Exp $ */ +/* $OpenBSD: hibernate_var.h,v 1.10 2014/11/22 18:31:46 mlarkin Exp $ */ /* * Copyright (c) 2011 Mike Larkin @@ -21,39 +21,39 @@ /* * PML4 table for resume */ -#define HIBERNATE_PML4T (PAGE_SIZE * 18) +#define HIBERNATE_PML4T (PAGE_SIZE * 20) /* * 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 * 19) -#define HIBERNATE_PDPT_HI (PAGE_SIZE * 20) +#define HIBERNATE_PDPT_LOW (PAGE_SIZE * 21) +#define HIBERNATE_PDPT_HI (PAGE_SIZE * 22) /* * 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 * 21) -#define HIBERNATE_PD_LOW2 (PAGE_SIZE * 22) -#define HIBERNATE_PD_HI (PAGE_SIZE * 23) +#define HIBERNATE_PD_LOW (PAGE_SIZE * 23) +#define HIBERNATE_PD_LOW2 (PAGE_SIZE * 24) +#define HIBERNATE_PD_HI (PAGE_SIZE * 25) /* * 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 * 24) -#define HIBERNATE_PT_LOW2 (PAGE_SIZE * 25) -#define HIBERNATE_PT_HI (PAGE_SIZE * 26) +#define HIBERNATE_PT_LOW (PAGE_SIZE * 26) +#define HIBERNATE_PT_LOW2 (PAGE_SIZE * 27) +#define HIBERNATE_PT_HI (PAGE_SIZE * 28) /* 3 pages for stack */ -#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 29) +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 31) -#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 30) +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 32) /* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */ -#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 31) +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 33) /* 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 8cf3ce0fb6d..d71b9d8ac99 100644 --- a/sys/arch/amd64/include/mpbiosvar.h +++ b/sys/arch/amd64/include/mpbiosvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpbiosvar.h,v 1.5 2014/01/05 20:23:57 mlarkin Exp $ */ +/* $OpenBSD: mpbiosvar.h,v 1.6 2014/11/22 18:31:46 mlarkin Exp $ */ /* $NetBSD: mpbiosvar.h,v 1.2 2003/04/02 07:53:57 thorpej Exp $ */ /*- @@ -37,6 +37,7 @@ #define _MACHINE_MPBIOSVAR_H_ #define MP_TRAMPOLINE (16 * PAGE_SIZE) +#define MP_TRAMP_DATA (17 * PAGE_SIZE) #if !defined(_LOCORE) -- cgit v1.2.3