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