mpboot.S revision 25164
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 * $Id: mpboot.s,v 1.18 1997/04/25 03:11:27 fsmp Exp $ 35 */ 36 37 38#include <machine/asmacros.h> /* miscellaneous asm macros */ 39#include <machine/apic.h> 40#include <machine/specialreg.h> 41 42#include "assym.s" 43 44/* 45 * this code MUST be enabled here and in mp_machdep.c 46 * it follows the very early stages of AP boot by placing values in CMOS ram. 47 * it NORMALLY will never be needed and thus the primitive method for enabling. 48 * 49#define CHECK_POINTS 50 */ 51 52#if defined(CHECK_POINTS) 53 54#define CMOS_REG (0x70) 55#define CMOS_DATA (0x71) 56 57#define CHECKPOINT(A,D) \ 58 movb $(A),%al ; \ 59 outb %al,$CMOS_REG ; \ 60 movb $(D),%al ; \ 61 outb %al,$CMOS_DATA 62 63#else 64 65#define CHECKPOINT(A,D) 66 67#endif /* CHECK_POINTS */ 68 69 70/* 71 * the APs enter here from their trampoline code (bootMP, below) 72 */ 73 .align 4 74 75NON_GPROF_ENTRY(MPentry) 76 CHECKPOINT(0x36, 3) 77 movl $mp_stk-KERNBASE,%esp /* mp boot stack end loc. */ 78 /* Now enable paging mode */ 79 movl _IdlePTD-KERNBASE, %eax 80 movl %eax,%cr3 81 movl %cr0,%eax 82 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 83 movl $0x80000011,%eax 84 movl %eax,%cr0 /* let the games begin! */ 85 movl $mp_stk,%esp /* mp boot stack end loc. */ 86 87 pushl $mp_begin /* jump to high mem */ 88 ret 89 90 /* 91 * Wait for the booting CPU to signal startup 92 */ 93mp_begin: /* now running relocated at KERNBASE */ 94 CHECKPOINT(0x37, 4) 95 call _init_secondary /* load i386 tables */ 96 CHECKPOINT(0x38, 5) 97 98 /* disable the APIC, just to be SURE */ 99 movl _apic_base, %esi 100 movl APIC_SVR(%esi), %eax /* get spurious vector reg. */ 101 andl $~APIC_SVR_SWEN, %eax /* clear software enable bit */ 102 movl %eax, APIC_SVR(%esi) 103 104 /* signal our startup to the BSP */ 105 movl APIC_VER(%esi), %eax /* our version reg contents */ 106 movl %eax, _cpu_apic_versions /* into [ 0 ] */ 107 incl _mp_ncpus /* signal BSP */ 108 109 /* One at a time, we are running on the shared mp_stk */ 110 /* This is the Intel reccomended semaphore method */ 111#define BL_SET 0xff 112#define BL_CLR 0x00 113 movb $BL_SET, %al 1141: 115 xchgb %al, bootlock /* xchg is implicitly locked */ 116 cmpb $BL_SET, %al /* was is set? */ 117 jz 1b /* yes, keep trying... */ 118 CHECKPOINT(0x39, 6) 119 120 /* Now, let's do some REAL WORK :-) */ 121 call _secondary_main 122/* NOT REACHED */ 1232: hlt 124 jmp 2b 125 126/* 127 * Let a CPU past the semaphore so it can use mp_stk 128 */ 129ENTRY(boot_unlock) 130 movb $BL_CLR, %al 131 xchgb %al, bootlock /* xchg is implicitly locked */ 132 ret 133 134/* 135 * This is the embedded trampoline or bootstrap that is 136 * copied into 'real-mode' low memory, it is where the 137 * secondary processor "wakes up". When it is executed 138 * the processor will eventually jump into the routine 139 * MPentry, which resides in normal kernel text above 140 * 1Meg. -jackv 141 */ 142 143#define data32 .byte 0x66 144#define addr32 .byte 0x67 145 146 .data 147 ALIGN_DATA /* just to be sure */ 148 149BOOTMP1: 150 151NON_GPROF_ENTRY(bootMP) 152 cli 153 CHECKPOINT(0x34, 1) 154 /* First guarantee a 'clean slate' */ 155 data32 156 xorl %eax, %eax 157 data32 158 movl %eax, %ebx 159 data32 160 movl %eax, %ecx 161 data32 162 movl %eax, %edx 163 data32 164 movl %eax, %esi 165 data32 166 movl %eax, %edi 167 168 /* set up data segments */ 169 mov %cs, %ax 170 mov %ax, %ds 171 mov %ax, %es 172 mov %ax, %fs 173 mov %ax, %gs 174 mov %ax, %ss 175 mov $(boot_stk-_bootMP), %sp 176 177 /* Now load the global descriptor table */ 178 addr32 179 data32 180 /* XXX: sigh: lgdt MP_GDTptr-_bootMP GAS BUG! */ 181 .byte 0x0f, 0x01, 0x15 /* XXX hand assemble! */ 182 .long MP_GDTptr-_bootMP /* XXX hand assemble! */ 183 184 /* Enable protected mode */ 185 data32 186 movl %cr0, %eax 187 data32 188 orl $CR0_PE, %eax 189 data32 190 movl %eax, %cr0 191 192 /* 193 * make intrasegment jump to flush the processor pipeline and 194 * reload CS register 195 */ 196 data32 197 pushl $0x18 198 data32 199 pushl $(protmode-_bootMP) 200 data32 201 lret 202 203protmode: 204 CHECKPOINT(0x35, 2) 205 206 /* 207 * we are NOW running for the first time with %eip 208 * having the full physical address, BUT we still 209 * are using a segment descriptor with the origin 210 * not matching the booting kernel. 211 * 212 * SO NOW... for the BIG Jump into kernel's segment 213 * and physical text above 1 Meg. 214 */ 215 mov $0x10, %ebx 216 movw %bx, %ds 217 movw %bx, %es 218 movw %bx, %fs 219 movw %bx, %gs 220 movw %bx, %ss 221 222 .globl _bigJump 223_bigJump: 224 /* this will be modified by mpInstallTramp() */ 225 ljmp $0x08, $0 /* far jmp to MPentry() */ 226 227dead: hlt /* We should never get here */ 228 jmp dead 229 230/* 231 * MP boot strap Global Descriptor Table 232 */ 233 .align 4 234 .globl _MP_GDT 235 .globl _bootCodeSeg 236 .globl _bootDataSeg 237_MP_GDT: 238 239nulldesc: /* offset = 0x0 */ 240 241 .word 0x0 242 .word 0x0 243 .byte 0x0 244 .byte 0x0 245 .byte 0x0 246 .byte 0x0 247 248kernelcode: /* offset = 0x08 */ 249 250 .word 0xffff /* segment limit 0..15 */ 251 .word 0x0000 /* segment base 0..15 */ 252 .byte 0x0 /* segment base 16..23; set for 0K */ 253 .byte 0x9f /* flags; Type */ 254 .byte 0xcf /* flags; Limit */ 255 .byte 0x0 /* segment base 24..32 */ 256 257kerneldata: /* offset = 0x10 */ 258 259 .word 0xffff /* segment limit 0..15 */ 260 .word 0x0000 /* segment base 0..15 */ 261 .byte 0x0 /* segment base 16..23; set for 0k */ 262 .byte 0x93 /* flags; Type */ 263 .byte 0xcf /* flags; Limit */ 264 .byte 0x0 /* segment base 24..32 */ 265 266bootcode: /* offset = 0x18 */ 267 268 .word 0xffff /* segment limit 0..15 */ 269_bootCodeSeg: /* this will be modified by mpInstallTramp() */ 270 .word 0x0000 /* segment base 0..15 */ 271 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 272 .byte 0x9e /* flags; Type */ 273 .byte 0xcf /* flags; Limit */ 274 .byte 0x0 /*segment base 24..32 */ 275 276bootdata: /* offset = 0x20 */ 277 278 .word 0xffff 279_bootDataSeg: /* this will be modified by mpInstallTramp() */ 280 .word 0x0000 /* segment base 0..15 */ 281 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 282 .byte 0x92 283 .byte 0xcf 284 .byte 0x0 285 286/* 287 * GDT pointer for the lgdt call 288 */ 289 .globl _mp_gdtbase 290 291MP_GDTptr: 292_mp_gdtlimit: 293 .word 0x0028 294_mp_gdtbase: /* this will be modified by mpInstallTramp() */ 295 .long 0 296 297 .space 0x100 /* space for boot_stk - 1st temporary stack */ 298boot_stk: 299 300BOOTMP2: 301 .globl _bootMP_size 302_bootMP_size: 303 .long BOOTMP2 - BOOTMP1 304 305 /* 306 * Temporary stack used while booting AP's 307 * It is protected by: 308 * 1: only one cpu is started at a time and it ends up waiting 309 * for smp_active before continuing. 310 * 2: Once smp_active != 0; further access is limited by _bootlock. 311 */ 312 .globl mp_stk 313 .space 0x2000 /* space for mp_stk - 2nd temporary stack */ 314mp_stk: 315 316 .globl bootlock 317bootlock: .byte BL_SET 318