summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2014-11-22 18:31:47 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2014-11-22 18:31:47 +0000
commit76bb9637d53258812a3cd03d0b73a0c0fd40a1c1 (patch)
treee8aa2324c534afaa42051eaa5ee44f450321b6b3 /sys/arch
parenta5dbf793cad994a1b66a5f74a1a2bbc817cbc536 (diff)
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@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/acpi_wakecode.S17
-rw-r--r--sys/arch/amd64/amd64/cpu.c18
-rw-r--r--sys/arch/amd64/amd64/hibernate_machdep.c13
-rw-r--r--sys/arch/amd64/amd64/machdep.c11
-rw-r--r--sys/arch/amd64/amd64/mptramp.S73
-rw-r--r--sys/arch/amd64/include/hibernate_var.h26
-rw-r--r--sys/arch/amd64/include/mpbiosvar.h3
7 files changed, 101 insertions, 60 deletions
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 <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 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 <mlarkin@openbsd.org>
@@ -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 <mlarkin@openbsd.org>
@@ -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)