mpboot.S revision 120654
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 120654 2003-10-01 23:46:08Z 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#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
76NON_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#ifndef DISABLE_PSE
90	cmpl	$0, R(pseflag)
91	je	1f
92	movl	%cr4, %eax
93	orl	$CR4_PSE, %eax
94	movl	%eax, %cr4
951:
96#endif
97#ifndef DISABLE_PG_G
98	cmpl	$0, R(pgeflag)
99	je	2f
100	movl	%cr4, %eax
101	orl	$CR4_PGE, %eax
102	movl	%eax, %cr4
1032:
104#endif
105	movl	%cr0,%eax
106	orl	$CR0_PE|CR0_PG,%eax		/* enable paging */
107	movl	%eax,%cr0			/* let the games begin! */
108	movl	bootSTK,%esp			/* boot stack end loc. */
109
110	pushl	$mp_begin			/* jump to high mem */
111	ret
112
113	/*
114	 * Wait for the booting CPU to signal startup
115	 */
116mp_begin:	/* now running relocated at KERNBASE */
117	CHECKPOINT(0x37, 4)
118	call	init_secondary			/* load i386 tables */
119	CHECKPOINT(0x38, 5)
120
121	/*
122	 * If the [BSP] CPU has support for VME, turn it on.
123	 */
124	testl	$CPUID_VME, cpu_feature		/* XXX WRONG! BSP! */
125	jz	1f
126	movl	%cr4, %eax
127	orl	$CR4_VME, %eax
128	movl	%eax, %cr4
1291:
130
131	/* disable the APIC, just to be SURE */
132	movl	lapic+LA_SVR, %eax		/* get spurious vector reg. */
133	andl	$~APIC_SVR_SWEN, %eax		/* clear software enable bit */
134	movl	%eax, lapic+LA_SVR
135
136	/* signal our startup to the BSP */
137	movl	lapic+LA_VER, %eax		/* our version reg contents */
138	movl	%eax, cpu_apic_versions		/* into [ 0 ] */
139	incl	mp_ncpus			/* signal BSP */
140
141	CHECKPOINT(0x39, 6)
142
143	/* Now, let's prepare for some REAL WORK :-)  This doesn't return. */
144	call	ap_init
145
146/*
147 * This is the embedded trampoline or bootstrap that is
148 * copied into 'real-mode' low memory, it is where the
149 * secondary processor "wakes up". When it is executed
150 * the processor will eventually jump into the routine
151 * MPentry, which resides in normal kernel text above
152 * 1Meg.		-jackv
153 */
154
155	.data
156	ALIGN_DATA				/* just to be sure */
157
158BOOTMP1:
159
160NON_GPROF_ENTRY(bootMP)
161	.code16
162	cli
163	CHECKPOINT(0x34, 1)
164	/* First guarantee a 'clean slate' */
165	xorl	%eax, %eax
166	movl	%eax, %ebx
167	movl	%eax, %ecx
168 	movl	%eax, %edx
169	movl	%eax, %esi
170	movl	%eax, %edi
171
172	/* set up data segments */
173	mov	%cs, %ax
174	mov	%ax, %ds
175	mov	%ax, %es
176	mov	%ax, %fs
177	mov	%ax, %gs
178	mov	%ax, %ss
179	mov	$(boot_stk-bootMP), %esp
180
181	/* Now load the global descriptor table */
182	lgdt	MP_GDTptr-bootMP
183
184	/* Enable protected mode */
185	movl	%cr0, %eax
186	orl	$CR0_PE, %eax
187	movl	%eax, %cr0
188
189	/*
190	 * make intrasegment jump to flush the processor pipeline and
191	 * reload CS register
192	 */
193	pushl	$0x18
194	pushl	$(protmode-bootMP)
195	lretl
196
197       .code32
198protmode:
199	CHECKPOINT(0x35, 2)
200
201	/*
202	 * we are NOW running for the first time with %eip
203	 * having the full physical address, BUT we still
204	 * are using a segment descriptor with the origin
205	 * not matching the booting kernel.
206	 *
207 	 * SO NOW... for the BIG Jump into kernel's segment
208	 * and physical text above 1 Meg.
209	 */
210	mov	$0x10, %ebx
211	movw	%bx, %ds
212	movw	%bx, %es
213	movw	%bx, %fs
214	movw	%bx, %gs
215	movw	%bx, %ss
216
217	.globl	bigJump
218bigJump:
219	/* this will be modified by mpInstallTramp() */
220	ljmp	$0x08, $0			/* far jmp to MPentry() */
221
222dead:	hlt /* We should never get here */
223	jmp	dead
224
225/*
226 * MP boot strap Global Descriptor Table
227 */
228	.p2align 4
229	.globl	MP_GDT
230	.globl	bootCodeSeg
231	.globl	bootDataSeg
232MP_GDT:
233
234nulldesc:		/* offset = 0x0 */
235
236	.word	0x0
237	.word	0x0
238	.byte	0x0
239	.byte	0x0
240	.byte	0x0
241	.byte	0x0
242
243kernelcode:		/* offset = 0x08 */
244
245	.word	0xffff	/* segment limit 0..15 */
246	.word	0x0000	/* segment base 0..15 */
247	.byte	0x0	/* segment base 16..23; set for 0K */
248	.byte	0x9f	/* flags; Type	*/
249	.byte	0xcf	/* flags; Limit	*/
250	.byte	0x0	/* segment base 24..32 */
251
252kerneldata:		/* offset = 0x10 */
253
254	.word	0xffff	/* segment limit 0..15 */
255	.word	0x0000	/* segment base 0..15 */
256	.byte	0x0	/* segment base 16..23; set for 0k */
257	.byte	0x93	/* flags; Type  */
258	.byte	0xcf	/* flags; Limit */
259	.byte	0x0	/* segment base 24..32 */
260
261bootcode:		/* offset = 0x18 */
262
263	.word	0xffff	/* segment limit 0..15 */
264bootCodeSeg:		/* this will be modified by mpInstallTramp() */
265	.word	0x0000	/* segment base 0..15 */
266	.byte	0x00	/* segment base 16...23; set for 0x000xx000 */
267	.byte	0x9e	/* flags; Type  */
268	.byte	0xcf	/* flags; Limit */
269	.byte	0x0	/*segment base 24..32 */
270
271bootdata:		/* offset = 0x20 */
272
273	.word	0xffff
274bootDataSeg:		/* this will be modified by mpInstallTramp() */
275	.word	0x0000	/* segment base 0..15 */
276	.byte	0x00	/* segment base 16...23; set for 0x000xx000 */
277	.byte	0x92
278	.byte	0xcf
279	.byte	0x0
280
281/*
282 * GDT pointer for the lgdt call
283 */
284	.globl	mp_gdtbase
285
286MP_GDTptr:
287mp_gdtlimit:
288	.word	0x0028
289mp_gdtbase:		/* this will be modified by mpInstallTramp() */
290	.long	0
291
292	.space	0x100	/* space for boot_stk - 1st temporary stack */
293boot_stk:
294
295BOOTMP2:
296	.globl	bootMP_size
297bootMP_size:
298	.long	BOOTMP2 - BOOTMP1
299