xref: /freebsd/sys/i386/i386/mpboot.S (revision 95ee2897)
1ccd9b49fSElliott Mitchell/*-
2ccd9b49fSElliott Mitchell * Copyright (c) 1995 Jack F. Vogel
3ccd9b49fSElliott Mitchell * All rights reserved.
4ccd9b49fSElliott Mitchell *
5ccd9b49fSElliott Mitchell * Redistribution and use in source and binary forms, with or without
6ccd9b49fSElliott Mitchell * modification, are permitted provided that the following conditions
7ccd9b49fSElliott Mitchell * are met:
8ccd9b49fSElliott Mitchell * 1. Redistributions of source code must retain the above copyright
9ccd9b49fSElliott Mitchell *    notice, this list of conditions and the following disclaimer.
10ccd9b49fSElliott Mitchell * 2. Redistributions in binary form must reproduce the above copyright
11ccd9b49fSElliott Mitchell *    notice, this list of conditions and the following disclaimer in the
12ccd9b49fSElliott Mitchell *    documentation and/or other materials provided with the distribution.
13ccd9b49fSElliott Mitchell *
14ccd9b49fSElliott Mitchell * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ccd9b49fSElliott Mitchell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ccd9b49fSElliott Mitchell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ccd9b49fSElliott Mitchell * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18ccd9b49fSElliott Mitchell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ccd9b49fSElliott Mitchell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ccd9b49fSElliott Mitchell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ccd9b49fSElliott Mitchell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ccd9b49fSElliott Mitchell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ccd9b49fSElliott Mitchell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ccd9b49fSElliott Mitchell * SUCH DAMAGE.
25ccd9b49fSElliott Mitchell *
26ccd9b49fSElliott Mitchell * mpboot.s:	FreeBSD machine support for the Intel MP Spec
27ccd9b49fSElliott Mitchell *		multiprocessor systems.
28ccd9b49fSElliott Mitchell */
29ccd9b49fSElliott Mitchell
30ccd9b49fSElliott Mitchell#include "opt_pmap.h"
31ccd9b49fSElliott Mitchell
32ccd9b49fSElliott Mitchell#include <machine/asmacros.h>		/* miscellaneous asm macros */
33ccd9b49fSElliott Mitchell#include <x86/apicreg.h>
34ccd9b49fSElliott Mitchell#include <machine/specialreg.h>
35ccd9b49fSElliott Mitchell
36ccd9b49fSElliott Mitchell#include "assym.inc"
37ccd9b49fSElliott Mitchell
38ccd9b49fSElliott Mitchell/*
39ccd9b49fSElliott Mitchell * this code MUST be enabled here and in mp_machdep.c
40ccd9b49fSElliott Mitchell * it follows the very early stages of AP boot by placing values in CMOS ram.
41ccd9b49fSElliott Mitchell * it NORMALLY will never be needed and thus the primitive method for enabling.
42ccd9b49fSElliott Mitchell *
43ccd9b49fSElliott Mitchell#define CHECK_POINTS
44ccd9b49fSElliott Mitchell */
45ccd9b49fSElliott Mitchell
46ccd9b49fSElliott Mitchell#if defined(CHECK_POINTS)
47ccd9b49fSElliott Mitchell
48ccd9b49fSElliott Mitchell#define CMOS_REG	(0x70)
49ccd9b49fSElliott Mitchell#define CMOS_DATA	(0x71)
50ccd9b49fSElliott Mitchell
51ccd9b49fSElliott Mitchell#define CHECKPOINT(A,D)		\
52ccd9b49fSElliott Mitchell	movb	$(A),%al ;	\
53ccd9b49fSElliott Mitchell	outb	%al,$CMOS_REG ;	\
54ccd9b49fSElliott Mitchell	movb	$(D),%al ;	\
55ccd9b49fSElliott Mitchell	outb	%al,$CMOS_DATA
56ccd9b49fSElliott Mitchell
57ccd9b49fSElliott Mitchell#else
58ccd9b49fSElliott Mitchell
59ccd9b49fSElliott Mitchell#define CHECKPOINT(A,D)
60ccd9b49fSElliott Mitchell
61ccd9b49fSElliott Mitchell#endif /* CHECK_POINTS */
62ccd9b49fSElliott Mitchell
63ccd9b49fSElliott Mitchell
64ccd9b49fSElliott Mitchell/*
65ccd9b49fSElliott Mitchell * the APs enter here from their trampoline code (bootMP, below)
66ccd9b49fSElliott Mitchell */
67ccd9b49fSElliott Mitchell	.p2align 4
68ccd9b49fSElliott Mitchell
69ccd9b49fSElliott MitchellENTRY(MPentry)
70ccd9b49fSElliott Mitchell	CHECKPOINT(0x36, 3)
71ccd9b49fSElliott Mitchell	/*
72ccd9b49fSElliott Mitchell	 * Enable features on this processor.  We don't support SMP on
73ccd9b49fSElliott Mitchell	 * CPUs older than a Pentium, so we know that we can use the cpuid
74ccd9b49fSElliott Mitchell	 * instruction.
75ccd9b49fSElliott Mitchell	 */
76ccd9b49fSElliott Mitchell	movl	$1,%eax
77ccd9b49fSElliott Mitchell	cpuid					/* Retrieve features */
78ccd9b49fSElliott Mitchell	movl	%cr4,%eax
79ccd9b49fSElliott Mitchell	testl	$CPUID_PSE,%edx
80ccd9b49fSElliott Mitchell	jz 1f
81ccd9b49fSElliott Mitchell	orl	$CR4_PSE,%eax			/* Enable PSE  */
82ccd9b49fSElliott Mitchell1:	testl	$CPUID_PGE,%edx
83ccd9b49fSElliott Mitchell	jz 2f
84ccd9b49fSElliott Mitchell	orl	$CR4_PGE,%eax			/* Enable PGE  */
85ccd9b49fSElliott Mitchell2:	testl	$CPUID_VME,%edx
86ccd9b49fSElliott Mitchell	jz 3f
87ccd9b49fSElliott Mitchell	orl	$CR4_VME,%eax			/* Enable VME  */
88ccd9b49fSElliott Mitchell3:	movl	%eax,%cr4
89ccd9b49fSElliott Mitchell
90ccd9b49fSElliott Mitchell	/* Now enable paging mode */
91ccd9b49fSElliott Mitchell	cmpl	$0, pae_mode
92ccd9b49fSElliott Mitchell	je	4f
93ccd9b49fSElliott Mitchell	movl	IdlePDPT, %eax
94ccd9b49fSElliott Mitchell	movl	%eax, %cr3
95ccd9b49fSElliott Mitchell	movl	%cr4, %eax
96ccd9b49fSElliott Mitchell	orl	$CR4_PAE, %eax
97ccd9b49fSElliott Mitchell	movl	%eax, %cr4
98ccd9b49fSElliott Mitchell	movl	$0x80000000, %eax
99ccd9b49fSElliott Mitchell	cpuid
100ccd9b49fSElliott Mitchell	movl	$0x80000001, %ebx
101ccd9b49fSElliott Mitchell	cmpl	%ebx, %eax
102ccd9b49fSElliott Mitchell	jb	5f
103ccd9b49fSElliott Mitchell	movl	%ebx, %eax
104ccd9b49fSElliott Mitchell	cpuid
105ccd9b49fSElliott Mitchell	testl	$AMDID_NX, %edx
106ccd9b49fSElliott Mitchell	je	5f
107ccd9b49fSElliott Mitchell	movl	$MSR_EFER, %ecx
108ccd9b49fSElliott Mitchell	rdmsr
109ccd9b49fSElliott Mitchell	orl	$EFER_NXE,%eax
110ccd9b49fSElliott Mitchell	wrmsr
111ccd9b49fSElliott Mitchell	jmp	5f
112ccd9b49fSElliott Mitchell4:	movl	IdlePTD_nopae, %eax
113ccd9b49fSElliott Mitchell	movl	%eax,%cr3
114ccd9b49fSElliott Mitchell5:	movl	%cr0,%eax
115ccd9b49fSElliott Mitchell	orl	$CR0_PE|CR0_PG,%eax		/* enable paging */
116ccd9b49fSElliott Mitchell	movl	%eax,%cr0			/* let the games begin! */
117ccd9b49fSElliott Mitchell	movl	bootSTK,%esp			/* boot stack end loc. */
118ccd9b49fSElliott Mitchell
119ccd9b49fSElliott Mitchell	pushl	$mp_begin			/* jump to high mem */
120ccd9b49fSElliott Mitchell	ret
121ccd9b49fSElliott Mitchell
122ccd9b49fSElliott Mitchell	/*
123ccd9b49fSElliott Mitchell	 * Wait for the booting CPU to signal startup
124ccd9b49fSElliott Mitchell	 */
125ccd9b49fSElliott Mitchellmp_begin:	/* now running relocated at KERNBASE */
126ccd9b49fSElliott Mitchell	CHECKPOINT(0x37, 4)
127ccd9b49fSElliott Mitchell	call	init_secondary			/* load i386 tables */
128ccd9b49fSElliott Mitchell
129ccd9b49fSElliott Mitchell/*
130ccd9b49fSElliott Mitchell * This is the embedded trampoline or bootstrap that is
131ccd9b49fSElliott Mitchell * copied into 'real-mode' low memory, it is where the
132ccd9b49fSElliott Mitchell * secondary processor "wakes up". When it is executed
133ccd9b49fSElliott Mitchell * the processor will eventually jump into the routine
134ccd9b49fSElliott Mitchell * MPentry, which resides in normal kernel text above
135ccd9b49fSElliott Mitchell * 1Meg.		-jackv
136ccd9b49fSElliott Mitchell */
137ccd9b49fSElliott Mitchell
138ccd9b49fSElliott Mitchell	.data
139ccd9b49fSElliott Mitchell	ALIGN_DATA				/* just to be sure */
140ccd9b49fSElliott Mitchell
141ccd9b49fSElliott MitchellBOOTMP1:
142ccd9b49fSElliott Mitchell
143ccd9b49fSElliott MitchellENTRY(bootMP)
144ccd9b49fSElliott Mitchell	.code16
145ccd9b49fSElliott Mitchell	cli
146ccd9b49fSElliott Mitchell	CHECKPOINT(0x34, 1)
147ccd9b49fSElliott Mitchell	/* First guarantee a 'clean slate' */
148ccd9b49fSElliott Mitchell	xorl	%eax, %eax
149ccd9b49fSElliott Mitchell	movl	%eax, %ebx
150ccd9b49fSElliott Mitchell	movl	%eax, %ecx
151ccd9b49fSElliott Mitchell 	movl	%eax, %edx
152ccd9b49fSElliott Mitchell	movl	%eax, %esi
153ccd9b49fSElliott Mitchell	movl	%eax, %edi
154ccd9b49fSElliott Mitchell
155ccd9b49fSElliott Mitchell	/* set up data segments */
156ccd9b49fSElliott Mitchell	mov	%cs, %ax
157ccd9b49fSElliott Mitchell	mov	%ax, %ds
158ccd9b49fSElliott Mitchell	mov	%ax, %es
159ccd9b49fSElliott Mitchell	mov	%ax, %fs
160ccd9b49fSElliott Mitchell	mov	%ax, %gs
161ccd9b49fSElliott Mitchell	mov	%ax, %ss
162ccd9b49fSElliott Mitchell	mov	$(boot_stk-bootMP), %esp
163ccd9b49fSElliott Mitchell
164ccd9b49fSElliott Mitchell	/* Now load the global descriptor table */
165ccd9b49fSElliott Mitchell	lgdt	MP_GDTptr-bootMP
166ccd9b49fSElliott Mitchell
167ccd9b49fSElliott Mitchell	/* Enable protected mode */
168ccd9b49fSElliott Mitchell	movl	%cr0, %eax
169ccd9b49fSElliott Mitchell	orl	$CR0_PE, %eax
170ccd9b49fSElliott Mitchell	movl	%eax, %cr0
171ccd9b49fSElliott Mitchell
172ccd9b49fSElliott Mitchell	/*
173ccd9b49fSElliott Mitchell	 * make intrasegment jump to flush the processor pipeline and
174ccd9b49fSElliott Mitchell	 * reload CS register
175ccd9b49fSElliott Mitchell	 */
176ccd9b49fSElliott Mitchell	pushl	$0x18
177ccd9b49fSElliott Mitchell	pushl	$(protmode-bootMP)
178ccd9b49fSElliott Mitchell	lretl
179ccd9b49fSElliott Mitchell
180ccd9b49fSElliott Mitchell       .code32
181ccd9b49fSElliott Mitchellprotmode:
182ccd9b49fSElliott Mitchell	CHECKPOINT(0x35, 2)
183ccd9b49fSElliott Mitchell
184ccd9b49fSElliott Mitchell	/*
185ccd9b49fSElliott Mitchell	 * we are NOW running for the first time with %eip
186ccd9b49fSElliott Mitchell	 * having the full physical address, BUT we still
187ccd9b49fSElliott Mitchell	 * are using a segment descriptor with the origin
188ccd9b49fSElliott Mitchell	 * not matching the booting kernel.
189ccd9b49fSElliott Mitchell	 *
190ccd9b49fSElliott Mitchell 	 * SO NOW... for the BIG Jump into kernel's segment
191ccd9b49fSElliott Mitchell	 * and physical text above 1 Meg.
192ccd9b49fSElliott Mitchell	 */
193ccd9b49fSElliott Mitchell	mov	$0x10, %ebx
194ccd9b49fSElliott Mitchell	movw	%bx, %ds
195ccd9b49fSElliott Mitchell	movw	%bx, %es
196ccd9b49fSElliott Mitchell	movw	%bx, %fs
197ccd9b49fSElliott Mitchell	movw	%bx, %gs
198ccd9b49fSElliott Mitchell	movw	%bx, %ss
199ccd9b49fSElliott Mitchell
200ccd9b49fSElliott Mitchell	.globl	bigJump
201ccd9b49fSElliott MitchellbigJump:
202ccd9b49fSElliott Mitchell	/* this will be modified by mpInstallTramp() */
203ccd9b49fSElliott Mitchell	ljmp	$0x08, $0			/* far jmp to MPentry() */
204ccd9b49fSElliott Mitchell
205ccd9b49fSElliott Mitchelldead:	hlt /* We should never get here */
206ccd9b49fSElliott Mitchell	jmp	dead
207ccd9b49fSElliott Mitchell
208ccd9b49fSElliott Mitchell/*
209ccd9b49fSElliott Mitchell * MP boot strap Global Descriptor Table
210ccd9b49fSElliott Mitchell */
211ccd9b49fSElliott Mitchell	.p2align 4
212ccd9b49fSElliott Mitchell	.globl	MP_GDT
213ccd9b49fSElliott Mitchell	.globl	bootCodeSeg
214ccd9b49fSElliott Mitchell	.globl	bootDataSeg
215ccd9b49fSElliott MitchellMP_GDT:
216ccd9b49fSElliott Mitchell
217ccd9b49fSElliott Mitchellnulldesc:		/* offset = 0x0 */
218ccd9b49fSElliott Mitchell
219ccd9b49fSElliott Mitchell	.word	0x0
220ccd9b49fSElliott Mitchell	.word	0x0
221ccd9b49fSElliott Mitchell	.byte	0x0
222ccd9b49fSElliott Mitchell	.byte	0x0
223ccd9b49fSElliott Mitchell	.byte	0x0
224ccd9b49fSElliott Mitchell	.byte	0x0
225ccd9b49fSElliott Mitchell
226ccd9b49fSElliott Mitchellkernelcode:		/* offset = 0x08 */
227ccd9b49fSElliott Mitchell
228ccd9b49fSElliott Mitchell	.word	0xffff	/* segment limit 0..15 */
229ccd9b49fSElliott Mitchell	.word	0x0000	/* segment base 0..15 */
230ccd9b49fSElliott Mitchell	.byte	0x0	/* segment base 16..23; set for 0K */
231ccd9b49fSElliott Mitchell	.byte	0x9f	/* flags; Type	*/
232ccd9b49fSElliott Mitchell	.byte	0xcf	/* flags; Limit	*/
233ccd9b49fSElliott Mitchell	.byte	0x0	/* segment base 24..32 */
234ccd9b49fSElliott Mitchell
235ccd9b49fSElliott Mitchellkerneldata:		/* offset = 0x10 */
236ccd9b49fSElliott Mitchell
237ccd9b49fSElliott Mitchell	.word	0xffff	/* segment limit 0..15 */
238ccd9b49fSElliott Mitchell	.word	0x0000	/* segment base 0..15 */
239ccd9b49fSElliott Mitchell	.byte	0x0	/* segment base 16..23; set for 0k */
240ccd9b49fSElliott Mitchell	.byte	0x93	/* flags; Type  */
241ccd9b49fSElliott Mitchell	.byte	0xcf	/* flags; Limit */
242ccd9b49fSElliott Mitchell	.byte	0x0	/* segment base 24..32 */
243ccd9b49fSElliott Mitchell
244ccd9b49fSElliott Mitchellbootcode:		/* offset = 0x18 */
245ccd9b49fSElliott Mitchell
246ccd9b49fSElliott Mitchell	.word	0xffff	/* segment limit 0..15 */
247ccd9b49fSElliott MitchellbootCodeSeg:		/* this will be modified by mpInstallTramp() */
248ccd9b49fSElliott Mitchell	.word	0x0000	/* segment base 0..15 */
249ccd9b49fSElliott Mitchell	.byte	0x00	/* segment base 16...23; set for 0x000xx000 */
250ccd9b49fSElliott Mitchell	.byte	0x9e	/* flags; Type  */
251ccd9b49fSElliott Mitchell	.byte	0xcf	/* flags; Limit */
252ccd9b49fSElliott Mitchell	.byte	0x0	/*segment base 24..32 */
253ccd9b49fSElliott Mitchell
254ccd9b49fSElliott Mitchellbootdata:		/* offset = 0x20 */
255ccd9b49fSElliott Mitchell
256ccd9b49fSElliott Mitchell	.word	0xffff
257ccd9b49fSElliott MitchellbootDataSeg:		/* this will be modified by mpInstallTramp() */
258ccd9b49fSElliott Mitchell	.word	0x0000	/* segment base 0..15 */
259ccd9b49fSElliott Mitchell	.byte	0x00	/* segment base 16...23; set for 0x000xx000 */
260ccd9b49fSElliott Mitchell	.byte	0x92
261ccd9b49fSElliott Mitchell	.byte	0xcf
262ccd9b49fSElliott Mitchell	.byte	0x0
263ccd9b49fSElliott Mitchell
264ccd9b49fSElliott Mitchell/*
265ccd9b49fSElliott Mitchell * GDT pointer for the lgdt call
266ccd9b49fSElliott Mitchell */
267ccd9b49fSElliott Mitchell	.globl	mp_gdtbase
268ccd9b49fSElliott Mitchell
269ccd9b49fSElliott MitchellMP_GDTptr:
270ccd9b49fSElliott Mitchellmp_gdtlimit:
271ccd9b49fSElliott Mitchell	.word	0x0028
272ccd9b49fSElliott Mitchellmp_gdtbase:		/* this will be modified by mpInstallTramp() */
273ccd9b49fSElliott Mitchell	.long	0
274ccd9b49fSElliott Mitchell
275ccd9b49fSElliott Mitchell	.space	0x100	/* space for boot_stk - 1st temporary stack */
276ccd9b49fSElliott Mitchellboot_stk:
277ccd9b49fSElliott Mitchell
278ccd9b49fSElliott MitchellBOOTMP2:
279ccd9b49fSElliott Mitchell	.globl	bootMP_size
280ccd9b49fSElliott MitchellbootMP_size:
281ccd9b49fSElliott Mitchell	.long	BOOTMP2 - BOOTMP1
282