]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/i386/i386/mpboot.s
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / 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