1b2b3ffcdSSimon Schubert/*- 2b2b3ffcdSSimon Schubert * Copyright (c) 2003 Peter Wemm 3b2b3ffcdSSimon Schubert * All rights reserved. 4b2b3ffcdSSimon Schubert * 5b2b3ffcdSSimon Schubert * Redistribution and use in source and binary forms, with or without 6b2b3ffcdSSimon Schubert * modification, are permitted provided that the following conditions 7b2b3ffcdSSimon Schubert * are met: 8b2b3ffcdSSimon Schubert * 1. Redistributions of source code must retain the above copyright 9b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer. 10b2b3ffcdSSimon Schubert * 2. Redistributions in binary form must reproduce the above copyright 11b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer in the 12b2b3ffcdSSimon Schubert * documentation and/or other materials provided with the distribution. 13b2b3ffcdSSimon Schubert * 14b2b3ffcdSSimon Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15b2b3ffcdSSimon Schubert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16b2b3ffcdSSimon Schubert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17b2b3ffcdSSimon Schubert * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18b2b3ffcdSSimon Schubert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19b2b3ffcdSSimon Schubert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20b2b3ffcdSSimon Schubert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21b2b3ffcdSSimon Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22b2b3ffcdSSimon Schubert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23b2b3ffcdSSimon Schubert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24b2b3ffcdSSimon Schubert * SUCH DAMAGE. 25b2b3ffcdSSimon Schubert * 26b2b3ffcdSSimon Schubert * $FreeBSD: head/sys/amd64/amd64/mpboot.S 130224 2004-06-08 01:02:52Z peter $ 27b2b3ffcdSSimon Schubert */ 28b2b3ffcdSSimon Schubert 29b2b3ffcdSSimon Schubert#include <machine/asmacros.h> /* miscellaneous asm macros */ 30b2b3ffcdSSimon Schubert#include <machine/specialreg.h> 31b2b3ffcdSSimon Schubert 32b2b3ffcdSSimon Schubert#include "assym.s" 33b2b3ffcdSSimon Schubert 34b2b3ffcdSSimon Schubert .data /* So we can modify it */ 35b2b3ffcdSSimon Schubert 36b2b3ffcdSSimon Schubert .p2align 4,0 37b2b3ffcdSSimon Schubert .globl mptramp_start 38b2b3ffcdSSimon Schubertmptramp_start: 39b2b3ffcdSSimon Schubert .code16 40b2b3ffcdSSimon Schubert /* 41b2b3ffcdSSimon Schubert * The AP enters here in response to the startup IPI. 42b2b3ffcdSSimon Schubert * We are in real mode. %cs is the only segment register set. 43b2b3ffcdSSimon Schubert */ 44b2b3ffcdSSimon Schubert cli /* make sure no interrupts */ 45b2b3ffcdSSimon Schubert mov %cs, %ax /* copy %cs to %ds. Remember these */ 46b2b3ffcdSSimon Schubert mov %ax, %ds /* are offsets rather than selectors */ 47b2b3ffcdSSimon Schubert mov %ax, %ss 48b2b3ffcdSSimon Schubert 49b2b3ffcdSSimon Schubert /* 50b2b3ffcdSSimon Schubert * Find relocation base and patch the gdt descript and ljmp targets 51b2b3ffcdSSimon Schubert */ 52b2b3ffcdSSimon Schubert xorl %ebx,%ebx 53b2b3ffcdSSimon Schubert mov %cs, %bx 54b2b3ffcdSSimon Schubert sall $4, %ebx /* %ebx is now our relocation base */ 55b2b3ffcdSSimon Schubert orl %ebx, lgdt_desc-mptramp_start+2 56b2b3ffcdSSimon Schubert orl %ebx, jmp_32-mptramp_start+2 57b2b3ffcdSSimon Schubert orl %ebx, jmp_64-mptramp_start+1 58b2b3ffcdSSimon Schubert 59b2b3ffcdSSimon Schubert /* 60b2b3ffcdSSimon Schubert * Load the descriptor table pointer. We'll need it when running 61b2b3ffcdSSimon Schubert * in 16 bit protected mode. 62b2b3ffcdSSimon Schubert */ 63b2b3ffcdSSimon Schubert lgdt lgdt_desc-mptramp_start 64b2b3ffcdSSimon Schubert 65b2b3ffcdSSimon Schubert /* Enable protected mode */ 66b2b3ffcdSSimon Schubert movl $CR0_PE, %eax 67b2b3ffcdSSimon Schubert mov %eax, %cr0 68b2b3ffcdSSimon Schubert 69b2b3ffcdSSimon Schubert /* 70b2b3ffcdSSimon Schubert * Now execute a far jump to turn on protected mode. This 71b2b3ffcdSSimon Schubert * causes the segment registers to turn into selectors and causes 72b2b3ffcdSSimon Schubert * %cs to be loaded from the gdt. 73b2b3ffcdSSimon Schubert * 74b2b3ffcdSSimon Schubert * The following instruction is: 75b2b3ffcdSSimon Schubert * ljmpl $bootcode-gdt, $protmode-mptramp_start 76b2b3ffcdSSimon Schubert * but gas cannot assemble that. And besides, we patch the targets 77b2b3ffcdSSimon Schubert * in early startup and its a little clearer what we are patching. 78b2b3ffcdSSimon Schubert */ 79b2b3ffcdSSimon Schubertjmp_32: 80b2b3ffcdSSimon Schubert .byte 0x66 /* size override to 32 bits */ 81b2b3ffcdSSimon Schubert .byte 0xea /* opcode for far jump */ 82b2b3ffcdSSimon Schubert .long protmode-mptramp_start /* offset in segment */ 83b2b3ffcdSSimon Schubert .word bootcode-gdt /* index in gdt for 32 bit code */ 84b2b3ffcdSSimon Schubert 85b2b3ffcdSSimon Schubert /* 86b2b3ffcdSSimon Schubert * At this point, we are running in 32 bit legacy protected mode. 87b2b3ffcdSSimon Schubert */ 88b2b3ffcdSSimon Schubert .code32 89b2b3ffcdSSimon Schubertprotmode: 90b2b3ffcdSSimon Schubert mov $bootdata-gdt, %eax 91b2b3ffcdSSimon Schubert mov %ax, %ds 92b2b3ffcdSSimon Schubert 93b2b3ffcdSSimon Schubert /* Turn on the PAE, PSE and PGE bits for when paging is enabled */ 94b2b3ffcdSSimon Schubert mov %cr4, %eax 95b2b3ffcdSSimon Schubert orl $(CR4_PAE | CR4_PSE), %eax 96b2b3ffcdSSimon Schubert mov %eax, %cr4 97b2b3ffcdSSimon Schubert 98b2b3ffcdSSimon Schubert /* 99b2b3ffcdSSimon Schubert * Enable EFER.LME so that we get long mode when all the prereqs are 100b2b3ffcdSSimon Schubert * in place. In this case, it turns on when CR0_PG is finally enabled. 101b2b3ffcdSSimon Schubert * Pick up a few other EFER bits that we'll use need we're here. 102b2b3ffcdSSimon Schubert */ 103b2b3ffcdSSimon Schubert movl $MSR_EFER, %ecx 104b2b3ffcdSSimon Schubert rdmsr 105b2b3ffcdSSimon Schubert orl $EFER_LME | EFER_SCE, %eax 106b2b3ffcdSSimon Schubert wrmsr 107b2b3ffcdSSimon Schubert 108b2b3ffcdSSimon Schubert /* 109b2b3ffcdSSimon Schubert * Point to the embedded page tables for startup. Note that this 110b2b3ffcdSSimon Schubert * only gets accessed after we're actually in 64 bit mode, however 111b2b3ffcdSSimon Schubert * we can only set the bottom 32 bits of %cr3 in this state. This 112b2b3ffcdSSimon Schubert * means we are required to use a temporary page table that is below 113b2b3ffcdSSimon Schubert * the 4GB limit. %ebx is still our relocation base. We could just 114b2b3ffcdSSimon Schubert * subtract 3 * PAGE_SIZE, but that would be too easy. 115b2b3ffcdSSimon Schubert */ 116b2b3ffcdSSimon Schubert leal mptramp_pagetables-mptramp_start(%ebx),%eax 117b2b3ffcdSSimon Schubert movl (%eax), %eax 118b2b3ffcdSSimon Schubert mov %eax, %cr3 119b2b3ffcdSSimon Schubert 120b2b3ffcdSSimon Schubert /* 121b2b3ffcdSSimon Schubert * Finally, switch to long bit mode by enabling paging. We have 122b2b3ffcdSSimon Schubert * to be very careful here because all the segmentation disappears 123b2b3ffcdSSimon Schubert * out from underneath us. The spec says we can depend on the 124*87ef2da6Szrj * subsequent pipelined branch to execute, but *only if* everything 125b2b3ffcdSSimon Schubert * is still identity mapped. If any mappings change, the pipeline 126b2b3ffcdSSimon Schubert * will flush. 127b2b3ffcdSSimon Schubert */ 128b2b3ffcdSSimon Schubert mov %cr0, %eax 129b2b3ffcdSSimon Schubert orl $CR0_PG, %eax 130b2b3ffcdSSimon Schubert mov %eax, %cr0 131b2b3ffcdSSimon Schubert 132b2b3ffcdSSimon Schubert /* 133*87ef2da6Szrj * At this point paging is enabled, and we are in "compatibility" mode. 134b2b3ffcdSSimon Schubert * We do another far jump to reload %cs with the 64 bit selector. 135b2b3ffcdSSimon Schubert * %cr3 points to a 4-level page table page. 136b2b3ffcdSSimon Schubert * We cannot yet jump all the way to the kernel because we can only 137b2b3ffcdSSimon Schubert * specify a 32 bit linear address. So, yet another trampoline. 138b2b3ffcdSSimon Schubert * 139b2b3ffcdSSimon Schubert * The following instruction is: 140b2b3ffcdSSimon Schubert * ljmp $kernelcode-gdt, $tramp_64-mptramp_start 141b2b3ffcdSSimon Schubert * but gas cannot assemble that. And besides, we patch the targets 142b2b3ffcdSSimon Schubert * in early startup and its a little clearer what we are patching. 143b2b3ffcdSSimon Schubert */ 144b2b3ffcdSSimon Schubertjmp_64: 145b2b3ffcdSSimon Schubert .byte 0xea /* opcode for far jump */ 146b2b3ffcdSSimon Schubert .long tramp_64-mptramp_start /* offset in segment */ 147b2b3ffcdSSimon Schubert .word kernelcode-gdt /* index in gdt for 64 bit code */ 148b2b3ffcdSSimon Schubert 149b2b3ffcdSSimon Schubert /* 150b2b3ffcdSSimon Schubert * Yeehar! We're running in 64 bit mode! We can mostly ignore our 151b2b3ffcdSSimon Schubert * segment registers, and get on with it. 152b2b3ffcdSSimon Schubert * Note that we are running at the correct virtual address, but with 153b2b3ffcdSSimon Schubert * a 1:1 1GB mirrored mapping over entire address space. We had better 154b2b3ffcdSSimon Schubert * switch to a real %cr3 promptly so that we can get to the direct map 155b2b3ffcdSSimon Schubert * space. Remember that jmp is relative and that we've been relocated, 156b2b3ffcdSSimon Schubert * so use an indirect jump. 157b2b3ffcdSSimon Schubert */ 158b2b3ffcdSSimon Schubert .code64 159b2b3ffcdSSimon Schuberttramp_64: 160b2b3ffcdSSimon Schubert movabsq $entry_64,%rax /* 64 bit immediate load */ 161b2b3ffcdSSimon Schubert jmp *%rax 162b2b3ffcdSSimon Schubert 163b2b3ffcdSSimon Schubert .p2align 4,0 164b2b3ffcdSSimon Schubertgdt: 165b2b3ffcdSSimon Schubert /* 166b2b3ffcdSSimon Schubert * All segment descriptor tables start with a null descriptor 167b2b3ffcdSSimon Schubert */ 168b2b3ffcdSSimon Schubert .long 0x00000000 169b2b3ffcdSSimon Schubert .long 0x00000000 170b2b3ffcdSSimon Schubert 171b2b3ffcdSSimon Schubert /* 172b2b3ffcdSSimon Schubert * This is the 64 bit long mode code descriptor. There is no 173b2b3ffcdSSimon Schubert * 64 bit data descriptor. 174b2b3ffcdSSimon Schubert */ 175b2b3ffcdSSimon Schubertkernelcode: 176b2b3ffcdSSimon Schubert .long 0x00000000 177b2b3ffcdSSimon Schubert .long 0x00209800 178b2b3ffcdSSimon Schubert 179b2b3ffcdSSimon Schubert /* 180b2b3ffcdSSimon Schubert * This is the descriptor for the 32 bit boot code. 181b2b3ffcdSSimon Schubert * %cs: +A, +R, -C, DPL=0, +P, +D, +G 182b2b3ffcdSSimon Schubert * Accessed, Readable, Present, 32 bit, 4G granularity 183b2b3ffcdSSimon Schubert */ 184b2b3ffcdSSimon Schubertbootcode: 185b2b3ffcdSSimon Schubert .long 0x0000ffff 186b2b3ffcdSSimon Schubert .long 0x00cf9b00 187b2b3ffcdSSimon Schubert 188b2b3ffcdSSimon Schubert /* 189b2b3ffcdSSimon Schubert * This is the descriptor for the 32 bit boot data. 190b2b3ffcdSSimon Schubert * We load it into %ds and %ss. The bits for each selector 191b2b3ffcdSSimon Schubert * are interpreted slightly differently. 192b2b3ffcdSSimon Schubert * %ds: +A, +W, -E, DPL=0, +P, +D, +G 193b2b3ffcdSSimon Schubert * %ss: +A, +W, -E, DPL=0, +P, +B, +G 194b2b3ffcdSSimon Schubert * Accessed, Writeable, Expand up, Present, 32 bit, 4GB 195b2b3ffcdSSimon Schubert * For %ds, +D means 'default operand size is 32 bit'. 196b2b3ffcdSSimon Schubert * For %ss, +B means the stack register is %esp rather than %sp. 197b2b3ffcdSSimon Schubert */ 198b2b3ffcdSSimon Schubertbootdata: 199b2b3ffcdSSimon Schubert .long 0x0000ffff 200b2b3ffcdSSimon Schubert .long 0x00cf9300 201b2b3ffcdSSimon Schubert 202b2b3ffcdSSimon Schubertgdtend: 203b2b3ffcdSSimon Schubert 204b2b3ffcdSSimon Schubert /* 205b2b3ffcdSSimon Schubert * The address of our page table pages that the boot code 206b2b3ffcdSSimon Schubert * uses to trampoline up to kernel address space. 207b2b3ffcdSSimon Schubert */ 208b2b3ffcdSSimon Schubert .globl mptramp_pagetables 209b2b3ffcdSSimon Schubertmptramp_pagetables: 210b2b3ffcdSSimon Schubert .long 0 211b2b3ffcdSSimon Schubert 212b2b3ffcdSSimon Schubert /* 213b2b3ffcdSSimon Schubert * The pseudo descriptor for lgdt to use. 214b2b3ffcdSSimon Schubert */ 215b2b3ffcdSSimon Schubertlgdt_desc: 216b2b3ffcdSSimon Schubert .word gdtend-gdt /* Length */ 217b2b3ffcdSSimon Schubert .long gdt-mptramp_start /* Offset plus %ds << 4 */ 218b2b3ffcdSSimon Schubert 219b2b3ffcdSSimon Schubert .globl mptramp_end 220b2b3ffcdSSimon Schubertmptramp_end: 221b2b3ffcdSSimon Schubert 222b2b3ffcdSSimon Schubert /* 223b2b3ffcdSSimon Schubert * From here on down is executed in the kernel .text section. 224b2b3ffcdSSimon Schubert * 225b2b3ffcdSSimon Schubert * Load a real %cr3 that has all the direct map stuff and switches 226b2b3ffcdSSimon Schubert * off the 1GB replicated mirror. Load a stack pointer and jump 227b2b3ffcdSSimon Schubert * into AP startup code in C. 228b2b3ffcdSSimon Schubert */ 229b2b3ffcdSSimon Schubert .text 230b2b3ffcdSSimon Schubert .code64 231b2b3ffcdSSimon Schubert .p2align 4,0 232b2b3ffcdSSimon Schubertentry_64: 233b2b3ffcdSSimon Schubert movq KPML4phys, %rax 234b2b3ffcdSSimon Schubert movq %rax, %cr3 235b2b3ffcdSSimon Schubert movq bootSTK, %rsp 236b2b3ffcdSSimon Schubert call init_secondary 237b2b3ffcdSSimon Schubert /* 238b2b3ffcdSSimon Schubert * Execute the context restore function for the idlethread which 239b2b3ffcdSSimon Schubert * has conveniently been set as curthread. Remember, %rax must 240b2b3ffcdSSimon Schubert * contain the target thread and %rbx must contain the originating 241b2b3ffcdSSimon Schubert * thread (which we just set the same since we have no originating 242b2b3ffcdSSimon Schubert * thread). BSP/AP synchronization occurs in ap_init(). We do 243b2b3ffcdSSimon Schubert * not need to mess with the BGL for this because LWKT threads are 244b2b3ffcdSSimon Schubert * self-contained on each cpu (or, at least, the idlethread is!). 245b2b3ffcdSSimon Schubert */ 246b2b3ffcdSSimon Schubert movq PCPU(curthread),%rax 247b2b3ffcdSSimon Schubert movq %rax,%rbx 248b2b3ffcdSSimon Schubert movq TD_SP(%rax),%rsp 249b2b3ffcdSSimon Schubert ret 250