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 "opt_pmap.h"
38
39 #include <machine/asmacros.h> /* miscellaneous asm macros */
40 #include <machine/apicreg.h>
41 #include <machine/specialreg.h>
42
43 #include "assym.s"
44
45 #define R(x) ((x)-KERNBASE)
46
47 /*
48 * this code MUST be enabled here and in mp_machdep.c
49 * it follows the very early stages of AP boot by placing values in CMOS ram.
50 * it NORMALLY will never be needed and thus the primitive method for enabling.
51 *
52 #define CHECK_POINTS
53 */
54
55 #if defined(CHECK_POINTS) && !defined(PC98)
56
57 #define CMOS_REG (0x70)
58 #define CMOS_DATA (0x71)
59
60 #define CHECKPOINT(A,D) \
61 movb $(A),%al ; \
62 outb %al,$CMOS_REG ; \
63 movb $(D),%al ; \
64 outb %al,$CMOS_DATA
65
66 #else
67
68 #define CHECKPOINT(A,D)
69
70 #endif /* CHECK_POINTS */
71
72
73 /*
74 * the APs enter here from their trampoline code (bootMP, below)
75 */
76 .p2align 4
77
78 NON_GPROF_ENTRY(MPentry)
79 CHECKPOINT(0x36, 3)
80 /*
81 * Enable features on this processor. We don't support SMP on
82 * CPUs older than a Pentium, so we know that we can use the cpuid
83 * instruction.
84 */
85 movl $1,%eax
86 cpuid /* Retrieve features */
87 movl %cr4,%eax
88 #ifndef DISABLE_PSE
89 testl $CPUID_PSE,%edx
90 jz 1f
91 orl $CR4_PSE,%eax /* Enable PSE */
92 1:
93 #endif
94 #ifndef DISABLE_PG_G
95 testl $CPUID_PGE,%edx
96 jz 1f
97 orl $CR4_PGE,%eax /* Enable PGE */
98 1:
99 #endif
100 testl $CPUID_VME,%edx
101 jz 1f
102 orl $CR4_VME,%eax /* Enable VME */
103 1:
104 movl %eax,%cr4
105
106 /* Now enable paging mode */
107 #ifdef PAE
108 movl R(IdlePDPT), %eax
109 movl %eax, %cr3
110 movl %cr4, %eax
111 orl $CR4_PAE, %eax
112 movl %eax, %cr4
113 #else
114 movl R(IdlePTD), %eax
115 movl %eax,%cr3
116 #endif
117 movl %cr0,%eax
118 orl $CR0_PE|CR0_PG,%eax /* enable paging */
119 movl %eax,%cr0 /* let the games begin! */
120 movl bootSTK,%esp /* boot stack end loc. */
121
122 pushl $mp_begin /* jump to high mem */
123 ret
124
125 /*
126 * Wait for the booting CPU to signal startup
127 */
128 mp_begin: /* now running relocated at KERNBASE */
129 CHECKPOINT(0x37, 4)
130 call init_secondary /* load i386 tables */
131
132 /*
133 * This is the embedded trampoline or bootstrap that is
134 * copied into 'real-mode' low memory, it is where the
135 * secondary processor "wakes up". When it is executed
136 * the processor will eventually jump into the routine
137 * MPentry, which resides in normal kernel text above
138 * 1Meg. -jackv
139 */
140
141 .data
142 ALIGN_DATA /* just to be sure */
143
144 BOOTMP1:
145
146 NON_GPROF_ENTRY(bootMP)
147 .code16
148 cli
149 CHECKPOINT(0x34, 1)
150 /* First guarantee a 'clean slate' */
151 xorl %eax, %eax
152 movl %eax, %ebx
153 movl %eax, %ecx
154 movl %eax, %edx
155 movl %eax, %esi
156 movl %eax, %edi
157
158 /* set up data segments */
159 mov %cs, %ax
160 mov %ax, %ds
161 mov %ax, %es
162 mov %ax, %fs
163 mov %ax, %gs
164 mov %ax, %ss
165 mov $(boot_stk-bootMP), %esp
166
167 /* Now load the global descriptor table */
168 lgdt MP_GDTptr-bootMP
169
170 /* Enable protected mode */
171 movl %cr0, %eax
172 orl $CR0_PE, %eax
173 movl %eax, %cr0
174
175 /*
176 * make intrasegment jump to flush the processor pipeline and
177 * reload CS register
178 */
179 pushl $0x18
180 pushl $(protmode-bootMP)
181 lretl
182
183 .code32
184 protmode:
185 CHECKPOINT(0x35, 2)
186
187 /*
188 * we are NOW running for the first time with %eip
189 * having the full physical address, BUT we still
190 * are using a segment descriptor with the origin
191 * not matching the booting kernel.
192 *
193 * SO NOW... for the BIG Jump into kernel's segment
194 * and physical text above 1 Meg.
195 */
196 mov $0x10, %ebx
197 movw %bx, %ds
198 movw %bx, %es
199 movw %bx, %fs
200 movw %bx, %gs
201 movw %bx, %ss
202
203 .globl bigJump
204 bigJump:
205 /* this will be modified by mpInstallTramp() */
206 ljmp $0x08, $0 /* far jmp to MPentry() */
207
208 dead: hlt /* We should never get here */
209 jmp dead
210
211 /*
212 * MP boot strap Global Descriptor Table
213 */
214 .p2align 4
215 .globl MP_GDT
216 .globl bootCodeSeg
217 .globl bootDataSeg
218 MP_GDT:
219
220 nulldesc: /* offset = 0x0 */
221
222 .word 0x0
223 .word 0x0
224 .byte 0x0
225 .byte 0x0
226 .byte 0x0
227 .byte 0x0
228
229 kernelcode: /* offset = 0x08 */
230
231 .word 0xffff /* segment limit 0..15 */
232 .word 0x0000 /* segment base 0..15 */
233 .byte 0x0 /* segment base 16..23; set for 0K */
234 .byte 0x9f /* flags; Type */
235 .byte 0xcf /* flags; Limit */
236 .byte 0x0 /* segment base 24..32 */
237
238 kerneldata: /* offset = 0x10 */
239
240 .word 0xffff /* segment limit 0..15 */
241 .word 0x0000 /* segment base 0..15 */
242 .byte 0x0 /* segment base 16..23; set for 0k */
243 .byte 0x93 /* flags; Type */
244 .byte 0xcf /* flags; Limit */
245 .byte 0x0 /* segment base 24..32 */
246
247 bootcode: /* offset = 0x18 */
248
249 .word 0xffff /* segment limit 0..15 */
250 bootCodeSeg: /* this will be modified by mpInstallTramp() */
251 .word 0x0000 /* segment base 0..15 */
252 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
253 .byte 0x9e /* flags; Type */
254 .byte 0xcf /* flags; Limit */
255 .byte 0x0 /*segment base 24..32 */
256
257 bootdata: /* offset = 0x20 */
258
259 .word 0xffff
260 bootDataSeg: /* this will be modified by mpInstallTramp() */
261 .word 0x0000 /* segment base 0..15 */
262 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
263 .byte 0x92
264 .byte 0xcf
265 .byte 0x0
266
267 /*
268 * GDT pointer for the lgdt call
269 */
270 .globl mp_gdtbase
271
272 MP_GDTptr:
273 mp_gdtlimit:
274 .word 0x0028
275 mp_gdtbase: /* this will be modified by mpInstallTramp() */
276 .long 0
277
278 .space 0x100 /* space for boot_stk - 1st temporary stack */
279 boot_stk:
280
281 BOOTMP2:
282 .globl bootMP_size
283 bootMP_size:
284 .long BOOTMP2 - BOOTMP1
Cache object: 4d944ed4b95083225e503c3c389a983b
|