2 * Copyright (c) 1995, Jack F. Vogel
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
31 * mpboot.s: FreeBSD machine support for the Intel MP Spec
32 * multiprocessor systems.
34 * $FreeBSD: src/sys/i386/i386/mpboot.s,v 1.13.2.3 2000/09/07 01:18:26 tegge Exp $
35 * $DragonFly: src/sys/i386/i386/Attic/mpboot.s,v 1.3 2003/07/01 20:30:40 dillon Exp $
38 #include <machine/asmacros.h> /* miscellaneous asm macros */
39 #include <machine/apic.h>
40 #include <machine/specialreg.h>
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.
52 #if defined(CHECK_POINTS) && !defined(PC98)
54 #define CMOS_REG (0x70)
55 #define CMOS_DATA (0x71)
57 #define CHECKPOINT(A,D) \
59 outb %al,$CMOS_REG ; \
65 #define CHECKPOINT(A,D)
67 #endif /* CHECK_POINTS */
71 * the APs enter here from their trampoline code (bootMP, below)
75 NON_GPROF_ENTRY(MPentry)
77 /* Now enable paging mode */
78 movl IdlePTD-KERNBASE, %eax
81 orl $CR0_PE|CR0_PG,%eax /* enable paging */
82 movl %eax,%cr0 /* let the games begin! */
83 movl bootSTK,%esp /* boot stack end loc. */
85 pushl $mp_begin /* jump to high mem */
89 * Wait for the booting CPU to signal startup
91 mp_begin: /* now running relocated at KERNBASE */
93 call init_secondary /* load i386 tables */
97 * If the [BSP] CPU has support for VME, turn it on.
99 testl $CPUID_VME, cpu_feature /* XXX WRONG! BSP! */
106 /* disable the APIC, just to be SURE */
107 movl lapic_svr, %eax /* get spurious vector reg. */
108 andl $~APIC_SVR_SWEN, %eax /* clear software enable bit */
111 /* signal our startup to the BSP */
112 movl lapic_ver, %eax /* our version reg contents */
113 movl %eax, cpu_apic_versions /* into [ 0 ] */
114 incl mp_ncpus /* signal BSP */
118 /* wait till we can get into the kernel */
121 /* Now, let's prepare for some REAL WORK :-) */
125 wbinvd /* Avoid livelock */
127 cmpl $0, CNAME(smp_started) /* Wait for last AP to be ready */
131 /* let her rip! (loads new stack) */
134 NON_GPROF_ENTRY(wait_ap)
138 wbinvd /* Avoid livelock */
141 cmpl $0, CNAME(smp_started)
154 * This is the embedded trampoline or bootstrap that is
155 * copied into 'real-mode' low memory, it is where the
156 * secondary processor "wakes up". When it is executed
157 * the processor will eventually jump into the routine
158 * MPentry, which resides in normal kernel text above
163 ALIGN_DATA /* just to be sure */
167 NON_GPROF_ENTRY(bootMP)
171 /* First guarantee a 'clean slate' */
179 /* set up data segments */
186 mov $(boot_stk - bootMP), %esp
188 /* Now load the global descriptor table */
189 lgdt MP_GDTptr - bootMP
191 /* Enable protected mode */
197 * make intrasegment jump to flush the processor pipeline and
201 pushl $(protmode - bootMP)
209 * we are NOW running for the first time with %eip
210 * having the full physical address, BUT we still
211 * are using a segment descriptor with the origin
212 * not matching the booting kernel.
214 * SO NOW... for the BIG Jump into kernel's segment
215 * and physical text above 1 Meg.
226 /* this will be modified by mpInstallTramp() */
227 ljmp $0x08, $0 /* far jmp to MPentry() */
229 dead: hlt /* We should never get here */
233 * MP boot strap Global Descriptor Table
241 nulldesc: /* offset = 0x0 */
250 kernelcode: /* offset = 0x08 */
252 .word 0xffff /* segment limit 0..15 */
253 .word 0x0000 /* segment base 0..15 */
254 .byte 0x0 /* segment base 16..23; set for 0K */
255 .byte 0x9f /* flags; Type */
256 .byte 0xcf /* flags; Limit */
257 .byte 0x0 /* segment base 24..32 */
259 kerneldata: /* offset = 0x10 */
261 .word 0xffff /* segment limit 0..15 */
262 .word 0x0000 /* segment base 0..15 */
263 .byte 0x0 /* segment base 16..23; set for 0k */
264 .byte 0x93 /* flags; Type */
265 .byte 0xcf /* flags; Limit */
266 .byte 0x0 /* segment base 24..32 */
268 bootcode: /* offset = 0x18 */
270 .word 0xffff /* segment limit 0..15 */
271 bootCodeSeg: /* this will be modified by mpInstallTramp() */
272 .word 0x0000 /* segment base 0..15 */
273 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
274 .byte 0x9e /* flags; Type */
275 .byte 0xcf /* flags; Limit */
276 .byte 0x0 /*segment base 24..32 */
278 bootdata: /* offset = 0x20 */
281 bootDataSeg: /* this will be modified by mpInstallTramp() */
282 .word 0x0000 /* segment base 0..15 */
283 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
289 * GDT pointer for the lgdt call
296 mp_gdtbase: /* this will be modified by mpInstallTramp() */
299 .space 0x100 /* space for boot_stk - 1st temporary stack */
305 .long BOOTMP2 - BOOTMP1