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