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