1ccd9b49fSElliott Mitchell/*- 2ccd9b49fSElliott Mitchell * Copyright (c) 1995 Jack F. Vogel 3ccd9b49fSElliott Mitchell * All rights reserved. 4ccd9b49fSElliott Mitchell * 5ccd9b49fSElliott Mitchell * Redistribution and use in source and binary forms, with or without 6ccd9b49fSElliott Mitchell * modification, are permitted provided that the following conditions 7ccd9b49fSElliott Mitchell * are met: 8ccd9b49fSElliott Mitchell * 1. Redistributions of source code must retain the above copyright 9ccd9b49fSElliott Mitchell * notice, this list of conditions and the following disclaimer. 10ccd9b49fSElliott Mitchell * 2. Redistributions in binary form must reproduce the above copyright 11ccd9b49fSElliott Mitchell * notice, this list of conditions and the following disclaimer in the 12ccd9b49fSElliott Mitchell * documentation and/or other materials provided with the distribution. 13ccd9b49fSElliott Mitchell * 14ccd9b49fSElliott Mitchell * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ccd9b49fSElliott Mitchell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ccd9b49fSElliott Mitchell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ccd9b49fSElliott Mitchell * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18ccd9b49fSElliott Mitchell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ccd9b49fSElliott Mitchell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ccd9b49fSElliott Mitchell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ccd9b49fSElliott Mitchell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ccd9b49fSElliott Mitchell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ccd9b49fSElliott Mitchell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ccd9b49fSElliott Mitchell * SUCH DAMAGE. 25ccd9b49fSElliott Mitchell * 26ccd9b49fSElliott Mitchell * mpboot.s: FreeBSD machine support for the Intel MP Spec 27ccd9b49fSElliott Mitchell * multiprocessor systems. 28ccd9b49fSElliott Mitchell */ 29ccd9b49fSElliott Mitchell 30ccd9b49fSElliott Mitchell#include "opt_pmap.h" 31ccd9b49fSElliott Mitchell 32ccd9b49fSElliott Mitchell#include <machine/asmacros.h> /* miscellaneous asm macros */ 33ccd9b49fSElliott Mitchell#include <x86/apicreg.h> 34ccd9b49fSElliott Mitchell#include <machine/specialreg.h> 35ccd9b49fSElliott Mitchell 36ccd9b49fSElliott Mitchell#include "assym.inc" 37ccd9b49fSElliott Mitchell 38ccd9b49fSElliott Mitchell/* 39ccd9b49fSElliott Mitchell * this code MUST be enabled here and in mp_machdep.c 40ccd9b49fSElliott Mitchell * it follows the very early stages of AP boot by placing values in CMOS ram. 41ccd9b49fSElliott Mitchell * it NORMALLY will never be needed and thus the primitive method for enabling. 42ccd9b49fSElliott Mitchell * 43ccd9b49fSElliott Mitchell#define CHECK_POINTS 44ccd9b49fSElliott Mitchell */ 45ccd9b49fSElliott Mitchell 46ccd9b49fSElliott Mitchell#if defined(CHECK_POINTS) 47ccd9b49fSElliott Mitchell 48ccd9b49fSElliott Mitchell#define CMOS_REG (0x70) 49ccd9b49fSElliott Mitchell#define CMOS_DATA (0x71) 50ccd9b49fSElliott Mitchell 51ccd9b49fSElliott Mitchell#define CHECKPOINT(A,D) \ 52ccd9b49fSElliott Mitchell movb $(A),%al ; \ 53ccd9b49fSElliott Mitchell outb %al,$CMOS_REG ; \ 54ccd9b49fSElliott Mitchell movb $(D),%al ; \ 55ccd9b49fSElliott Mitchell outb %al,$CMOS_DATA 56ccd9b49fSElliott Mitchell 57ccd9b49fSElliott Mitchell#else 58ccd9b49fSElliott Mitchell 59ccd9b49fSElliott Mitchell#define CHECKPOINT(A,D) 60ccd9b49fSElliott Mitchell 61ccd9b49fSElliott Mitchell#endif /* CHECK_POINTS */ 62ccd9b49fSElliott Mitchell 63ccd9b49fSElliott Mitchell 64ccd9b49fSElliott Mitchell/* 65ccd9b49fSElliott Mitchell * the APs enter here from their trampoline code (bootMP, below) 66ccd9b49fSElliott Mitchell */ 67ccd9b49fSElliott Mitchell .p2align 4 68ccd9b49fSElliott Mitchell 69ccd9b49fSElliott MitchellENTRY(MPentry) 70ccd9b49fSElliott Mitchell CHECKPOINT(0x36, 3) 71ccd9b49fSElliott Mitchell /* 72ccd9b49fSElliott Mitchell * Enable features on this processor. We don't support SMP on 73ccd9b49fSElliott Mitchell * CPUs older than a Pentium, so we know that we can use the cpuid 74ccd9b49fSElliott Mitchell * instruction. 75ccd9b49fSElliott Mitchell */ 76ccd9b49fSElliott Mitchell movl $1,%eax 77ccd9b49fSElliott Mitchell cpuid /* Retrieve features */ 78ccd9b49fSElliott Mitchell movl %cr4,%eax 79ccd9b49fSElliott Mitchell testl $CPUID_PSE,%edx 80ccd9b49fSElliott Mitchell jz 1f 81ccd9b49fSElliott Mitchell orl $CR4_PSE,%eax /* Enable PSE */ 82ccd9b49fSElliott Mitchell1: testl $CPUID_PGE,%edx 83ccd9b49fSElliott Mitchell jz 2f 84ccd9b49fSElliott Mitchell orl $CR4_PGE,%eax /* Enable PGE */ 85ccd9b49fSElliott Mitchell2: testl $CPUID_VME,%edx 86ccd9b49fSElliott Mitchell jz 3f 87ccd9b49fSElliott Mitchell orl $CR4_VME,%eax /* Enable VME */ 88ccd9b49fSElliott Mitchell3: movl %eax,%cr4 89ccd9b49fSElliott Mitchell 90ccd9b49fSElliott Mitchell /* Now enable paging mode */ 91ccd9b49fSElliott Mitchell cmpl $0, pae_mode 92ccd9b49fSElliott Mitchell je 4f 93ccd9b49fSElliott Mitchell movl IdlePDPT, %eax 94ccd9b49fSElliott Mitchell movl %eax, %cr3 95ccd9b49fSElliott Mitchell movl %cr4, %eax 96ccd9b49fSElliott Mitchell orl $CR4_PAE, %eax 97ccd9b49fSElliott Mitchell movl %eax, %cr4 98ccd9b49fSElliott Mitchell movl $0x80000000, %eax 99ccd9b49fSElliott Mitchell cpuid 100ccd9b49fSElliott Mitchell movl $0x80000001, %ebx 101ccd9b49fSElliott Mitchell cmpl %ebx, %eax 102ccd9b49fSElliott Mitchell jb 5f 103ccd9b49fSElliott Mitchell movl %ebx, %eax 104ccd9b49fSElliott Mitchell cpuid 105ccd9b49fSElliott Mitchell testl $AMDID_NX, %edx 106ccd9b49fSElliott Mitchell je 5f 107ccd9b49fSElliott Mitchell movl $MSR_EFER, %ecx 108ccd9b49fSElliott Mitchell rdmsr 109ccd9b49fSElliott Mitchell orl $EFER_NXE,%eax 110ccd9b49fSElliott Mitchell wrmsr 111ccd9b49fSElliott Mitchell jmp 5f 112ccd9b49fSElliott Mitchell4: movl IdlePTD_nopae, %eax 113ccd9b49fSElliott Mitchell movl %eax,%cr3 114ccd9b49fSElliott Mitchell5: movl %cr0,%eax 115ccd9b49fSElliott Mitchell orl $CR0_PE|CR0_PG,%eax /* enable paging */ 116ccd9b49fSElliott Mitchell movl %eax,%cr0 /* let the games begin! */ 117ccd9b49fSElliott Mitchell movl bootSTK,%esp /* boot stack end loc. */ 118ccd9b49fSElliott Mitchell 119ccd9b49fSElliott Mitchell pushl $mp_begin /* jump to high mem */ 120ccd9b49fSElliott Mitchell ret 121ccd9b49fSElliott Mitchell 122ccd9b49fSElliott Mitchell /* 123ccd9b49fSElliott Mitchell * Wait for the booting CPU to signal startup 124ccd9b49fSElliott Mitchell */ 125ccd9b49fSElliott Mitchellmp_begin: /* now running relocated at KERNBASE */ 126ccd9b49fSElliott Mitchell CHECKPOINT(0x37, 4) 127ccd9b49fSElliott Mitchell call init_secondary /* load i386 tables */ 128ccd9b49fSElliott Mitchell 129ccd9b49fSElliott Mitchell/* 130ccd9b49fSElliott Mitchell * This is the embedded trampoline or bootstrap that is 131ccd9b49fSElliott Mitchell * copied into 'real-mode' low memory, it is where the 132ccd9b49fSElliott Mitchell * secondary processor "wakes up". When it is executed 133ccd9b49fSElliott Mitchell * the processor will eventually jump into the routine 134ccd9b49fSElliott Mitchell * MPentry, which resides in normal kernel text above 135ccd9b49fSElliott Mitchell * 1Meg. -jackv 136ccd9b49fSElliott Mitchell */ 137ccd9b49fSElliott Mitchell 138ccd9b49fSElliott Mitchell .data 139ccd9b49fSElliott Mitchell ALIGN_DATA /* just to be sure */ 140ccd9b49fSElliott Mitchell 141ccd9b49fSElliott MitchellBOOTMP1: 142ccd9b49fSElliott Mitchell 143ccd9b49fSElliott MitchellENTRY(bootMP) 144ccd9b49fSElliott Mitchell .code16 145ccd9b49fSElliott Mitchell cli 146ccd9b49fSElliott Mitchell CHECKPOINT(0x34, 1) 147ccd9b49fSElliott Mitchell /* First guarantee a 'clean slate' */ 148ccd9b49fSElliott Mitchell xorl %eax, %eax 149ccd9b49fSElliott Mitchell movl %eax, %ebx 150ccd9b49fSElliott Mitchell movl %eax, %ecx 151ccd9b49fSElliott Mitchell movl %eax, %edx 152ccd9b49fSElliott Mitchell movl %eax, %esi 153ccd9b49fSElliott Mitchell movl %eax, %edi 154ccd9b49fSElliott Mitchell 155ccd9b49fSElliott Mitchell /* set up data segments */ 156ccd9b49fSElliott Mitchell mov %cs, %ax 157ccd9b49fSElliott Mitchell mov %ax, %ds 158ccd9b49fSElliott Mitchell mov %ax, %es 159ccd9b49fSElliott Mitchell mov %ax, %fs 160ccd9b49fSElliott Mitchell mov %ax, %gs 161ccd9b49fSElliott Mitchell mov %ax, %ss 162ccd9b49fSElliott Mitchell mov $(boot_stk-bootMP), %esp 163ccd9b49fSElliott Mitchell 164ccd9b49fSElliott Mitchell /* Now load the global descriptor table */ 165ccd9b49fSElliott Mitchell lgdt MP_GDTptr-bootMP 166ccd9b49fSElliott Mitchell 167ccd9b49fSElliott Mitchell /* Enable protected mode */ 168ccd9b49fSElliott Mitchell movl %cr0, %eax 169ccd9b49fSElliott Mitchell orl $CR0_PE, %eax 170ccd9b49fSElliott Mitchell movl %eax, %cr0 171ccd9b49fSElliott Mitchell 172ccd9b49fSElliott Mitchell /* 173ccd9b49fSElliott Mitchell * make intrasegment jump to flush the processor pipeline and 174ccd9b49fSElliott Mitchell * reload CS register 175ccd9b49fSElliott Mitchell */ 176ccd9b49fSElliott Mitchell pushl $0x18 177ccd9b49fSElliott Mitchell pushl $(protmode-bootMP) 178ccd9b49fSElliott Mitchell lretl 179ccd9b49fSElliott Mitchell 180ccd9b49fSElliott Mitchell .code32 181ccd9b49fSElliott Mitchellprotmode: 182ccd9b49fSElliott Mitchell CHECKPOINT(0x35, 2) 183ccd9b49fSElliott Mitchell 184ccd9b49fSElliott Mitchell /* 185ccd9b49fSElliott Mitchell * we are NOW running for the first time with %eip 186ccd9b49fSElliott Mitchell * having the full physical address, BUT we still 187ccd9b49fSElliott Mitchell * are using a segment descriptor with the origin 188ccd9b49fSElliott Mitchell * not matching the booting kernel. 189ccd9b49fSElliott Mitchell * 190ccd9b49fSElliott Mitchell * SO NOW... for the BIG Jump into kernel's segment 191ccd9b49fSElliott Mitchell * and physical text above 1 Meg. 192ccd9b49fSElliott Mitchell */ 193ccd9b49fSElliott Mitchell mov $0x10, %ebx 194ccd9b49fSElliott Mitchell movw %bx, %ds 195ccd9b49fSElliott Mitchell movw %bx, %es 196ccd9b49fSElliott Mitchell movw %bx, %fs 197ccd9b49fSElliott Mitchell movw %bx, %gs 198ccd9b49fSElliott Mitchell movw %bx, %ss 199ccd9b49fSElliott Mitchell 200ccd9b49fSElliott Mitchell .globl bigJump 201ccd9b49fSElliott MitchellbigJump: 202ccd9b49fSElliott Mitchell /* this will be modified by mpInstallTramp() */ 203ccd9b49fSElliott Mitchell ljmp $0x08, $0 /* far jmp to MPentry() */ 204ccd9b49fSElliott Mitchell 205ccd9b49fSElliott Mitchelldead: hlt /* We should never get here */ 206ccd9b49fSElliott Mitchell jmp dead 207ccd9b49fSElliott Mitchell 208ccd9b49fSElliott Mitchell/* 209ccd9b49fSElliott Mitchell * MP boot strap Global Descriptor Table 210ccd9b49fSElliott Mitchell */ 211ccd9b49fSElliott Mitchell .p2align 4 212ccd9b49fSElliott Mitchell .globl MP_GDT 213ccd9b49fSElliott Mitchell .globl bootCodeSeg 214ccd9b49fSElliott Mitchell .globl bootDataSeg 215ccd9b49fSElliott MitchellMP_GDT: 216ccd9b49fSElliott Mitchell 217ccd9b49fSElliott Mitchellnulldesc: /* offset = 0x0 */ 218ccd9b49fSElliott Mitchell 219ccd9b49fSElliott Mitchell .word 0x0 220ccd9b49fSElliott Mitchell .word 0x0 221ccd9b49fSElliott Mitchell .byte 0x0 222ccd9b49fSElliott Mitchell .byte 0x0 223ccd9b49fSElliott Mitchell .byte 0x0 224ccd9b49fSElliott Mitchell .byte 0x0 225ccd9b49fSElliott Mitchell 226ccd9b49fSElliott Mitchellkernelcode: /* offset = 0x08 */ 227ccd9b49fSElliott Mitchell 228ccd9b49fSElliott Mitchell .word 0xffff /* segment limit 0..15 */ 229ccd9b49fSElliott Mitchell .word 0x0000 /* segment base 0..15 */ 230ccd9b49fSElliott Mitchell .byte 0x0 /* segment base 16..23; set for 0K */ 231ccd9b49fSElliott Mitchell .byte 0x9f /* flags; Type */ 232ccd9b49fSElliott Mitchell .byte 0xcf /* flags; Limit */ 233ccd9b49fSElliott Mitchell .byte 0x0 /* segment base 24..32 */ 234ccd9b49fSElliott Mitchell 235ccd9b49fSElliott Mitchellkerneldata: /* offset = 0x10 */ 236ccd9b49fSElliott Mitchell 237ccd9b49fSElliott Mitchell .word 0xffff /* segment limit 0..15 */ 238ccd9b49fSElliott Mitchell .word 0x0000 /* segment base 0..15 */ 239ccd9b49fSElliott Mitchell .byte 0x0 /* segment base 16..23; set for 0k */ 240ccd9b49fSElliott Mitchell .byte 0x93 /* flags; Type */ 241ccd9b49fSElliott Mitchell .byte 0xcf /* flags; Limit */ 242ccd9b49fSElliott Mitchell .byte 0x0 /* segment base 24..32 */ 243ccd9b49fSElliott Mitchell 244ccd9b49fSElliott Mitchellbootcode: /* offset = 0x18 */ 245ccd9b49fSElliott Mitchell 246ccd9b49fSElliott Mitchell .word 0xffff /* segment limit 0..15 */ 247ccd9b49fSElliott MitchellbootCodeSeg: /* this will be modified by mpInstallTramp() */ 248ccd9b49fSElliott Mitchell .word 0x0000 /* segment base 0..15 */ 249ccd9b49fSElliott Mitchell .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 250ccd9b49fSElliott Mitchell .byte 0x9e /* flags; Type */ 251ccd9b49fSElliott Mitchell .byte 0xcf /* flags; Limit */ 252ccd9b49fSElliott Mitchell .byte 0x0 /*segment base 24..32 */ 253ccd9b49fSElliott Mitchell 254ccd9b49fSElliott Mitchellbootdata: /* offset = 0x20 */ 255ccd9b49fSElliott Mitchell 256ccd9b49fSElliott Mitchell .word 0xffff 257ccd9b49fSElliott MitchellbootDataSeg: /* this will be modified by mpInstallTramp() */ 258ccd9b49fSElliott Mitchell .word 0x0000 /* segment base 0..15 */ 259ccd9b49fSElliott Mitchell .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 260ccd9b49fSElliott Mitchell .byte 0x92 261ccd9b49fSElliott Mitchell .byte 0xcf 262ccd9b49fSElliott Mitchell .byte 0x0 263ccd9b49fSElliott Mitchell 264ccd9b49fSElliott Mitchell/* 265ccd9b49fSElliott Mitchell * GDT pointer for the lgdt call 266ccd9b49fSElliott Mitchell */ 267ccd9b49fSElliott Mitchell .globl mp_gdtbase 268ccd9b49fSElliott Mitchell 269ccd9b49fSElliott MitchellMP_GDTptr: 270ccd9b49fSElliott Mitchellmp_gdtlimit: 271ccd9b49fSElliott Mitchell .word 0x0028 272ccd9b49fSElliott Mitchellmp_gdtbase: /* this will be modified by mpInstallTramp() */ 273ccd9b49fSElliott Mitchell .long 0 274ccd9b49fSElliott Mitchell 275ccd9b49fSElliott Mitchell .space 0x100 /* space for boot_stk - 1st temporary stack */ 276ccd9b49fSElliott Mitchellboot_stk: 277ccd9b49fSElliott Mitchell 278ccd9b49fSElliott MitchellBOOTMP2: 279ccd9b49fSElliott Mitchell .globl bootMP_size 280ccd9b49fSElliott MitchellbootMP_size: 281ccd9b49fSElliott Mitchell .long BOOTMP2 - BOOTMP1 282