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