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