summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/amd64/locore.S
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64/amd64/locore.S')
-rw-r--r--sys/arch/amd64/amd64/locore.S531
1 files changed, 1 insertions, 530 deletions
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index c617d17b467..c8a4b133d9d 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.84 2017/02/06 09:15:51 mpi Exp $ */
+/* $OpenBSD: locore.S,v 1.85 2017/05/31 19:18:18 deraadt Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -140,11 +140,6 @@
#define SET_CURPCB(reg) movq reg,CPUVAR(CURPCB)
-/* XXX temporary kluge; these should not be here */
-/* Get definitions for IOM_BEGIN, IOM_END, and IOM_SIZE */
-#include <dev/isa/isareg.h>
-
-
/*
* Initialization
*/
@@ -230,524 +225,11 @@ gdt64_start:
.quad 0x00cf92000000ffff /* kernel DS */
gdt64_end:
-farjmp64:
- .long longmode-KERNBASE
- .word GSEL(GCODE_SEL, SEL_KPL)
-
- .space 512
-tmpstk:
-
- .globl _C_LABEL(cpu_private)
- .comm _C_LABEL(cpu_private),NBPG,NBPG
-
/*
* Some hackage to deal with 64bit symbols in 32 bit mode.
* This may not be needed if things are cleaned up a little.
*/
- .text
- .globl _C_LABEL(kernel_text)
- .set _C_LABEL(kernel_text),KERNTEXTOFF
-
- .code32
-
- .globl start
-start: movw $0x1234,0x472 # warm boot
-
- /*
- * Load parameters from stack
- * (howto, bootdev, bootapiver, esym, extmem, cnvmem, ac, av)
- */
- movl 4(%esp),%eax
- movl %eax, RELOC(boothowto)
- movl 8(%esp),%eax
- movl %eax, RELOC(bootdev)
-
- /*
- * Syms are placed after last load and bss of the kernel.
- * XXX Boot ignores 2MB roundup of _end, so esyms can be < _end.
- */
- movl 16(%esp), %eax
- testl %eax,%eax
- jz 1f
- addl $KERNBASE_LO,%eax
- movl $RELOC(esym),%ebp
- movl %eax,(%ebp)
- movl $KERNBASE_HI,4(%ebp)
-1:
- movl 20(%esp), %eax
- movl %eax, RELOC(biosextmem)
- movl 24(%esp), %eax
- movl %eax, RELOC(biosbasemem)
-
- movl 12(%esp), %eax
- movl %eax, RELOC(bootapiver)
-
- /*
- * Copy the boot arguments to bootinfo[] in machdep.c.
- *
- * We are passed the size of the data /boot passed to us in
- * 28(%esp). We copy up to bootinfo_size bytes of data into
- * bootinfo and report back how much we copied in bootinfo_size.
- *
- * machdep.c can then take action if bootinfo_size >= bootinfo[]
- * (which would meant that we may have been passed too much data).
- */
- movl 28(%esp), %eax
- movl %eax, %ecx
- cmpl RELOC(bootinfo_size), %ecx /* Too much? */
- jb bi_size_ok
- movl RELOC(bootinfo_size), %ecx /* Only copy this much */
-bi_size_ok:
- movl %eax, RELOC(bootinfo_size) /* Report full amount */
-
- movl $RELOC(bootinfo), %edi /* Destination */
- movl 32(%esp), %esi /* Source */
- rep movsb /* Copy this many bytes */
-
- /* First, reset the PSL. */
- pushl $PSL_MBO
- popfl
-
- xorl %eax,%eax
- cpuid
- movl %eax,RELOC(cpuid_level)
- movl $RELOC(cpu_vendor),%ebp
- movl %ebx,(%ebp)
- movl %edx,4(%ebp)
- movl %ecx,8(%ebp)
- movl $0, 12(%ebp)
-
- movl $1,%eax
- cpuid
- movl %eax,RELOC(cpu_id)
- movl %ebx,RELOC(cpu_ebxfeature)
- movl %ecx,RELOC(cpu_ecxfeature)
- movl %edx,RELOC(cpu_feature)
-
- movl $0x0a,%eax
- cpuid
- movl %eax,RELOC(_C_LABEL(cpu_perf_eax))
- movl %ebx,RELOC(_C_LABEL(cpu_perf_ebx))
- movl %edx,RELOC(_C_LABEL(cpu_perf_edx))
-
- movl $0x80000001, %eax
- cpuid
- andl $CPUID_NXE, %edx /* other bits may clash */
- jz cont
-
- /*
- * We have NX, set pg_nx accordingly.
- * NX bit is bit 63 (bit 31 of the second 32 bit dword) - need
- * to use 32 bit registers here
- */
- pushl %edx
- movl RELOC((pg_nx + 4)), %edx /* Second dword */
- orl $0x80000000, %edx /* Bit 31 (really 63) */
- movl %edx, RELOC((pg_nx + 4))
- popl %edx
-cont:
- orl %edx, RELOC(cpu_feature)
-
- movl $0x80000007,%eax
- cpuid
- movl %edx,RELOC(_C_LABEL(cpu_apmi_edx))
-
- /*
- * Finished with old stack; load new %esp now instead of later so we
- * can trace this code without having to worry about the trace trap
- * clobbering the memory test or the zeroing of the bss+bootstrap page
- * tables.
- *
- * The boot program should check:
- * text+data <= &stack_variable - more_space_for_stack
- * text+data+bss+pad+space_for_page_tables <= end_of_memory
- * Oops, the gdt is in the carcass of the boot program so clearing
- * the rest of memory is still not possible.
- */
- movl $RELOC(tmpstk),%esp
-
-/*
- * Virtual address space of kernel:
- *
- * text | data | bss | [syms] | page dir | proc0 kstack | L1 ptp | L2 ptp | L3
- * 0 1 2 3
- */
-
-#if L2_SLOT_KERNBASE > 0
-#define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1))
-#else
-#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
-#endif
-
-#if L3_SLOT_KERNBASE > 0
-#define TABLE_L3_ENTRIES (2 * NKL3_KIMG_ENTRIES)
-#else
-#define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES
-#endif
-
-
-#define PROC0_PML4_OFF 0
-#define PROC0_STK_OFF (PROC0_PML4_OFF + NBPG)
-#define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * NBPG)
-#define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * NBPG)
-#define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * NBPG)
-#define PROC0_DMP3_OFF (PROC0_PTP1_OFF + TABLE_L2_ENTRIES * NBPG)
-#define PROC0_DMP2_OFF (PROC0_DMP3_OFF + NDML3_ENTRIES * NBPG)
-#define TABLESIZE \
- ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES + \
- NDML3_ENTRIES + NDML2_ENTRIES) * NBPG)
-
-#define fillkpt \
-1: movl %eax,(%ebx) ; /* store phys addr */ \
- movl $0,4(%ebx) ; /* upper 32 bits 0 */ \
- addl $8,%ebx ; /* next pte/pde */ \
- addl $NBPG,%eax ; /* next phys page */ \
- loop 1b ; /* till finished */
-
-
-#define fillkpt_nx \
- pushl %ebp ; /* save */ \
-1: movl %eax,(%ebx) ; /* store phys addr */ \
- movl RELOC((pg_nx + 4)), %ebp ; /* NX bit? */ \
- movl %ebp,4(%ebx) ; /* upper 32 bits */ \
- addl $8,%ebx ; /* next pte/pde */ \
- addl $NBPG,%eax ; /* next phys page */ \
- loop 1b ; /* till finished */ \
- popl %ebp
-
- /* Find end of kernel image. */
- movl $RELOC(end),%edi
-#if (NKSYMS || defined(DDB))
- /* Save the symbols (if loaded). */
- movl RELOC(esym),%eax
- testl %eax,%eax
- jz 1f
- subl $KERNBASE_LO,%eax /* XXX */
- /* Page tables must be after symbols and after kernel image. */
- cmpl %eax,%edi
- jg 1f
- movl %eax,%edi
-1:
-#endif
- /* Clear tables */
- movl %edi,%esi
- addl $PGOFSET,%esi
- andl $~PGOFSET,%esi
-
- movl %esi,%edi
- xorl %eax,%eax
- cld
- movl $TABLESIZE,%ecx
- shrl $2,%ecx
- rep
- stosl
-
- leal (PROC0_PTP1_OFF)(%esi), %ebx
-
- /*
- * Compute etext - KERNBASE. This can't be > 4G, or we can't deal
- * with it anyway, since we can't load it in 32 bit mode. So use
- * the bottom 32 bits.
- */
- movl $RELOC(etext),%edx
- addl $PGOFSET,%edx
- andl $~PGOFSET,%edx
-
- /*
- * Skip the first MB.
- */
- movl $(KERNTEXTOFF_LO - KERNBASE_LO),%eax
- movl %eax,%ecx
- shrl $(PGSHIFT-3),%ecx /* ((n >> PGSHIFT) << 3) for # pdes */
- addl %ecx,%ebx
-
- /* Map kernel text RO, X */
- movl %edx,%ecx
- subl %eax,%ecx
- shrl $PGSHIFT,%ecx
- orl $(PG_V|PG_KR),%eax
- fillkpt
-
- /* Map .rodata RO, NX */
- movl $RELOC(__rodata_start), %eax
- movl $RELOC(erodata), %ecx
- addl $PGOFSET, %ecx
- andl $~PGOFSET, %ecx
- subl %eax, %ecx
- shrl $PGSHIFT, %ecx
- orl $(PG_V|PG_KR), %eax
- fillkpt_nx
-
- /* Map the data and BSS sections RW, NX */
- movl $RELOC(__data_start), %eax
- movl $RELOC(__kernel_bss_end),%ecx
- addl $PGOFSET, %ecx
- andl $~PGOFSET, %ecx
- subl %eax, %ecx
- shrl $PGSHIFT,%ecx
- orl $(PG_V|PG_KW), %eax
- fillkpt_nx
-
- /* Map "hole" at end of BSS RO, NX */
- movl $RELOC(__kernel_bss_end), %eax
- movl $RELOC(end), %ecx
- addl $PGOFSET, %ecx
- andl $~PGOFSET, %ecx
- cmpl %eax, %ecx
- je map_syms
- subl %eax, %ecx
- shrl $PGSHIFT, %ecx
- orl $(PG_V|PG_KR), %eax
- fillkpt_nx
-
-map_syms:
- /* Map symbol space RO, NX */
- movl $RELOC(end), %eax
- movl %esi, %ecx
- addl $PGOFSET, %ecx
- andl $~PGOFSET, %ecx
- cmpl %eax, %ecx
- je map_tables
- subl %eax, %ecx
- shrl $PGSHIFT, %ecx
- orl $(PG_V|PG_KR), %eax
- fillkpt_nx
-
-map_tables:
- /* Map the bootstrap tables RW, NX */
- movl %esi, %edx
- leal (PG_V|PG_KW)(%edx),%eax
- movl $TABLESIZE,%ecx
- shrl $PGSHIFT,%ecx
- fillkpt_nx
-
- /* Map ISA I/O mem (later atdevbase) RW, NX */
- movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax
- movl $(IOM_SIZE>>PGSHIFT),%ecx
- fillkpt_nx
-
- /* Set up level 2 pages (RWX) */
- leal (PROC0_PTP2_OFF)(%esi),%ebx
- leal (PROC0_PTP1_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $(NKL2_KIMG_ENTRIES+1),%ecx
- fillkpt
-
-#if L2_SLOT_KERNBASE > 0
- /* If needed, set up L2 entries for actual kernel mapping (RWX) */
- leal (PROC0_PTP2_OFF+ L2_SLOT_KERNBASE*8)(%esi),%ebx
- leal (PROC0_PTP1_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $(NKL2_KIMG_ENTRIES+1),%ecx
- fillkpt
-#endif
-
- /* Set up level 3 pages (RWX) */
- leal (PROC0_PTP3_OFF)(%esi),%ebx
- leal (PROC0_PTP2_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $NKL3_KIMG_ENTRIES,%ecx
- fillkpt
-
-#if L3_SLOT_KERNBASE > 0
- /* If needed, set up L3 entries for actual kernel mapping (RWX) */
- leal (PROC0_PTP3_OFF+ L3_SLOT_KERNBASE*8)(%esi),%ebx
- leal (PROC0_PTP2_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $NKL3_KIMG_ENTRIES,%ecx
- fillkpt
-#endif
-
- /* Set up top level entries for identity mapping (RWX) */
- leal (PROC0_PML4_OFF)(%esi),%ebx
- leal (PROC0_PTP3_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $NKL4_KIMG_ENTRIES,%ecx
- fillkpt
-
- /* Set up top level entries for actual kernel mapping (RWX) */
- leal (PROC0_PML4_OFF + L4_SLOT_KERNBASE*8)(%esi),%ebx
- leal (PROC0_PTP3_OFF)(%esi),%eax
- orl $(PG_V|PG_KW), %eax
- movl $NKL4_KIMG_ENTRIES,%ecx
- fillkpt
-
- /*
- * Map the first 4 GB with the direct map. We'll map the rest
- * in pmap_bootstrap. But we always need the first 4GB during
- * bootstrap. The direct map is mapped RW, NX. We also change
- * the permissions on the 2MB pages corresponding to the kernel
- * PAs to RO to prevent someone writing to the kernel area
- * via the direct map.
- */
- leal (PROC0_DMP2_OFF)(%esi), %ebx
- xorl %eax, %eax
- movl $(NDML2_ENTRIES * NPDPG), %ecx
-1: orl $(PG_V|PG_KW|PG_PS|PG_G), %eax
- cmpl $__kernel_base_phys, %eax
- jl store_pte
- cmpl $__kernel_end_phys, %eax
- jg store_pte
- andl $(~PG_KW), %eax
-store_pte:
- movl %eax, (%ebx)
- pushl %ebp
- movl RELOC((pg_nx + 4)), %ebp
- movl %ebp, 4(%ebx)
- popl %ebp
- addl $8, %ebx
- addl $NBPD_L2, %eax
- loop 1b
-
- leal (PROC0_DMP3_OFF)(%esi), %ebx
- leal (PROC0_DMP2_OFF)(%esi), %eax
- orl $(PG_V|PG_KW), %eax
- movl $NDML2_ENTRIES, %ecx
- fillkpt_nx
-
- leal (PROC0_PML4_OFF + PDIR_SLOT_DIRECT * 8)(%esi), %ebx
- leal (PROC0_DMP3_OFF)(%esi), %eax
- orl $(PG_V|PG_KW), %eax
- movl $NDML3_ENTRIES, %ecx
- fillkpt_nx
-
- /* Install recursive top level PDE */
- leal (PROC0_PML4_OFF + PDIR_SLOT_PTE*8)(%esi),%ebx
- leal (PROC0_PML4_OFF)(%esi),%eax
- orl $(PG_V|PG_KW),%eax
- movl %eax,(%ebx)
- pushl %ebp
- movl RELOC((pg_nx + 4)), %ebp
- movl %ebp, 4(%ebx)
- popl %ebp
-
- /* Save phys. addr of PTD, for libkvm. */
- movl $RELOC(PTDpaddr),%ebp
- movl %esi,(%ebp)
- movl $0,4(%ebp)
-
- /*
- * Startup checklist:
- * 1. Enable PAE (and SSE while here).
- */
- movl %cr4,%eax
- orl $(CR4_DEFAULT),%eax
- movl %eax,%cr4
-
- /*
- * 2. Set Long Mode Enable in EFER. Also enable the
- * syscall extensions and NX (if available).
- */
- movl $MSR_EFER,%ecx
- rdmsr
- xorl %eax,%eax /* XXX */
- orl $(EFER_LME|EFER_SCE),%eax
- movl RELOC((pg_nx + 4)), %ebx
- cmpl $0, %ebx
- je write_efer
- orl $(EFER_NXE), %eax
-write_efer:
- wrmsr
-
- /*
- * 3. Load %cr3 with pointer to PML4.
- */
- movl %esi,%eax
- movl %eax,%cr3
-
- /*
- * 4. Enable paging and the rest of it.
- */
- movl %cr0,%eax
- orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP),%eax
- movl %eax,%cr0
- jmp compat
-compat:
-
- /*
- * 5.
- * Not quite done yet, we're now in a compatibility segment,
- * in legacy mode. We must jump to a long mode segment.
- * Need to set up a temporary GDT with a long mode segment
- * in it to do that.
- */
-
- movl $RELOC(gdt64),%eax
- lgdt (%eax)
- movl $RELOC(farjmp64),%eax
- ljmp *(%eax)
-
-.code64
-longmode:
- /*
- * 6.
- * Finally, we're in long mode. However, we're still
- * in the identity mapped area (could not jump out
- * of that earlier because it would have been a > 32bit
- * jump). We can do that now, so here we go.
- */
- movabsq $longmode_hi,%rax
- jmp *%rax
-longmode_hi:
- /*
- * We have arrived.
- * There's no need anymore for the identity mapping in low
- * memory, remove it.
- */
- movq $KERNBASE,%r8
-
-#if L2_SLOT_KERNBASE > 0
- movq $(NKL2_KIMG_ENTRIES+1),%rcx
- leaq (PROC0_PTP2_OFF)(%rsi),%rbx
- addq %r8, %rbx
-1: movq $0 ,(%rbx)
- addq $8,%rbx
- loop 1b
-#endif
-
-#if L3_SLOT_KERNBASE > 0
- movq $NKL3_KIMG_ENTRIES,%rcx
- leaq (PROC0_PTP3_OFF)(%rsi),%rbx
- addq %r8, %rbx
-1: movq $0 ,(%rbx)
- addq $8,%rbx
- loop 1b
-#endif
-
- movq $NKL4_KIMG_ENTRIES,%rcx
- leaq (PROC0_PML4_OFF)(%rsi),%rbx # old, phys address of PML4
- addq %r8, %rbx # new, virtual address of PML4
-1: movq $0, (%rbx)
- addq $8,%rbx
- loop 1b
-
- /* Relocate atdevbase. */
- movq $(TABLESIZE+KERNBASE),%rdx
- addq %rsi,%rdx
- movq %rdx,_C_LABEL(atdevbase)(%rip)
-
- /* Record start of symbols */
- movq $__kernel_bss_end, _C_LABEL(ssym)(%rip)
-
- /* Set up bootstrap stack. */
- leaq (PROC0_STK_OFF)(%rsi),%rax
- addq %r8,%rax
- movq %rax,_C_LABEL(proc0paddr)(%rip)
- leaq (USPACE-FRAMESIZE)(%rax),%rsp
- movq %rsi,PCB_CR3(%rax) # pcb->pcb_cr3
- xorq %rbp,%rbp # mark end of frames
-
- xorw %ax,%ax
- movw %ax,%gs
- movw %ax,%fs
-
- /* XXX merge these */
- leaq TABLESIZE(%rsi),%rdi
- call _C_LABEL(init_x86_64)
-
- call _C_LABEL(main)
-
/*****************************************************************************/
/*
@@ -1217,17 +699,6 @@ ENTRY(pagezero)
sfence
ret
- .section .codepatch,"a"
- .align 8, 0xcc
- .globl _C_LABEL(codepatch_begin)
-_C_LABEL(codepatch_begin):
- .previous
-
- .section .codepatchend,"a"
- .globl _C_LABEL(codepatch_end)
-_C_LABEL(codepatch_end):
- .previous
-
#if NXEN > 0
/* Hypercall page needs to be page aligned */
.text