Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / platform / pc32 / 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: src/sys/i386/i386/mpboot.s,v 1.13.2.3 2000/09/07 01:18:26 tegge Exp $
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_svr, %eax                 /* get spurious vector reg. */
107         andl    $~APIC_SVR_SWEN, %eax           /* clear software enable bit */
108         movl    %eax, lapic_svr
109
110         /* signal our startup to the BSP */
111         movl    lapic_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         /* wait till we can get into the kernel */
118         call    _boot_get_mplock
119
120         /* Now, let's prepare for some REAL WORK :-) */
121         call    _ap_init
122
123         call    _rel_mplock
124         wbinvd                          /* Avoid livelock */
125 2:      
126         cmpl    $0, CNAME(smp_started)  /* Wait for last AP to be ready */
127         jz      2b
128         call _get_mplock
129         
130         /* let her rip! (loads new stack) */
131         jmp     _cpu_switch
132
133 NON_GPROF_ENTRY(wait_ap)
134         pushl   %ebp
135         movl    %esp, %ebp
136         call    _rel_mplock
137         wbinvd                          /* Avoid livelock */
138         movl    %eax, 8(%ebp)
139 1:              
140         cmpl    $0, CNAME(smp_started)
141         jnz     2f
142         decl    %eax
143         cmpl    $0, %eax
144         jge     1b
145 2:
146         call    _get_mplock
147         movl    %ebp, %esp
148         popl    %ebp
149         ret
150         
151
152 /*
153  * This is the embedded trampoline or bootstrap that is
154  * copied into 'real-mode' low memory, it is where the
155  * secondary processor "wakes up". When it is executed
156  * the processor will eventually jump into the routine
157  * MPentry, which resides in normal kernel text above
158  * 1Meg.                -jackv
159  */
160
161         .data
162         ALIGN_DATA                              /* just to be sure */
163
164 BOOTMP1:
165
166 NON_GPROF_ENTRY(bootMP)
167         .code16         
168         cli
169         CHECKPOINT(0x34, 1)
170         /* First guarantee a 'clean slate' */
171         xorl    %eax, %eax
172         movl    %eax, %ebx
173         movl    %eax, %ecx
174         movl    %eax, %edx
175         movl    %eax, %esi
176         movl    %eax, %edi
177
178         /* set up data segments */
179         mov     %cs, %ax
180         mov     %ax, %ds
181         mov     %ax, %es
182         mov     %ax, %fs
183         mov     %ax, %gs
184         mov     %ax, %ss
185         mov     $(boot_stk-_bootMP), %esp
186
187         /* Now load the global descriptor table */
188         lgdt    MP_GDTptr-_bootMP
189
190         /* Enable protected mode */
191         movl    %cr0, %eax
192         orl     $CR0_PE, %eax
193         movl    %eax, %cr0 
194
195         /*
196          * make intrasegment jump to flush the processor pipeline and
197          * reload CS register
198          */
199         pushl   $0x18
200         pushl   $(protmode-_bootMP)
201         lretl
202
203        .code32          
204 protmode:
205         CHECKPOINT(0x35, 2)
206
207         /*
208          * we are NOW running for the first time with %eip
209          * having the full physical address, BUT we still
210          * are using a segment descriptor with the origin
211          * not matching the booting kernel.
212          *
213          * SO NOW... for the BIG Jump into kernel's segment
214          * and physical text above 1 Meg.
215          */
216         mov     $0x10, %ebx
217         movw    %bx, %ds
218         movw    %bx, %es
219         movw    %bx, %fs
220         movw    %bx, %gs
221         movw    %bx, %ss
222
223         .globl  _bigJump
224 _bigJump:
225         /* this will be modified by mpInstallTramp() */
226         ljmp    $0x08, $0                       /* far jmp to MPentry() */
227         
228 dead:   hlt /* We should never get here */
229         jmp     dead
230
231 /*
232  * MP boot strap Global Descriptor Table
233  */
234         .p2align 4
235         .globl  _MP_GDT
236         .globl  _bootCodeSeg
237         .globl  _bootDataSeg
238 _MP_GDT:
239
240 nulldesc:               /* offset = 0x0 */
241
242         .word   0x0     
243         .word   0x0     
244         .byte   0x0     
245         .byte   0x0     
246         .byte   0x0     
247         .byte   0x0     
248
249 kernelcode:             /* offset = 0x08 */
250
251         .word   0xffff  /* segment limit 0..15 */
252         .word   0x0000  /* segment base 0..15 */
253         .byte   0x0     /* segment base 16..23; set for 0K */
254         .byte   0x9f    /* flags; Type  */
255         .byte   0xcf    /* flags; Limit */
256         .byte   0x0     /* segment base 24..32 */
257
258 kerneldata:             /* offset = 0x10 */
259
260         .word   0xffff  /* segment limit 0..15 */
261         .word   0x0000  /* segment base 0..15 */
262         .byte   0x0     /* segment base 16..23; set for 0k */
263         .byte   0x93    /* flags; Type  */
264         .byte   0xcf    /* flags; Limit */
265         .byte   0x0     /* segment base 24..32 */
266
267 bootcode:               /* offset = 0x18 */
268
269         .word   0xffff  /* segment limit 0..15 */
270 _bootCodeSeg:           /* this will be modified by mpInstallTramp() */
271         .word   0x0000  /* segment base 0..15 */
272         .byte   0x00    /* segment base 16...23; set for 0x000xx000 */
273         .byte   0x9e    /* flags; Type  */
274         .byte   0xcf    /* flags; Limit */
275         .byte   0x0     /*segment base 24..32 */
276
277 bootdata:               /* offset = 0x20 */
278
279         .word   0xffff  
280 _bootDataSeg:           /* this will be modified by mpInstallTramp() */
281         .word   0x0000  /* segment base 0..15 */
282         .byte   0x00    /* segment base 16...23; set for 0x000xx000 */
283         .byte   0x92    
284         .byte   0xcf    
285         .byte   0x0             
286
287 /*
288  * GDT pointer for the lgdt call
289  */
290         .globl  _mp_gdtbase
291
292 MP_GDTptr:      
293 _mp_gdtlimit:
294         .word   0x0028          
295 _mp_gdtbase:            /* this will be modified by mpInstallTramp() */
296         .long   0
297
298         .space  0x100   /* space for boot_stk - 1st temporary stack */
299 boot_stk:
300
301 BOOTMP2:
302         .globl  _bootMP_size
303 _bootMP_size:
304         .long   BOOTMP2 - BOOTMP1