mpboot.S revision 121996
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 121996 2003-11-03 22:32:04Z jhb $
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
78NON_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  */
921:
93#endif
94#ifndef DISABLE_PG_G
95	testl	$CPUID_PGE,%edx
96	jz 1f
97	orl	$CR4_PGE,%eax			/* Enable PGE  */
981:
99#endif
100	testl	$CPUID_VME,%edx
101	jz 1f
102	orl	$CR4_VME,%eax			/* Enable VME  */
1031:
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	 */
128mp_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
144BOOTMP1:
145
146NON_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
184protmode:
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
204bigJump:
205	/* this will be modified by mpInstallTramp() */
206	ljmp	$0x08, $0			/* far jmp to MPentry() */
207
208dead:	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
218MP_GDT:
219
220nulldesc:		/* offset = 0x0 */
221
222	.word	0x0
223	.word	0x0
224	.byte	0x0
225	.byte	0x0
226	.byte	0x0
227	.byte	0x0
228
229kernelcode:		/* 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
238kerneldata:		/* 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
247bootcode:		/* offset = 0x18 */
248
249	.word	0xffff	/* segment limit 0..15 */
250bootCodeSeg:		/* 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
257bootdata:		/* offset = 0x20 */
258
259	.word	0xffff
260bootDataSeg:		/* 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
272MP_GDTptr:
273mp_gdtlimit:
274	.word	0x0028
275mp_gdtbase:		/* this will be modified by mpInstallTramp() */
276	.long	0
277
278	.space	0x100	/* space for boot_stk - 1st temporary stack */
279boot_stk:
280
281BOOTMP2:
282	.globl	bootMP_size
283bootMP_size:
284	.long	BOOTMP2 - BOOTMP1
285