FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/mpboot.s
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: releng/5.1/sys/i386/i386/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
76 NON_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 */
100 mp_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
113 1:
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
142 BOOTMP1:
143
144 NON_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
182 protmode:
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
202 bigJump:
203 /* this will be modified by mpInstallTramp() */
204 ljmp $0x08, $0 /* far jmp to MPentry() */
205
206 dead: 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
216 MP_GDT:
217
218 nulldesc: /* offset = 0x0 */
219
220 .word 0x0
221 .word 0x0
222 .byte 0x0
223 .byte 0x0
224 .byte 0x0
225 .byte 0x0
226
227 kernelcode: /* 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
236 kerneldata: /* 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
245 bootcode: /* offset = 0x18 */
246
247 .word 0xffff /* segment limit 0..15 */
248 bootCodeSeg: /* 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
255 bootdata: /* offset = 0x20 */
256
257 .word 0xffff
258 bootDataSeg: /* 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
270 MP_GDTptr:
271 mp_gdtlimit:
272 .word 0x0028
273 mp_gdtbase: /* this will be modified by mpInstallTramp() */
274 .long 0
275
276 .space 0x100 /* space for boot_stk - 1st temporary stack */
277 boot_stk:
278
279 BOOTMP2:
280 .globl bootMP_size
281 bootMP_size:
282 .long BOOTMP2 - BOOTMP1
Cache object: f7101684390e46b6d05eb8b3a0e5856e
|