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