]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/mpboot.s
add <sys/sytm.h> (for cpufunc.h -> rdtsc)
[FreeBSD/FreeBSD.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 <machine/asmacros.h>           /* miscellaneous asm macros */
38 #include <machine/apic.h>
39 #include <machine/specialreg.h>
40
41 #include "assym.s"
42
43 /*
44  * this code MUST be enabled here and in mp_machdep.c
45  * it follows the very early stages of AP boot by placing values in CMOS ram.
46  * it NORMALLY will never be needed and thus the primitive method for enabling.
47  *
48 #define CHECK_POINTS
49  */
50
51 #if defined(CHECK_POINTS) && !defined(PC98)
52
53 #define CMOS_REG        (0x70)
54 #define CMOS_DATA       (0x71)
55
56 #define CHECKPOINT(A,D)         \
57         movb    $(A),%al ;      \
58         outb    %al,$CMOS_REG ; \
59         movb    $(D),%al ;      \
60         outb    %al,$CMOS_DATA
61
62 #else
63
64 #define CHECKPOINT(A,D)
65
66 #endif /* CHECK_POINTS */
67
68
69 /*
70  * the APs enter here from their trampoline code (bootMP, below)
71  */
72         .p2align 4
73
74 NON_GPROF_ENTRY(MPentry)
75         CHECKPOINT(0x36, 3)
76         /* Now enable paging mode */
77         movl    IdlePTD-KERNBASE, %eax
78         movl    %eax,%cr3       
79         movl    %cr0,%eax
80         orl     $CR0_PE|CR0_PG,%eax             /* enable paging */
81         movl    %eax,%cr0                       /* let the games begin! */
82         movl    bootSTK,%esp                    /* boot stack end loc. */
83
84         pushl   $mp_begin                       /* jump to high mem */
85         ret
86
87         /*
88          * Wait for the booting CPU to signal startup
89          */
90 mp_begin:       /* now running relocated at KERNBASE */
91         CHECKPOINT(0x37, 4)
92         call    init_secondary                  /* load i386 tables */
93         CHECKPOINT(0x38, 5)
94
95         /*
96          * If the [BSP] CPU has support for VME, turn it on.
97          */
98         testl   $CPUID_VME, cpu_feature         /* XXX WRONG! BSP! */
99         jz      1f
100         movl    %cr4, %eax
101         orl     $CR4_VME, %eax
102         movl    %eax, %cr4
103 1:
104
105         /* disable the APIC, just to be SURE */
106         movl    lapic+LA_SVR, %eax              /* get spurious vector reg. */
107         andl    $~APIC_SVR_SWEN, %eax           /* clear software enable bit */
108         movl    %eax, lapic+LA_SVR
109
110         /* signal our startup to the BSP */
111         movl    lapic+LA_VER, %eax              /* our version reg contents */
112         movl    %eax, cpu_apic_versions         /* into [ 0 ] */
113         incl    mp_ncpus                        /* signal BSP */
114
115         CHECKPOINT(0x39, 6)
116
117         /* Now, let's prepare for some REAL WORK :-)  This doesn't return. */
118         call    ap_init
119
120 /*
121  * This is the embedded trampoline or bootstrap that is
122  * copied into 'real-mode' low memory, it is where the
123  * secondary processor "wakes up". When it is executed
124  * the processor will eventually jump into the routine
125  * MPentry, which resides in normal kernel text above
126  * 1Meg.                -jackv
127  */
128
129         .data
130         ALIGN_DATA                              /* just to be sure */
131
132 BOOTMP1:
133
134 NON_GPROF_ENTRY(bootMP)
135         .code16         
136         cli
137         CHECKPOINT(0x34, 1)
138         /* First guarantee a 'clean slate' */
139         xorl    %eax, %eax
140         movl    %eax, %ebx
141         movl    %eax, %ecx
142         movl    %eax, %edx
143         movl    %eax, %esi
144         movl    %eax, %edi
145
146         /* set up data segments */
147         mov     %cs, %ax
148         mov     %ax, %ds
149         mov     %ax, %es
150         mov     %ax, %fs
151         mov     %ax, %gs
152         mov     %ax, %ss
153         mov     $(boot_stk-bootMP), %esp
154
155         /* Now load the global descriptor table */
156         lgdt    MP_GDTptr-bootMP
157
158         /* Enable protected mode */
159         movl    %cr0, %eax
160         orl     $CR0_PE, %eax
161         movl    %eax, %cr0 
162
163         /*
164          * make intrasegment jump to flush the processor pipeline and
165          * reload CS register
166          */
167         pushl   $0x18
168         pushl   $(protmode-bootMP)
169         lretl
170
171        .code32          
172 protmode:
173         CHECKPOINT(0x35, 2)
174
175         /*
176          * we are NOW running for the first time with %eip
177          * having the full physical address, BUT we still
178          * are using a segment descriptor with the origin
179          * not matching the booting kernel.
180          *
181          * SO NOW... for the BIG Jump into kernel's segment
182          * and physical text above 1 Meg.
183          */
184         mov     $0x10, %ebx
185         movw    %bx, %ds
186         movw    %bx, %es
187         movw    %bx, %fs
188         movw    %bx, %gs
189         movw    %bx, %ss
190
191         .globl  bigJump
192 bigJump:
193         /* this will be modified by mpInstallTramp() */
194         ljmp    $0x08, $0                       /* far jmp to MPentry() */
195         
196 dead:   hlt /* We should never get here */
197         jmp     dead
198
199 /*
200  * MP boot strap Global Descriptor Table
201  */
202         .p2align 4
203         .globl  MP_GDT
204         .globl  bootCodeSeg
205         .globl  bootDataSeg
206 MP_GDT:
207
208 nulldesc:               /* offset = 0x0 */
209
210         .word   0x0     
211         .word   0x0     
212         .byte   0x0     
213         .byte   0x0     
214         .byte   0x0     
215         .byte   0x0     
216
217 kernelcode:             /* offset = 0x08 */
218
219         .word   0xffff  /* segment limit 0..15 */
220         .word   0x0000  /* segment base 0..15 */
221         .byte   0x0     /* segment base 16..23; set for 0K */
222         .byte   0x9f    /* flags; Type  */
223         .byte   0xcf    /* flags; Limit */
224         .byte   0x0     /* segment base 24..32 */
225
226 kerneldata:             /* offset = 0x10 */
227
228         .word   0xffff  /* segment limit 0..15 */
229         .word   0x0000  /* segment base 0..15 */
230         .byte   0x0     /* segment base 16..23; set for 0k */
231         .byte   0x93    /* flags; Type  */
232         .byte   0xcf    /* flags; Limit */
233         .byte   0x0     /* segment base 24..32 */
234
235 bootcode:               /* offset = 0x18 */
236
237         .word   0xffff  /* segment limit 0..15 */
238 bootCodeSeg:            /* this will be modified by mpInstallTramp() */
239         .word   0x0000  /* segment base 0..15 */
240         .byte   0x00    /* segment base 16...23; set for 0x000xx000 */
241         .byte   0x9e    /* flags; Type  */
242         .byte   0xcf    /* flags; Limit */
243         .byte   0x0     /*segment base 24..32 */
244
245 bootdata:               /* offset = 0x20 */
246
247         .word   0xffff  
248 bootDataSeg:            /* this will be modified by mpInstallTramp() */
249         .word   0x0000  /* segment base 0..15 */
250         .byte   0x00    /* segment base 16...23; set for 0x000xx000 */
251         .byte   0x92    
252         .byte   0xcf    
253         .byte   0x0             
254
255 /*
256  * GDT pointer for the lgdt call
257  */
258         .globl  mp_gdtbase
259
260 MP_GDTptr:      
261 mp_gdtlimit:
262         .word   0x0028          
263 mp_gdtbase:             /* this will be modified by mpInstallTramp() */
264         .long   0
265
266         .space  0x100   /* space for boot_stk - 1st temporary stack */
267 boot_stk:
268
269 BOOTMP2:
270         .globl  bootMP_size
271 bootMP_size:
272         .long   BOOTMP2 - BOOTMP1