1*7196220cSmlarkin/* $OpenBSD: locore.S,v 1.73 2015/11/09 01:08:56 mlarkin Exp $ */ 2b5b9857bSart/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ 3f5df1827Smickey 4f5df1827Smickey/* 5f5df1827Smickey * Copyright-o-rama! 6f5df1827Smickey */ 7f5df1827Smickey 8f5df1827Smickey/* 9f5df1827Smickey * Copyright (c) 2001 Wasabi Systems, Inc. 10f5df1827Smickey * All rights reserved. 11f5df1827Smickey * 12f5df1827Smickey * Written by Frank van der Linden for Wasabi Systems, Inc. 13f5df1827Smickey * 14f5df1827Smickey * Redistribution and use in source and binary forms, with or without 15f5df1827Smickey * modification, are permitted provided that the following conditions 16f5df1827Smickey * are met: 17f5df1827Smickey * 1. Redistributions of source code must retain the above copyright 18f5df1827Smickey * notice, this list of conditions and the following disclaimer. 19f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright 20f5df1827Smickey * notice, this list of conditions and the following disclaimer in the 21f5df1827Smickey * documentation and/or other materials provided with the distribution. 22f5df1827Smickey * 3. All advertising materials mentioning features or use of this software 23f5df1827Smickey * must display the following acknowledgement: 24f5df1827Smickey * This product includes software developed for the NetBSD Project by 25f5df1827Smickey * Wasabi Systems, Inc. 26f5df1827Smickey * 4. The name of Wasabi Systems, Inc. may not be used to endorse 27f5df1827Smickey * or promote products derived from this software without specific prior 28f5df1827Smickey * written permission. 29f5df1827Smickey * 30f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 31f5df1827Smickey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 32f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33f5df1827Smickey * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 34f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE. 41f5df1827Smickey */ 42f5df1827Smickey 43f5df1827Smickey 44f5df1827Smickey/*- 45f5df1827Smickey * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 46f5df1827Smickey * All rights reserved. 47f5df1827Smickey * 48f5df1827Smickey * This code is derived from software contributed to The NetBSD Foundation 49f5df1827Smickey * by Charles M. Hannum. 50f5df1827Smickey * 51f5df1827Smickey * Redistribution and use in source and binary forms, with or without 52f5df1827Smickey * modification, are permitted provided that the following conditions 53f5df1827Smickey * are met: 54f5df1827Smickey * 1. Redistributions of source code must retain the above copyright 55f5df1827Smickey * notice, this list of conditions and the following disclaimer. 56f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright 57f5df1827Smickey * notice, this list of conditions and the following disclaimer in the 58f5df1827Smickey * documentation and/or other materials provided with the distribution. 59f5df1827Smickey * 60f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 61f5df1827Smickey * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 62f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 63f5df1827Smickey * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 64f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 65f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 66f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 67f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 68f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 69f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 70f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE. 71f5df1827Smickey */ 72f5df1827Smickey 73f5df1827Smickey/*- 74f5df1827Smickey * Copyright (c) 1990 The Regents of the University of California. 75f5df1827Smickey * All rights reserved. 76f5df1827Smickey * 77f5df1827Smickey * This code is derived from software contributed to Berkeley by 78f5df1827Smickey * William Jolitz. 79f5df1827Smickey * 80f5df1827Smickey * Redistribution and use in source and binary forms, with or without 81f5df1827Smickey * modification, are permitted provided that the following conditions 82f5df1827Smickey * are met: 83f5df1827Smickey * 1. Redistributions of source code must retain the above copyright 84f5df1827Smickey * notice, this list of conditions and the following disclaimer. 85f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright 86f5df1827Smickey * notice, this list of conditions and the following disclaimer in the 87f5df1827Smickey * documentation and/or other materials provided with the distribution. 88b5b9857bSart * 3. Neither the name of the University nor the names of its contributors 89f5df1827Smickey * may be used to endorse or promote products derived from this software 90f5df1827Smickey * without specific prior written permission. 91f5df1827Smickey * 92f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 93f5df1827Smickey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94f5df1827Smickey * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 95f5df1827Smickey * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 96f5df1827Smickey * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 97f5df1827Smickey * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 98f5df1827Smickey * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99f5df1827Smickey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 100f5df1827Smickey * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 101f5df1827Smickey * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 102f5df1827Smickey * SUCH DAMAGE. 103f5df1827Smickey * 104f5df1827Smickey * @(#)locore.s 7.3 (Berkeley) 5/13/91 105f5df1827Smickey */ 106f5df1827Smickey 107f5df1827Smickey#include "assym.h" 108f5df1827Smickey#include "lapic.h" 109f5df1827Smickey#include "ioapic.h" 110f5df1827Smickey#include "ksyms.h" 1113c8478a6Sgwk#include "acpi.h" 112f5df1827Smickey 113f5df1827Smickey#include <sys/errno.h> 114f5df1827Smickey#include <sys/syscall.h> 115f5df1827Smickey 116f5df1827Smickey#include <machine/param.h> 117f5df1827Smickey#include <machine/segments.h> 118f5df1827Smickey#include <machine/specialreg.h> 119f5df1827Smickey#include <machine/trap.h> 120f5df1827Smickey#include <machine/frameasm.h> 121f5df1827Smickey 122f5df1827Smickey#if NLAPIC > 0 123f5df1827Smickey#include <machine/i82489reg.h> 124f5df1827Smickey#endif 125f5df1827Smickey 126f5df1827Smickey/* 127f5df1827Smickey * override user-land alignment before including asm.h 128f5df1827Smickey */ 129f5df1827Smickey#define ALIGN_DATA .align 8 130f5df1827Smickey#define ALIGN_TEXT .align 16,0x90 131f5df1827Smickey#define _ALIGN_TEXT ALIGN_TEXT 132f5df1827Smickey 133f5df1827Smickey#include <machine/asm.h> 134f5df1827Smickey 135fbe53cacSkrw#define SET_CURPROC(proc,cpu) \ 136fbe53cacSkrw movq CPUVAR(SELF),cpu ; \ 137fbe53cacSkrw movq proc,CPUVAR(CURPROC) ; \ 138fbe53cacSkrw movq cpu,P_CPU(proc) 139fbe53cacSkrw 140fbe53cacSkrw#define GET_CURPCB(reg) movq CPUVAR(CURPCB),reg 141fbe53cacSkrw#define SET_CURPCB(reg) movq reg,CPUVAR(CURPCB) 142fbe53cacSkrw 143fbe53cacSkrw 144f5df1827Smickey/* XXX temporary kluge; these should not be here */ 145f5df1827Smickey/* Get definitions for IOM_BEGIN, IOM_END, and IOM_SIZE */ 146f5df1827Smickey#include <dev/isa/isareg.h> 147f5df1827Smickey 148fbe53cacSkrw 149f5df1827Smickey/* 150f5df1827Smickey * Initialization 151f5df1827Smickey */ 152f5df1827Smickey .data 153f5df1827Smickey 154f5df1827Smickey#if NLAPIC > 0 155f5df1827Smickey .align NBPG 156f5df1827Smickey .globl _C_LABEL(local_apic), _C_LABEL(lapic_id), _C_LABEL(lapic_tpr) 157f5df1827Smickey_C_LABEL(local_apic): 158f5df1827Smickey .space LAPIC_ID 159f5df1827Smickey_C_LABEL(lapic_id): 160f5df1827Smickey .long 0x00000000 161f5df1827Smickey .space LAPIC_TPRI-(LAPIC_ID+4) 162f5df1827Smickey_C_LABEL(lapic_tpr): 163f5df1827Smickey .space LAPIC_PPRI-LAPIC_TPRI 164f5df1827Smickey_C_LABEL(lapic_ppr): 165f5df1827Smickey .space LAPIC_ISR-LAPIC_PPRI 166f5df1827Smickey_C_LABEL(lapic_isr): 167f5df1827Smickey .space NBPG-LAPIC_ISR 168f5df1827Smickey#endif 169f5df1827Smickey 170576d2332Smlarkin .globl _C_LABEL(cpu_id),_C_LABEL(cpu_vendor) 171f5df1827Smickey .globl _C_LABEL(cpuid_level),_C_LABEL(cpu_feature) 172*7196220cSmlarkin .globl _C_LABEL(cpu_ebxfeature) 1736995b18fShaesbaert .globl _C_LABEL(cpu_ecxfeature),_C_LABEL(ecpu_ecxfeature) 17407166672Smglocker .globl _C_LABEL(cpu_perf_eax) 17507166672Smglocker .globl _C_LABEL(cpu_perf_ebx) 17607166672Smglocker .globl _C_LABEL(cpu_perf_edx) 17707166672Smglocker .globl _C_LABEL(cpu_apmi_edx) 178c7636a68Smlarkin .globl _C_LABEL(ssym),_C_LABEL(esym),_C_LABEL(boothowto),_C_LABEL(bootdev) 1796483bf47Sderaadt .globl _C_LABEL(bootinfo), _C_LABEL(bootinfo_size), _C_LABEL(atdevbase) 180f5df1827Smickey .globl _C_LABEL(proc0paddr),_C_LABEL(PTDpaddr) 181f5df1827Smickey .globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem) 1826483bf47Sderaadt .globl _C_LABEL(bootapiver) 18336414dbbSmlarkin .globl _C_LABEL(pg_nx) 184f5df1827Smickey_C_LABEL(cpu_id): .long 0 # saved from `cpuid' instruction 185f5df1827Smickey_C_LABEL(cpu_feature): .long 0 # feature flags from 'cpuid' 186f5df1827Smickey # instruction 187*7196220cSmlarkin_C_LABEL(cpu_ebxfeature):.long 0 # ext. ebx feature flags from 'cpuid' 188*7196220cSmlarkin_C_LABEL(cpu_ecxfeature):.long 0 # ext. ecx feature flags from 'cpuid' 1896995b18fShaesbaert_C_LABEL(ecpu_ecxfeature):.long 0 # extended ecx feature flags 19007166672Smglocker_C_LABEL(cpu_perf_eax): .long 0 # arch. perf. mon. flags from 'cpuid' 19107166672Smglocker_C_LABEL(cpu_perf_ebx): .long 0 # arch. perf. mon. flags from 'cpuid' 19207166672Smglocker_C_LABEL(cpu_perf_edx): .long 0 # arch. perf. mon. flags from 'cpuid' 19307166672Smglocker_C_LABEL(cpu_apmi_edx): .long 0 # adv. power mgmt. info. from 'cpuid' 194f5df1827Smickey_C_LABEL(cpuid_level): .long -1 # max. level accepted by 'cpuid' 195f5df1827Smickey # instruction 196f5df1827Smickey_C_LABEL(cpu_vendor): .space 16 # vendor string returned by `cpuid' 197f5df1827Smickey # instruction 198c7636a68Smlarkin_C_LABEL(ssym): .quad 0 # ptr to start of syms 199f5df1827Smickey_C_LABEL(esym): .quad 0 # ptr to end of syms 200f5df1827Smickey_C_LABEL(atdevbase): .quad 0 # location of start of iomem in virtual 201e9dacf7aStom_C_LABEL(bootapiver): .long 0 # /boot API version 202f431e893Smillert_C_LABEL(bootdev): .long 0 # device we booted from 203f5df1827Smickey_C_LABEL(proc0paddr): .quad 0 204f5df1827Smickey_C_LABEL(PTDpaddr): .quad 0 # paddr of PTD, for libkvm 205f5df1827Smickey#ifndef REALBASEMEM 206f5df1827Smickey_C_LABEL(biosbasemem): .long 0 # base memory reported by BIOS 207f5df1827Smickey#else 208f5df1827Smickey_C_LABEL(biosbasemem): .long REALBASEMEM 209f5df1827Smickey#endif 210f5df1827Smickey#ifndef REALEXTMEM 211f5df1827Smickey_C_LABEL(biosextmem): .long 0 # extended memory reported by BIOS 212f5df1827Smickey#else 213f5df1827Smickey_C_LABEL(biosextmem): .long REALEXTMEM 214f5df1827Smickey#endif 21536414dbbSmlarkin_C_LABEL(pg_nx): .quad 0 # NX PTE bit (if CPU supports) 216f5df1827Smickey 217f5df1827Smickey#define _RELOC(x) ((x) - KERNBASE) 218f5df1827Smickey#define RELOC(x) _RELOC(_C_LABEL(x)) 219f5df1827Smickey 220f5df1827Smickey .globl gdt64 221f5df1827Smickey 222f5df1827Smickeygdt64: 223029cc5b9Smikeb .word gdt64_end-gdt64_start-1 224f5df1827Smickey .quad _RELOC(gdt64_start) 225f5df1827Smickey.align 64 226f5df1827Smickey 227f5df1827Smickeygdt64_start: 228f5df1827Smickey .quad 0x0000000000000000 /* always empty */ 229f5df1827Smickey .quad 0x00af9a000000ffff /* kernel CS */ 230f5df1827Smickey .quad 0x00cf92000000ffff /* kernel DS */ 231f5df1827Smickeygdt64_end: 232f5df1827Smickey 233f5df1827Smickeyfarjmp64: 234f5df1827Smickey .long longmode-KERNBASE 235f5df1827Smickey .word GSEL(GCODE_SEL, SEL_KPL) 236f5df1827Smickey 237f5df1827Smickey .space 512 238f5df1827Smickeytmpstk: 239f5df1827Smickey 240f5df1827Smickey .globl _C_LABEL(cpu_private) 241f5df1827Smickey .comm _C_LABEL(cpu_private),NBPG,NBPG 242f5df1827Smickey 243f5df1827Smickey/* 244f5df1827Smickey * Some hackage to deal with 64bit symbols in 32 bit mode. 245e9dacf7aStom * This may not be needed if things are cleaned up a little. 246f5df1827Smickey */ 247f5df1827Smickey 248f5df1827Smickey .text 249f5df1827Smickey .globl _C_LABEL(kernel_text) 250f5df1827Smickey .set _C_LABEL(kernel_text),KERNTEXTOFF 251f5df1827Smickey 252f5df1827Smickey .code32 253f5df1827Smickey 254f5df1827Smickey .globl start 255f5df1827Smickeystart: movw $0x1234,0x472 # warm boot 256f5df1827Smickey 257f5df1827Smickey /* 258f5df1827Smickey * Load parameters from stack 259930756e7Stom * (howto, bootdev, bootapiver, esym, extmem, cnvmem, ac, av) 260f5df1827Smickey */ 261f5df1827Smickey movl 4(%esp),%eax 262930756e7Stom movl %eax, RELOC(boothowto) 263a47f7207Smickey movl 8(%esp),%eax 264930756e7Stom movl %eax, RELOC(bootdev) 265f5df1827Smickey 26619edda9eSbluhm /* 26719edda9eSbluhm * Syms are placed after last load and bss of the kernel. 26819edda9eSbluhm * XXX Boot ignores 2MB roundup of _end, so esyms can be < _end. 26919edda9eSbluhm */ 270f5df1827Smickey movl 16(%esp), %eax 271f5df1827Smickey testl %eax,%eax 272f5df1827Smickey jz 1f 273f5df1827Smickey addl $KERNBASE_LO,%eax 274a47f7207Smickey movl $RELOC(esym),%ebp 275f5df1827Smickey movl %eax,(%ebp) 276f5df1827Smickey movl $KERNBASE_HI,4(%ebp) 277a47f7207Smickey1: 278f5df1827Smickey movl 20(%esp), %eax 279a47f7207Smickey movl %eax, RELOC(biosextmem) 280f5df1827Smickey movl 24(%esp), %eax 281a47f7207Smickey movl %eax, RELOC(biosbasemem) 282f5df1827Smickey 283e9dacf7aStom movl 12(%esp), %eax 284e9dacf7aStom movl %eax, RELOC(bootapiver) 2856483bf47Sderaadt 2866483bf47Sderaadt /* 2876483bf47Sderaadt * Copy the boot arguments to bootinfo[] in machdep.c. 2886483bf47Sderaadt * 289a2932691Smlarkin * We are passed the size of the data /boot passed to us in 290a2932691Smlarkin * 28(%esp). We copy up to bootinfo_size bytes of data into 291a2932691Smlarkin * bootinfo and report back how much we copied in bootinfo_size. 2926483bf47Sderaadt * 2936483bf47Sderaadt * machdep.c can then take action if bootinfo_size >= bootinfo[] 2946483bf47Sderaadt * (which would meant that we may have been passed too much data). 2956483bf47Sderaadt */ 296e9dacf7aStom movl 28(%esp), %eax 2976483bf47Sderaadt movl %eax, %ecx 2986483bf47Sderaadt cmpl RELOC(bootinfo_size), %ecx /* Too much? */ 299a2932691Smlarkin jb bi_size_ok 3006483bf47Sderaadt movl RELOC(bootinfo_size), %ecx /* Only copy this much */ 3016483bf47Sderaadtbi_size_ok: 3026483bf47Sderaadt movl %eax, RELOC(bootinfo_size) /* Report full amount */ 3036483bf47Sderaadt 3046483bf47Sderaadt movl $RELOC(bootinfo), %edi /* Destination */ 3056483bf47Sderaadt movl 32(%esp), %esi /* Source */ 3066483bf47Sderaadt rep movsb /* Copy this many bytes */ 307e9dacf7aStom 308f5df1827Smickey /* First, reset the PSL. */ 309f5df1827Smickey pushl $PSL_MBO 310f5df1827Smickey popfl 311f5df1827Smickey 312f5df1827Smickey xorl %eax,%eax 313f5df1827Smickey cpuid 314f5df1827Smickey movl %eax,RELOC(cpuid_level) 315f5df1827Smickey movl $RELOC(cpu_vendor),%ebp 316f5df1827Smickey movl %ebx,(%ebp) 317f5df1827Smickey movl %edx,4(%ebp) 318f5df1827Smickey movl %ecx,8(%ebp) 319f5df1827Smickey movl $0, 12(%ebp) 320f5df1827Smickey 321f5df1827Smickey movl $1,%eax 322f5df1827Smickey cpuid 323f5df1827Smickey movl %eax,RELOC(cpu_id) 324*7196220cSmlarkin movl %ebx,RELOC(cpu_ebxfeature) 325c098ddcfSjsg movl %ecx,RELOC(cpu_ecxfeature) 326f5df1827Smickey movl %edx,RELOC(cpu_feature) 327f5df1827Smickey 32807166672Smglocker movl $0x0a,%eax 32907166672Smglocker cpuid 33007166672Smglocker movl %eax,RELOC(_C_LABEL(cpu_perf_eax)) 33107166672Smglocker movl %ebx,RELOC(_C_LABEL(cpu_perf_ebx)) 33207166672Smglocker movl %edx,RELOC(_C_LABEL(cpu_perf_edx)) 33307166672Smglocker 3341fef3300Smickey movl $0x80000001, %eax 3351fef3300Smickey cpuid 3361fef3300Smickey andl $CPUID_NXE, %edx /* other bits may clash */ 33736414dbbSmlarkin jz cont 33836414dbbSmlarkin 33936414dbbSmlarkin /* 34036414dbbSmlarkin * We have NX, set pg_nx accordingly. 34136414dbbSmlarkin * NX bit is bit 63 (bit 31 of the second 32 bit dword) - need 34236414dbbSmlarkin * to use 32 bit registers here 34336414dbbSmlarkin */ 34436414dbbSmlarkin pushl %edx 34536414dbbSmlarkin movl RELOC((pg_nx + 4)), %edx /* Second dword */ 34636414dbbSmlarkin orl $0x80000000, %edx /* Bit 31 (really 63) */ 34736414dbbSmlarkin movl %edx, RELOC((pg_nx + 4)) 34836414dbbSmlarkin popl %edx 34936414dbbSmlarkincont: 3501fef3300Smickey orl %edx, RELOC(cpu_feature) 3511fef3300Smickey 35207166672Smglocker movl $0x80000007,%eax 35307166672Smglocker cpuid 35407166672Smglocker movl %edx,RELOC(_C_LABEL(cpu_apmi_edx)) 35507166672Smglocker 356f5df1827Smickey /* 357f5df1827Smickey * Finished with old stack; load new %esp now instead of later so we 358f5df1827Smickey * can trace this code without having to worry about the trace trap 359f5df1827Smickey * clobbering the memory test or the zeroing of the bss+bootstrap page 360f5df1827Smickey * tables. 361f5df1827Smickey * 362f5df1827Smickey * The boot program should check: 363f5df1827Smickey * text+data <= &stack_variable - more_space_for_stack 364f5df1827Smickey * text+data+bss+pad+space_for_page_tables <= end_of_memory 365f5df1827Smickey * Oops, the gdt is in the carcass of the boot program so clearing 366f5df1827Smickey * the rest of memory is still not possible. 367f5df1827Smickey */ 368f5df1827Smickey movl $RELOC(tmpstk),%esp 369f5df1827Smickey 370f5df1827Smickey/* 371f5df1827Smickey * Virtual address space of kernel: 372f5df1827Smickey * 373f5df1827Smickey * text | data | bss | [syms] | page dir | proc0 kstack | L1 ptp | L2 ptp | L3 374f5df1827Smickey * 0 1 2 3 375f5df1827Smickey */ 376f5df1827Smickey 377f5df1827Smickey#if L2_SLOT_KERNBASE > 0 378f5df1827Smickey#define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1)) 379f5df1827Smickey#else 380f5df1827Smickey#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1) 381f5df1827Smickey#endif 382f5df1827Smickey 383f5df1827Smickey#if L3_SLOT_KERNBASE > 0 384f5df1827Smickey#define TABLE_L3_ENTRIES (2 * NKL3_KIMG_ENTRIES) 385f5df1827Smickey#else 386f5df1827Smickey#define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES 387f5df1827Smickey#endif 388f5df1827Smickey 389f5df1827Smickey 390f5df1827Smickey#define PROC0_PML4_OFF 0 391f5df1827Smickey#define PROC0_STK_OFF (PROC0_PML4_OFF + NBPG) 392f5df1827Smickey#define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * NBPG) 393f5df1827Smickey#define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * NBPG) 394f5df1827Smickey#define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * NBPG) 395f00c9240Sart#define PROC0_DMP3_OFF (PROC0_PTP1_OFF + TABLE_L2_ENTRIES * NBPG) 396f00c9240Sart#define PROC0_DMP2_OFF (PROC0_DMP3_OFF + NDML3_ENTRIES * NBPG) 397f5df1827Smickey#define TABLESIZE \ 398f00c9240Sart ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES + \ 399f00c9240Sart NDML3_ENTRIES + NDML2_ENTRIES) * NBPG) 400f5df1827Smickey 401f5df1827Smickey#define fillkpt \ 402f5df1827Smickey1: movl %eax,(%ebx) ; /* store phys addr */ \ 403f5df1827Smickey movl $0,4(%ebx) ; /* upper 32 bits 0 */ \ 404f5df1827Smickey addl $8,%ebx ; /* next pte/pde */ \ 405f5df1827Smickey addl $NBPG,%eax ; /* next phys page */ \ 40636414dbbSmlarkin loop 1b ; /* till finished */ 407f5df1827Smickey 408f5df1827Smickey 40936414dbbSmlarkin#define fillkpt_nx \ 41036414dbbSmlarkin pushl %ebp ; /* save */ \ 41136414dbbSmlarkin1: movl %eax,(%ebx) ; /* store phys addr */ \ 41236414dbbSmlarkin movl RELOC((pg_nx + 4)), %ebp ; /* NX bit? */ \ 41336414dbbSmlarkin movl %ebp,4(%ebx) ; /* upper 32 bits */ \ 41436414dbbSmlarkin addl $8,%ebx ; /* next pte/pde */ \ 41536414dbbSmlarkin addl $NBPG,%eax ; /* next phys page */ \ 41636414dbbSmlarkin loop 1b ; /* till finished */ \ 41736414dbbSmlarkin popl %ebp 41836414dbbSmlarkin 419f5df1827Smickey /* Find end of kernel image. */ 420f5df1827Smickey movl $RELOC(end),%edi 4218f48279bStedu#if (NKSYMS || defined(DDB)) && !defined(SYMTAB_SPACE) 422f5df1827Smickey /* Save the symbols (if loaded). */ 423f5df1827Smickey movl RELOC(esym),%eax 424f5df1827Smickey testl %eax,%eax 425f5df1827Smickey jz 1f 426f5df1827Smickey subl $KERNBASE_LO,%eax /* XXX */ 42719edda9eSbluhm /* Page tables must be after symbols and after kernel image. */ 42819edda9eSbluhm cmpl %eax,%edi 42919edda9eSbluhm jg 1f 430f5df1827Smickey movl %eax,%edi 431f5df1827Smickey1: 432f5df1827Smickey#endif 433f5df1827Smickey /* Clear tables */ 434f5df1827Smickey movl %edi,%esi 435f5df1827Smickey addl $PGOFSET,%esi 436f5df1827Smickey andl $~PGOFSET,%esi 437f5df1827Smickey 438f5df1827Smickey movl %esi,%edi 439f5df1827Smickey xorl %eax,%eax 440f5df1827Smickey cld 441f5df1827Smickey movl $TABLESIZE,%ecx 442f5df1827Smickey shrl $2,%ecx 443f5df1827Smickey rep 444f5df1827Smickey stosl 445f5df1827Smickey 446f5df1827Smickey leal (PROC0_PTP1_OFF)(%esi), %ebx 447f5df1827Smickey 448f5df1827Smickey /* 449f5df1827Smickey * Compute etext - KERNBASE. This can't be > 4G, or we can't deal 450f5df1827Smickey * with it anyway, since we can't load it in 32 bit mode. So use 451f5df1827Smickey * the bottom 32 bits. 452f5df1827Smickey */ 453f5df1827Smickey movl $RELOC(etext),%edx 454f5df1827Smickey addl $PGOFSET,%edx 455f5df1827Smickey andl $~PGOFSET,%edx 456f5df1827Smickey 457f5df1827Smickey /* 458f5df1827Smickey * Skip the first MB. 459f5df1827Smickey */ 460f5df1827Smickey movl $(KERNTEXTOFF_LO - KERNBASE_LO),%eax 461f5df1827Smickey movl %eax,%ecx 462f5df1827Smickey shrl $(PGSHIFT-3),%ecx /* ((n >> PGSHIFT) << 3) for # pdes */ 463f5df1827Smickey addl %ecx,%ebx 464f5df1827Smickey 46536414dbbSmlarkin /* Map kernel text RO, X */ 466f5df1827Smickey movl %edx,%ecx 467f5df1827Smickey subl %eax,%ecx 468f5df1827Smickey shrl $PGSHIFT,%ecx 469f5df1827Smickey orl $(PG_V|PG_KR),%eax 470f5df1827Smickey fillkpt 471f5df1827Smickey 47236414dbbSmlarkin /* Map .rodata RO, NX */ 4737e27549bSmlarkin movl $RELOC(__rodata_start), %eax 4747e27549bSmlarkin movl $RELOC(erodata), %ecx 4757e27549bSmlarkin addl $PGOFSET, %ecx 4767e27549bSmlarkin andl $~PGOFSET, %ecx 4777e27549bSmlarkin subl %eax, %ecx 4787e27549bSmlarkin shrl $PGSHIFT, %ecx 4797e27549bSmlarkin orl $(PG_V|PG_KR), %eax 48036414dbbSmlarkin fillkpt_nx 4817e27549bSmlarkin 482c7636a68Smlarkin /* Map the data and BSS sections RW, NX */ 483c7636a68Smlarkin movl $RELOC(__data_start), %eax 484c7636a68Smlarkin movl $RELOC(__kernel_bss_end),%ecx 485c7636a68Smlarkin addl $PGOFSET, %ecx 486c7636a68Smlarkin andl $~PGOFSET, %ecx 487c7636a68Smlarkin subl %eax, %ecx 488c7636a68Smlarkin shrl $PGSHIFT,%ecx 489c7636a68Smlarkin orl $(PG_V|PG_KW), %eax 490c7636a68Smlarkin fillkpt_nx 4917e27549bSmlarkin 492c7636a68Smlarkin /* Map "hole" at end of BSS RO, NX */ 493c7636a68Smlarkin movl $RELOC(__kernel_bss_end), %eax 494c7636a68Smlarkin movl $RELOC(end), %ecx 495c7636a68Smlarkin addl $PGOFSET, %ecx 496c7636a68Smlarkin andl $~PGOFSET, %ecx 497c7636a68Smlarkin cmpl %eax, %ecx 498c7636a68Smlarkin je map_syms 499c7636a68Smlarkin subl %eax, %ecx 500c7636a68Smlarkin shrl $PGSHIFT, %ecx 501c7636a68Smlarkin orl $(PG_V|PG_KR), %eax 502c7636a68Smlarkin fillkpt_nx 503c7636a68Smlarkin 504c7636a68Smlarkinmap_syms: 505c7636a68Smlarkin /* Map symbol space RO, NX */ 506c7636a68Smlarkin movl $RELOC(end), %eax 507c7636a68Smlarkin movl %esi, %ecx 508c7636a68Smlarkin addl $PGOFSET, %ecx 509c7636a68Smlarkin andl $~PGOFSET, %ecx 510c7636a68Smlarkin cmpl %eax, %ecx 511c7636a68Smlarkin je map_tables 512c7636a68Smlarkin subl %eax, %ecx 513c7636a68Smlarkin shrl $PGSHIFT, %ecx 514c7636a68Smlarkin orl $(PG_V|PG_KR), %eax 515c7636a68Smlarkin fillkpt_nx 516c7636a68Smlarkin 517c7636a68Smlarkinmap_tables: 518c7636a68Smlarkin /* Map the bootstrap tables RW, NX */ 519c7636a68Smlarkin movl %esi, %edx 520f5df1827Smickey leal (PG_V|PG_KW)(%edx),%eax 521f5df1827Smickey movl $TABLESIZE,%ecx 522f5df1827Smickey shrl $PGSHIFT,%ecx 52336414dbbSmlarkin fillkpt_nx 524f5df1827Smickey 52536414dbbSmlarkin /* Map ISA I/O mem (later atdevbase) RW, NX */ 526f5df1827Smickey movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax 527f5df1827Smickey movl $(IOM_SIZE>>PGSHIFT),%ecx 52836414dbbSmlarkin fillkpt_nx 529f5df1827Smickey 53036414dbbSmlarkin /* Set up level 2 pages (RWX) */ 531f5df1827Smickey leal (PROC0_PTP2_OFF)(%esi),%ebx 532f5df1827Smickey leal (PROC0_PTP1_OFF)(%esi),%eax 533f5df1827Smickey orl $(PG_V|PG_KW), %eax 534f5df1827Smickey movl $(NKL2_KIMG_ENTRIES+1),%ecx 535f5df1827Smickey fillkpt 536f5df1827Smickey 537f5df1827Smickey#if L2_SLOT_KERNBASE > 0 53836414dbbSmlarkin /* If needed, set up L2 entries for actual kernel mapping (RWX) */ 539f5df1827Smickey leal (PROC0_PTP2_OFF+ L2_SLOT_KERNBASE*8)(%esi),%ebx 540f5df1827Smickey leal (PROC0_PTP1_OFF)(%esi),%eax 541f5df1827Smickey orl $(PG_V|PG_KW), %eax 542f5df1827Smickey movl $(NKL2_KIMG_ENTRIES+1),%ecx 543f5df1827Smickey fillkpt 544f5df1827Smickey#endif 545f5df1827Smickey 54636414dbbSmlarkin /* Set up level 3 pages (RWX) */ 547f5df1827Smickey leal (PROC0_PTP3_OFF)(%esi),%ebx 548f5df1827Smickey leal (PROC0_PTP2_OFF)(%esi),%eax 549f5df1827Smickey orl $(PG_V|PG_KW), %eax 550f5df1827Smickey movl $NKL3_KIMG_ENTRIES,%ecx 551f5df1827Smickey fillkpt 552f5df1827Smickey 553f5df1827Smickey#if L3_SLOT_KERNBASE > 0 55436414dbbSmlarkin /* If needed, set up L3 entries for actual kernel mapping (RWX) */ 555f5df1827Smickey leal (PROC0_PTP3_OFF+ L3_SLOT_KERNBASE*8)(%esi),%ebx 556f5df1827Smickey leal (PROC0_PTP2_OFF)(%esi),%eax 557f5df1827Smickey orl $(PG_V|PG_KW), %eax 558f5df1827Smickey movl $NKL3_KIMG_ENTRIES,%ecx 559f5df1827Smickey fillkpt 560f5df1827Smickey#endif 561f5df1827Smickey 56236414dbbSmlarkin /* Set up top level entries for identity mapping (RWX) */ 563f5df1827Smickey leal (PROC0_PML4_OFF)(%esi),%ebx 564f5df1827Smickey leal (PROC0_PTP3_OFF)(%esi),%eax 565f5df1827Smickey orl $(PG_V|PG_KW), %eax 566f5df1827Smickey movl $NKL4_KIMG_ENTRIES,%ecx 567f5df1827Smickey fillkpt 568f5df1827Smickey 56936414dbbSmlarkin /* Set up top level entries for actual kernel mapping (RWX) */ 570f5df1827Smickey leal (PROC0_PML4_OFF + L4_SLOT_KERNBASE*8)(%esi),%ebx 571f5df1827Smickey leal (PROC0_PTP3_OFF)(%esi),%eax 572f5df1827Smickey orl $(PG_V|PG_KW), %eax 573f5df1827Smickey movl $NKL4_KIMG_ENTRIES,%ecx 574f5df1827Smickey fillkpt 575f5df1827Smickey 576f00c9240Sart /* 577f00c9240Sart * Map the first 4 GB with the direct map. We'll map the rest 578f00c9240Sart * in pmap_bootstrap. But we always need the first 4GB during 579c7636a68Smlarkin * bootstrap. The direct map is mapped RW, NX. We also change 580c7636a68Smlarkin * the permissions on the 2MB pages corresponding to the kernel 581c7636a68Smlarkin * PAs to RO to prevent someone writing to the kernel area 582c7636a68Smlarkin * via the direct map. 583f00c9240Sart */ 584f00c9240Sart leal (PROC0_DMP2_OFF)(%esi), %ebx 585f00c9240Sart xorl %eax, %eax 586f00c9240Sart movl $(NDML2_ENTRIES * NPDPG), %ecx 587c7636a68Smlarkin1: orl $(PG_V|PG_KW|PG_PS|PG_G), %eax 588c7636a68Smlarkin cmpl $__kernel_base_phys, %eax 589c7636a68Smlarkin jl store_pte 590c7636a68Smlarkin cmpl $__kernel_end_phys, %eax 591c7636a68Smlarkin jg store_pte 592c7636a68Smlarkin andl $(~PG_KW), %eax 593c7636a68Smlarkinstore_pte: 594c7636a68Smlarkin movl %eax, (%ebx) 59536414dbbSmlarkin pushl %ebp 59636414dbbSmlarkin movl RELOC((pg_nx + 4)), %ebp 59736414dbbSmlarkin movl %ebp, 4(%ebx) 59836414dbbSmlarkin popl %ebp 599f00c9240Sart addl $8, %ebx 600f00c9240Sart addl $NBPD_L2, %eax 601f00c9240Sart loop 1b 602f00c9240Sart 603f00c9240Sart leal (PROC0_DMP3_OFF)(%esi), %ebx 604f00c9240Sart leal (PROC0_DMP2_OFF)(%esi), %eax 605f00c9240Sart orl $(PG_V|PG_KW), %eax 606f00c9240Sart movl $NDML2_ENTRIES, %ecx 60736414dbbSmlarkin fillkpt_nx 608f00c9240Sart 609f00c9240Sart leal (PROC0_PML4_OFF + PDIR_SLOT_DIRECT * 8)(%esi), %ebx 610f00c9240Sart leal (PROC0_DMP3_OFF)(%esi), %eax 611f00c9240Sart orl $(PG_V|PG_KW), %eax 612f00c9240Sart movl $NDML3_ENTRIES, %ecx 61336414dbbSmlarkin fillkpt_nx 614f00c9240Sart 615f5df1827Smickey /* Install recursive top level PDE */ 616f5df1827Smickey leal (PROC0_PML4_OFF + PDIR_SLOT_PTE*8)(%esi),%ebx 617f5df1827Smickey leal (PROC0_PML4_OFF)(%esi),%eax 618f5df1827Smickey orl $(PG_V|PG_KW),%eax 619f5df1827Smickey movl %eax,(%ebx) 62036414dbbSmlarkin pushl %ebp 62136414dbbSmlarkin movl RELOC((pg_nx + 4)), %ebp 62236414dbbSmlarkin movl %ebp, 4(%ebx) 62336414dbbSmlarkin popl %ebp 624f5df1827Smickey 625f5df1827Smickey /* Save phys. addr of PTD, for libkvm. */ 626f5df1827Smickey movl $RELOC(PTDpaddr),%ebp 627f5df1827Smickey movl %esi,(%ebp) 628f5df1827Smickey movl $0,4(%ebp) 629f5df1827Smickey 630f5df1827Smickey /* 631f5df1827Smickey * Startup checklist: 632f5df1827Smickey * 1. Enable PAE (and SSE while here). 633f5df1827Smickey */ 634f5df1827Smickey movl %cr4,%eax 63549e2e7f9Sart orl $(CR4_DEFAULT),%eax 636f5df1827Smickey movl %eax,%cr4 637f5df1827Smickey 638f5df1827Smickey /* 639f5df1827Smickey * 2. Set Long Mode Enable in EFER. Also enable the 64036414dbbSmlarkin * syscall extensions and NX (if available). 641f5df1827Smickey */ 642f5df1827Smickey movl $MSR_EFER,%ecx 643f5df1827Smickey rdmsr 644f5df1827Smickey xorl %eax,%eax /* XXX */ 645f5df1827Smickey orl $(EFER_LME|EFER_SCE),%eax 64636414dbbSmlarkin movl RELOC((pg_nx + 4)), %ebx 647b73ba79bSmlarkin cmpl $0, %ebx 648b73ba79bSmlarkin je write_efer 64936414dbbSmlarkin orl $(EFER_NXE), %eax 65036414dbbSmlarkinwrite_efer: 651f5df1827Smickey wrmsr 652f5df1827Smickey 653f5df1827Smickey /* 654f5df1827Smickey * 3. Load %cr3 with pointer to PML4. 655f5df1827Smickey */ 656f5df1827Smickey movl %esi,%eax 657f5df1827Smickey movl %eax,%cr3 658f5df1827Smickey 659f5df1827Smickey /* 660f5df1827Smickey * 4. Enable paging and the rest of it. 661f5df1827Smickey */ 662f5df1827Smickey movl %cr0,%eax 663f5df1827Smickey orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP),%eax 664f5df1827Smickey movl %eax,%cr0 665f5df1827Smickey jmp compat 666f5df1827Smickeycompat: 667f5df1827Smickey 668f5df1827Smickey /* 669f5df1827Smickey * 5. 670f5df1827Smickey * Not quite done yet, we're now in a compatibility segment, 671f5df1827Smickey * in legacy mode. We must jump to a long mode segment. 672f5df1827Smickey * Need to set up a temporary GDT with a long mode segment 673f5df1827Smickey * in it to do that. 674f5df1827Smickey */ 675f5df1827Smickey 676f5df1827Smickey movl $RELOC(gdt64),%eax 677f5df1827Smickey lgdt (%eax) 678f5df1827Smickey movl $RELOC(farjmp64),%eax 679f5df1827Smickey ljmp *(%eax) 680f5df1827Smickey 681f5df1827Smickey.code64 682f5df1827Smickeylongmode: 683f5df1827Smickey /* 684f5df1827Smickey * 6. 685f5df1827Smickey * Finally, we're in long mode. However, we're still 686f5df1827Smickey * in the identity mapped area (could not jump out 687f5df1827Smickey * of that earlier because it would have been a > 32bit 688f5df1827Smickey * jump). We can do that now, so here we go. 689f5df1827Smickey */ 690f5df1827Smickey movabsq $longmode_hi,%rax 691f5df1827Smickey jmp *%rax 692f5df1827Smickeylongmode_hi: 693f5df1827Smickey /* 694f5df1827Smickey * We have arrived. 695f5df1827Smickey * There's no need anymore for the identity mapping in low 696f5df1827Smickey * memory, remove it. 697f5df1827Smickey */ 698f5df1827Smickey movq $KERNBASE,%r8 699f5df1827Smickey 700f5df1827Smickey#if L2_SLOT_KERNBASE > 0 701f5df1827Smickey movq $(NKL2_KIMG_ENTRIES+1),%rcx 702f5df1827Smickey leaq (PROC0_PTP2_OFF)(%rsi),%rbx 703f5df1827Smickey addq %r8, %rbx 704cd0e2476Smlarkin1: movq $0 ,(%rbx) 705f5df1827Smickey addq $8,%rbx 706f5df1827Smickey loop 1b 707f5df1827Smickey#endif 708f5df1827Smickey 709f5df1827Smickey#if L3_SLOT_KERNBASE > 0 710f5df1827Smickey movq $NKL3_KIMG_ENTRIES,%rcx 711f5df1827Smickey leaq (PROC0_PTP3_OFF)(%rsi),%rbx 712f5df1827Smickey addq %r8, %rbx 713cd0e2476Smlarkin1: movq $0 ,(%rbx) 714f5df1827Smickey addq $8,%rbx 715f5df1827Smickey loop 1b 716f5df1827Smickey#endif 717f5df1827Smickey 718f5df1827Smickey movq $NKL4_KIMG_ENTRIES,%rcx 719f5df1827Smickey leaq (PROC0_PML4_OFF)(%rsi),%rbx # old, phys address of PML4 720b5b9857bSart addq %r8, %rbx # new, virtual address of PML4 721cd0e2476Smlarkin1: movq $0, (%rbx) 722f5df1827Smickey addq $8,%rbx 723f5df1827Smickey loop 1b 724f5df1827Smickey 725f5df1827Smickey /* Relocate atdevbase. */ 726f5df1827Smickey movq $(TABLESIZE+KERNBASE),%rdx 727f5df1827Smickey addq %rsi,%rdx 728f5df1827Smickey movq %rdx,_C_LABEL(atdevbase)(%rip) 729f5df1827Smickey 730c7636a68Smlarkin /* Record start of symbols */ 731c7636a68Smlarkin movq $__kernel_bss_end, _C_LABEL(ssym)(%rip) 732c7636a68Smlarkin 733f5df1827Smickey /* Set up bootstrap stack. */ 734f5df1827Smickey leaq (PROC0_STK_OFF)(%rsi),%rax 735f5df1827Smickey addq %r8,%rax 736f5df1827Smickey movq %rax,_C_LABEL(proc0paddr)(%rip) 737f5df1827Smickey leaq (USPACE-FRAMESIZE)(%rax),%rsp 738f5df1827Smickey movq %rsi,PCB_CR3(%rax) # pcb->pcb_cr3 739f5df1827Smickey xorq %rbp,%rbp # mark end of frames 740f5df1827Smickey 741f5df1827Smickey xorw %ax,%ax 742f5df1827Smickey movw %ax,%gs 743f5df1827Smickey movw %ax,%fs 744f5df1827Smickey 745f5df1827Smickey /* XXX merge these */ 746f5df1827Smickey leaq TABLESIZE(%rsi),%rdi 747f5df1827Smickey call _C_LABEL(init_x86_64) 748f5df1827Smickey 749f5df1827Smickey call _C_LABEL(main) 750f5df1827Smickey 751f5df1827Smickey/*****************************************************************************/ 752f5df1827Smickey 753f5df1827Smickey/* 754f5df1827Smickey * Signal trampoline; copied to top of user stack. 755aa7a0a27Sguenther * gdb's backtrace logic matches against the instructions in this. 756f5df1827Smickey */ 757f5df1827SmickeyNENTRY(sigcode) 758f5df1827Smickey call *%rax 759f5df1827Smickey 760f5df1827Smickey movq %rsp,%rdi 761f5df1827Smickey pushq %rdi /* fake return address */ 762f5df1827Smickey movq $SYS_sigreturn,%rax 7631396572dSguenther syscall 764f5df1827Smickey movq $SYS_exit,%rax 765f5df1827Smickey syscall 766f5df1827Smickey .globl _C_LABEL(esigcode) 767f5df1827Smickey_C_LABEL(esigcode): 768f5df1827Smickey 769f5df1827Smickey/* 770f5df1827Smickey * void lgdt(struct region_descriptor *rdp); 771f5df1827Smickey * Change the global descriptor table. 772f5df1827Smickey */ 773f5df1827SmickeyNENTRY(lgdt) 774f5df1827Smickey /* Reload the descriptor table. */ 775f5df1827Smickey movq %rdi,%rax 776f5df1827Smickey lgdt (%rax) 777f5df1827Smickey /* Flush the prefetch q. */ 778f5df1827Smickey jmp 1f 779f5df1827Smickey nop 780f5df1827Smickey1: /* Reload "stale" selectors. */ 781f5df1827Smickey movl $GSEL(GDATA_SEL, SEL_KPL),%eax 782f5df1827Smickey movl %eax,%ds 783f5df1827Smickey movl %eax,%es 784f5df1827Smickey movl %eax,%ss 785f5df1827Smickey /* Reload code selector by doing intersegment return. */ 786f5df1827Smickey popq %rax 787f5df1827Smickey pushq $GSEL(GCODE_SEL, SEL_KPL) 788f5df1827Smickey pushq %rax 789f5df1827Smickey lretq 790f5df1827Smickey 791f5df1827SmickeyENTRY(setjmp) 792f5df1827Smickey /* 793f5df1827Smickey * Only save registers that must be preserved across function 794f5df1827Smickey * calls according to the ABI (%rbx, %rsp, %rbp, %r12-%r15) 795f5df1827Smickey * and %rip. 796f5df1827Smickey */ 797f5df1827Smickey movq %rdi,%rax 798f5df1827Smickey movq %rbx,(%rax) 799f5df1827Smickey movq %rsp,8(%rax) 800f5df1827Smickey movq %rbp,16(%rax) 801f5df1827Smickey movq %r12,24(%rax) 802f5df1827Smickey movq %r13,32(%rax) 803f5df1827Smickey movq %r14,40(%rax) 804f5df1827Smickey movq %r15,48(%rax) 805f5df1827Smickey movq (%rsp),%rdx 806f5df1827Smickey movq %rdx,56(%rax) 807f5df1827Smickey xorl %eax,%eax 808f5df1827Smickey ret 809f5df1827Smickey 810f5df1827SmickeyENTRY(longjmp) 811f5df1827Smickey movq %rdi,%rax 812f5df1827Smickey movq (%rax),%rbx 813f5df1827Smickey movq 8(%rax),%rsp 814f5df1827Smickey movq 16(%rax),%rbp 815f5df1827Smickey movq 24(%rax),%r12 816f5df1827Smickey movq 32(%rax),%r13 817f5df1827Smickey movq 40(%rax),%r14 818f5df1827Smickey movq 48(%rax),%r15 819f5df1827Smickey movq 56(%rax),%rdx 820f5df1827Smickey movq %rdx,(%rsp) 821f5df1827Smickey xorl %eax,%eax 822f5df1827Smickey incl %eax 823f5df1827Smickey ret 824f5df1827Smickey 825f5df1827Smickey/*****************************************************************************/ 826f5df1827Smickey 827f5df1827Smickey/* 82845053f4aSart * int cpu_switchto(struct proc *old, struct proc *new) 82945053f4aSart * Switch from "old" proc to "new". 830f5df1827Smickey */ 83145053f4aSartENTRY(cpu_switchto) 832f5df1827Smickey pushq %rbx 833f5df1827Smickey pushq %rbp 834f5df1827Smickey pushq %r12 835f5df1827Smickey pushq %r13 836f5df1827Smickey pushq %r14 837f5df1827Smickey pushq %r15 838f5df1827Smickey 839fbe53cacSkrw movq %rdi, %r13 840fbe53cacSkrw movq %rsi, %r12 841fbe53cacSkrw 84260854cb9Sguenther /* Record new proc. */ 843fbe53cacSkrw movb $SONPROC,P_STAT(%r12) # p->p_stat = SONPROC 844fbe53cacSkrw SET_CURPROC(%r12,%rcx) 84560854cb9Sguenther 846fd94711fSguenther movl CPUVAR(CPUID),%edi 847fd94711fSguenther 848fbe53cacSkrw /* If old proc exited, don't bother. */ 849fbe53cacSkrw testq %r13,%r13 850f5df1827Smickey jz switch_exited 851f5df1827Smickey 852fbe53cacSkrw /* 853fbe53cacSkrw * Save old context. 854fbe53cacSkrw * 855fbe53cacSkrw * Registers: 856fbe53cacSkrw * %rax, %rcx - scratch 857fbe53cacSkrw * %r13 - old proc, then old pcb 858fbe53cacSkrw * %r12 - new proc 859fd94711fSguenther * %edi - cpuid 860fbe53cacSkrw */ 861fbe53cacSkrw 862fbe53cacSkrw movq P_ADDR(%r13),%r13 863fbe53cacSkrw 864fd94711fSguenther /* clear the old pmap's bit for the cpu */ 865fd94711fSguenther movq PCB_PMAP(%r13),%rcx 866fd94711fSguenther lock 867f5e1db71Sguenther btrq %rdi,PM_CPUS(%rcx) 868fd94711fSguenther 869f5df1827Smickey /* Save stack pointers. */ 870f5df1827Smickey movq %rsp,PCB_RSP(%r13) 871f5df1827Smickey movq %rbp,PCB_RBP(%r13) 872fbe53cacSkrw 873f5df1827Smickeyswitch_exited: 874b13138f2Sguenther /* did old proc run in userspace? then reset the segment regs */ 875b13138f2Sguenther btrl $CPUF_USERSEGS_BIT, CPUVAR(FLAGS) 876b13138f2Sguenther jnc restore_saved 877b13138f2Sguenther 878b13138f2Sguenther /* set %ds, %es, and %fs to expected value to prevent info leak */ 879b13138f2Sguenther movw $(GSEL(GUDATA_SEL, SEL_UPL)),%ax 880b13138f2Sguenther movw %ax,%ds 881b13138f2Sguenther movw %ax,%es 882b13138f2Sguenther movw %ax,%fs 883b13138f2Sguenther 884b13138f2Sguentherrestore_saved: 885f5df1827Smickey /* 88645053f4aSart * Restore saved context. 887f5df1827Smickey * 888f5df1827Smickey * Registers: 889f5df1827Smickey * %rax, %rcx, %rdx - scratch 890f5df1827Smickey * %r13 - new pcb 891fbe53cacSkrw * %r12 - new process 892f5df1827Smickey */ 893f5df1827Smickey 894fbe53cacSkrw /* No interrupts while loading new state. */ 895fbe53cacSkrw cli 896fbe53cacSkrw movq P_ADDR(%r12),%r13 897fbe53cacSkrw 898f5df1827Smickey /* Restore stack pointers. */ 899f5df1827Smickey movq PCB_RSP(%r13),%rsp 900f5df1827Smickey movq PCB_RBP(%r13),%rbp 901f5df1827Smickey 902fd94711fSguenther movq CPUVAR(TSS),%rcx 903fd94711fSguenther movq PCB_KSTACK(%r13),%rdx 904fd94711fSguenther movq %rdx,TSS_RSP0(%rcx) 905fd94711fSguenther 906fd94711fSguenther movq PCB_CR3(%r13),%rax 907fd94711fSguenther movq %rax,%cr3 908fd94711fSguenther 909fbe53cacSkrw /* Don't bother with the rest if switching to a system process. */ 910fbe53cacSkrw testl $P_SYSTEM,P_FLAG(%r12) 911fbe53cacSkrw jnz switch_restored 912fd94711fSguenther 913fd94711fSguenther /* set the new pmap's bit for the cpu */ 914fd94711fSguenther movl CPUVAR(CPUID),%edi 915fd94711fSguenther movq PCB_PMAP(%r13),%rcx 916fd94711fSguenther lock 917f5e1db71Sguenther btsq %rdi,PM_CPUS(%rcx) 918fd94711fSguenther#ifdef DIAGNOSTIC 919fd94711fSguenther jc _C_LABEL(switch_pmcpu_set) 920fbe53cacSkrw#endif 921f5df1827Smickey 922fbe53cacSkrwswitch_restored: 923f5df1827Smickey /* Restore cr0 (including FPU state). */ 924f5df1827Smickey movl PCB_CR0(%r13),%ecx 925f5df1827Smickey#ifdef MULTIPROCESSOR 926f5df1827Smickey movq PCB_FPCPU(%r13),%r8 927f5df1827Smickey cmpq CPUVAR(SELF),%r8 928f5df1827Smickey jz 1f 929f5df1827Smickey orl $CR0_TS,%ecx 930f5df1827Smickey1: 931f5df1827Smickey#endif 932f5df1827Smickey movq %rcx,%cr0 933f5df1827Smickey 934fbe53cacSkrw SET_CURPCB(%r13) 935fbe53cacSkrw 936f5df1827Smickey /* Interrupts are okay again. */ 937f5df1827Smickey sti 938f5df1827Smickey 939fbe53cacSkrwswitch_return: 940fbe53cacSkrw 941f5df1827Smickey popq %r15 942f5df1827Smickey popq %r14 943f5df1827Smickey popq %r13 944f5df1827Smickey popq %r12 945f5df1827Smickey popq %rbp 946f5df1827Smickey popq %rbx 947f5df1827Smickey ret 948f5df1827Smickey 94945053f4aSartENTRY(cpu_idle_enter) 9502692ace4Sjordan movq _C_LABEL(cpu_idle_enter_fcn),%rax 9512692ace4Sjordan cmpq $0,%rax 9522692ace4Sjordan je 1f 9532692ace4Sjordan jmpq *%rax 9542692ace4Sjordan1: 95545053f4aSart ret 956f5df1827Smickey 95745053f4aSartENTRY(cpu_idle_cycle) 9582692ace4Sjordan movq _C_LABEL(cpu_idle_cycle_fcn),%rax 9592692ace4Sjordan cmpq $0,%rax 9602692ace4Sjordan je 1f 9612692ace4Sjordan call *%rax 9622692ace4Sjordan ret 9632692ace4Sjordan1: 9642692ace4Sjordan sti 96545053f4aSart hlt 96645053f4aSart ret 967f5df1827Smickey 96845053f4aSartENTRY(cpu_idle_leave) 9692692ace4Sjordan movq _C_LABEL(cpu_idle_leave_fcn),%rax 9702692ace4Sjordan cmpq $0,%rax 9712692ace4Sjordan je 1f 9722692ace4Sjordan jmpq *%rax 9732692ace4Sjordan1: 97445053f4aSart ret 975f5df1827Smickey 976da4ea94cSart .globl _C_LABEL(panic) 977da4ea94cSart 978da4ea94cSart#ifdef DIAGNOSTIC 979fd94711fSguentherNENTRY(switch_pmcpu_set) 980fd94711fSguenther movabsq $1f,%rdi 981fd94711fSguenther call _C_LABEL(panic) 982fd94711fSguenther /* NOTREACHED */ 983fd94711fSguenther1: .asciz "activate already active pmap" 984da4ea94cSart#endif /* DIAGNOSTIC */ 985f5df1827Smickey 986f5df1827Smickey/* 987f5df1827Smickey * savectx(struct pcb *pcb); 988f5df1827Smickey * Update pcb, saving current processor state. 989f5df1827Smickey */ 990f5df1827SmickeyENTRY(savectx) 991f5df1827Smickey /* Save stack pointers. */ 992f5df1827Smickey movq %rsp,PCB_RSP(%rdi) 993f5df1827Smickey movq %rbp,PCB_RBP(%rdi) 994f5df1827Smickey 995f5df1827Smickey ret 996f5df1827Smickey 997f5df1827SmickeyIDTVEC(syscall32) 998f5df1827Smickey sysret /* go away please */ 999f5df1827Smickey 1000f5df1827Smickey/* 1001f5df1827Smickey * syscall insn entry. This currently isn't much faster, but 1002f5df1827Smickey * it can be made faster in the future. 1003f5df1827Smickey */ 1004f5df1827SmickeyIDTVEC(syscall) 100574ebaa6aSguenther /* 100674ebaa6aSguenther * Enter here with interrupts blocked; %rcx contains the caller's 100774ebaa6aSguenther * %rip and the original rflags has been copied to %r11. %cs and 100874ebaa6aSguenther * %ss have been updated to the kernel segments, but %rsp is still 100974ebaa6aSguenther * the user-space value. 101074ebaa6aSguenther * First order of business is to swap to the kernel gs.base so that 101174ebaa6aSguenther * we can access our struct cpu_info and use the scratch space there 101274ebaa6aSguenther * to switch to our kernel stack. Once that's in place we can 101374ebaa6aSguenther * unblock interrupts and save the rest of the syscall frame. 101474ebaa6aSguenther */ 1015f5df1827Smickey swapgs 1016f5df1827Smickey movq %r15,CPUVAR(SCRATCH) 1017f5df1827Smickey movq CPUVAR(CURPCB),%r15 1018fd94711fSguenther movq PCB_KSTACK(%r15),%r15 1019f5df1827Smickey xchgq %r15,%rsp 1020f5df1827Smickey sti 1021f5df1827Smickey 1022f5df1827Smickey /* 1023f5df1827Smickey * XXX don't need this whole frame, split of the 1024f5df1827Smickey * syscall frame and trapframe is needed. 1025f5df1827Smickey * First, leave some room for the trapno, error, 1026f5df1827Smickey * ss:rsp, etc, so that all GP registers can be 1027f5df1827Smickey * saved. Then, fill in the rest. 1028f5df1827Smickey */ 10291f7e6433Sguenther pushq $(GSEL(GUDATA_SEL, SEL_UPL)) 1030f5df1827Smickey pushq %r15 1031f5df1827Smickey subq $(TF_RSP-TF_TRAPNO),%rsp 1032f5df1827Smickey movq CPUVAR(SCRATCH),%r15 1033f5df1827Smickey subq $32,%rsp 1034f5df1827Smickey INTR_SAVE_GPRS 1035f5df1827Smickey movq %r11, TF_RFLAGS(%rsp) /* old rflags from syscall insn */ 10361f7e6433Sguenther movq $(GSEL(GUCODE_SEL, SEL_UPL)), TF_CS(%rsp) 1037f5df1827Smickey movq %rcx,TF_RIP(%rsp) 10386620a6fbSguenther movq $2,TF_ERR(%rsp) /* ignored */ 1039f5df1827Smickey 1040f5df1827Smickey movq CPUVAR(CURPROC),%r14 1041f5df1827Smickey movq %rsp,P_MD_REGS(%r14) # save pointer to frame 1042f5df1827Smickey andl $~MDP_IRET,P_MD_FLAGS(%r14) 1043b5b9857bSart movq %rsp,%rdi 10444e1a77ceSsturm call _C_LABEL(syscall) 1045c9ad316fSguenther 1046c9ad316fSguenther.Lsyscall_check_asts: 1047c9ad316fSguenther /* Check for ASTs on exit to user mode. */ 1048f5df1827Smickey cli 1049f5df1827Smickey CHECK_ASTPENDING(%r11) 1050f5df1827Smickey je 2f 1051f5df1827Smickey CLEAR_ASTPENDING(%r11) 1052f5df1827Smickey sti 1053b5b9857bSart movq %rsp,%rdi 1054c9ad316fSguenther call _C_LABEL(ast) 1055c9ad316fSguenther jmp .Lsyscall_check_asts 1056c9ad316fSguenther 1057f5df1827Smickey2: 1058f5df1827Smickey#ifdef DIAGNOSTIC 1059b5b9857bSart cmpl $IPL_NONE,CPUVAR(ILEVEL) 1060c9ad316fSguenther jne .Lsyscall_spl_not_lowered 10611396572dSguenther#endif /* DIAGNOSTIC */ 10621396572dSguenther 1063c9ad316fSguenther /* Could registers have been changed that require an iretq? */ 1064c9ad316fSguenther testl $MDP_IRET, P_MD_FLAGS(%r14) 1065c9ad316fSguenther jne intr_fast_exit 1066c9ad316fSguenther 10671396572dSguenther movq TF_RDI(%rsp),%rdi 10681396572dSguenther movq TF_RSI(%rsp),%rsi 10691396572dSguenther movq TF_R8(%rsp),%r8 10701396572dSguenther movq TF_R9(%rsp),%r9 10711396572dSguenther movq TF_R10(%rsp),%r10 10721396572dSguenther movq TF_R12(%rsp),%r12 10731396572dSguenther movq TF_R13(%rsp),%r13 10741396572dSguenther movq TF_R14(%rsp),%r14 10751396572dSguenther movq TF_R15(%rsp),%r15 10761396572dSguenther movq TF_RBP(%rsp),%rbp 10771396572dSguenther movq TF_RBX(%rsp),%rbx 10781396572dSguenther 1079f1665d79Sguenther INTR_RESTORE_SELECTORS 10801396572dSguenther 10811396572dSguenther movq TF_RDX(%rsp),%rdx 10821396572dSguenther movq TF_RAX(%rsp),%rax 10831396572dSguenther 10841396572dSguenther movq TF_RIP(%rsp),%rcx 10851396572dSguenther movq TF_RFLAGS(%rsp),%r11 10861396572dSguenther movq TF_RSP(%rsp),%rsp 1087f5df1827Smickey sysretq 1088f5df1827Smickey 1089f5df1827Smickey#ifdef DIAGNOSTIC 1090c9ad316fSguenther.Lsyscall_spl_not_lowered: 1091c9ad316fSguenther movabsq $4f, %rdi 1092f5df1827Smickey movl TF_RAX(%rsp),%esi 1093f5df1827Smickey movl TF_RDI(%rsp),%edx 1094f5df1827Smickey movl %ebx,%ecx 1095b5b9857bSart movl CPUVAR(ILEVEL),%r8d 1096f5df1827Smickey xorq %rax,%rax 1097f5df1827Smickey call _C_LABEL(printf) 1098f5df1827Smickey#ifdef DDB 1099f5df1827Smickey int $3 1100f5df1827Smickey#endif /* DDB */ 1101f5df1827Smickey movl $IPL_NONE,CPUVAR(ILEVEL) 1102c9ad316fSguenther jmp .Lsyscall_check_asts 1103f5df1827Smickey4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL %d %d EXIT %x %x\n" 1104f5df1827Smickey#endif 1105f5df1827Smickey 1106f5df1827Smickey 1107f5df1827SmickeyNENTRY(proc_trampoline) 1108f5df1827Smickey#ifdef MULTIPROCESSOR 1109f5df1827Smickey call _C_LABEL(proc_trampoline_mp) 1110f5df1827Smickey#endif 1111f5df1827Smickey movl $IPL_NONE,CPUVAR(ILEVEL) 1112f5df1827Smickey movq %r13,%rdi 1113f5df1827Smickey call *%r12 1114c9ad316fSguenther movq CPUVAR(CURPROC),%r14 1115c9ad316fSguenther jmp .Lsyscall_check_asts 1116f5df1827Smickey 1117f5df1827Smickey 1118f5df1827Smickey/* 11191396572dSguenther * Return via iretq, for real interrupts and signal returns 11201396572dSguenther */ 1121c9ad316fSguentherNENTRY(intr_fast_exit) 11221396572dSguenther movq TF_RDI(%rsp),%rdi 11231396572dSguenther movq TF_RSI(%rsp),%rsi 11241396572dSguenther movq TF_R8(%rsp),%r8 11251396572dSguenther movq TF_R9(%rsp),%r9 11261396572dSguenther movq TF_R10(%rsp),%r10 11271396572dSguenther movq TF_R12(%rsp),%r12 11281396572dSguenther movq TF_R13(%rsp),%r13 11291396572dSguenther movq TF_R14(%rsp),%r14 11301396572dSguenther movq TF_R15(%rsp),%r15 11311396572dSguenther movq TF_RBP(%rsp),%rbp 11321396572dSguenther movq TF_RBX(%rsp),%rbx 11331396572dSguenther 113492f33f2bSguenther testq $SEL_RPL,TF_CS(%rsp) 1135c6853312Sguenther je 5f 11361396572dSguenther 1137f1665d79Sguenther INTR_RESTORE_SELECTORS 11381396572dSguenther 11391396572dSguenther5: movq TF_RDX(%rsp),%rdx 11401396572dSguenther movq TF_RCX(%rsp),%rcx 11411396572dSguenther movq TF_R11(%rsp),%r11 11421396572dSguenther movq TF_RAX(%rsp),%rax 11431396572dSguenther addq $TF_RIP,%rsp 11441396572dSguenther 1145c6853312Sguenther .globl _C_LABEL(doreti_iret) 1146c6853312Sguenther_C_LABEL(doreti_iret): 1147c6853312Sguenther iretq 1148c6853312Sguenther 11493a36161cSart 11503a36161cSartENTRY(pagezero) 11513a36161cSart movq $-PAGE_SIZE,%rdx 11523a36161cSart subq %rdx,%rdi 11533a36161cSart xorq %rax,%rax 11543a36161cSart1: 11553a36161cSart movnti %rax,(%rdi,%rdx) 11563a36161cSart movnti %rax,8(%rdi,%rdx) 11573a36161cSart movnti %rax,16(%rdi,%rdx) 11583a36161cSart movnti %rax,24(%rdi,%rdx) 11593a36161cSart addq $32,%rdx 11603a36161cSart jne 1b 11613a36161cSart sfence 11623a36161cSart ret 11633c8478a6Sgwk 116461d6df42Ssf .section .codepatch,"a" 116561d6df42Ssf .align 8 116661d6df42Ssf .globl _C_LABEL(codepatch_begin) 116761d6df42Ssf_C_LABEL(codepatch_begin): 116861d6df42Ssf .previous 116961d6df42Ssf 117061d6df42Ssf .section .codepatchend,"a" 117161d6df42Ssf .globl _C_LABEL(codepatch_end) 117261d6df42Ssf_C_LABEL(codepatch_end): 117361d6df42Ssf .previous 1174