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