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