mpboot.S revision 121996
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 121996 2003-11-03 22:32:04Z jhb $ 35 */ 36 37#include "opt_pmap.h" 38 39#include <machine/asmacros.h> /* miscellaneous asm macros */ 40#include <machine/apicreg.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 /* 81 * Enable features on this processor. We don't support SMP on 82 * CPUs older than a Pentium, so we know that we can use the cpuid 83 * instruction. 84 */ 85 movl $1,%eax 86 cpuid /* Retrieve features */ 87 movl %cr4,%eax 88#ifndef DISABLE_PSE 89 testl $CPUID_PSE,%edx 90 jz 1f 91 orl $CR4_PSE,%eax /* Enable PSE */ 921: 93#endif 94#ifndef DISABLE_PG_G 95 testl $CPUID_PGE,%edx 96 jz 1f 97 orl $CR4_PGE,%eax /* Enable PGE */ 981: 99#endif 100 testl $CPUID_VME,%edx 101 jz 1f 102 orl $CR4_VME,%eax /* Enable VME */ 1031: 104 movl %eax,%cr4 105 106 /* Now enable paging mode */ 107#ifdef PAE 108 movl R(IdlePDPT), %eax 109 movl %eax, %cr3 110 movl %cr4, %eax 111 orl $CR4_PAE, %eax 112 movl %eax, %cr4 113#else 114 movl R(IdlePTD), %eax 115 movl %eax,%cr3 116#endif 117 movl %cr0,%eax 118 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 119 movl %eax,%cr0 /* let the games begin! */ 120 movl bootSTK,%esp /* boot stack end loc. */ 121 122 pushl $mp_begin /* jump to high mem */ 123 ret 124 125 /* 126 * Wait for the booting CPU to signal startup 127 */ 128mp_begin: /* now running relocated at KERNBASE */ 129 CHECKPOINT(0x37, 4) 130 call init_secondary /* load i386 tables */ 131 132/* 133 * This is the embedded trampoline or bootstrap that is 134 * copied into 'real-mode' low memory, it is where the 135 * secondary processor "wakes up". When it is executed 136 * the processor will eventually jump into the routine 137 * MPentry, which resides in normal kernel text above 138 * 1Meg. -jackv 139 */ 140 141 .data 142 ALIGN_DATA /* just to be sure */ 143 144BOOTMP1: 145 146NON_GPROF_ENTRY(bootMP) 147 .code16 148 cli 149 CHECKPOINT(0x34, 1) 150 /* First guarantee a 'clean slate' */ 151 xorl %eax, %eax 152 movl %eax, %ebx 153 movl %eax, %ecx 154 movl %eax, %edx 155 movl %eax, %esi 156 movl %eax, %edi 157 158 /* set up data segments */ 159 mov %cs, %ax 160 mov %ax, %ds 161 mov %ax, %es 162 mov %ax, %fs 163 mov %ax, %gs 164 mov %ax, %ss 165 mov $(boot_stk-bootMP), %esp 166 167 /* Now load the global descriptor table */ 168 lgdt MP_GDTptr-bootMP 169 170 /* Enable protected mode */ 171 movl %cr0, %eax 172 orl $CR0_PE, %eax 173 movl %eax, %cr0 174 175 /* 176 * make intrasegment jump to flush the processor pipeline and 177 * reload CS register 178 */ 179 pushl $0x18 180 pushl $(protmode-bootMP) 181 lretl 182 183 .code32 184protmode: 185 CHECKPOINT(0x35, 2) 186 187 /* 188 * we are NOW running for the first time with %eip 189 * having the full physical address, BUT we still 190 * are using a segment descriptor with the origin 191 * not matching the booting kernel. 192 * 193 * SO NOW... for the BIG Jump into kernel's segment 194 * and physical text above 1 Meg. 195 */ 196 mov $0x10, %ebx 197 movw %bx, %ds 198 movw %bx, %es 199 movw %bx, %fs 200 movw %bx, %gs 201 movw %bx, %ss 202 203 .globl bigJump 204bigJump: 205 /* this will be modified by mpInstallTramp() */ 206 ljmp $0x08, $0 /* far jmp to MPentry() */ 207 208dead: hlt /* We should never get here */ 209 jmp dead 210 211/* 212 * MP boot strap Global Descriptor Table 213 */ 214 .p2align 4 215 .globl MP_GDT 216 .globl bootCodeSeg 217 .globl bootDataSeg 218MP_GDT: 219 220nulldesc: /* offset = 0x0 */ 221 222 .word 0x0 223 .word 0x0 224 .byte 0x0 225 .byte 0x0 226 .byte 0x0 227 .byte 0x0 228 229kernelcode: /* offset = 0x08 */ 230 231 .word 0xffff /* segment limit 0..15 */ 232 .word 0x0000 /* segment base 0..15 */ 233 .byte 0x0 /* segment base 16..23; set for 0K */ 234 .byte 0x9f /* flags; Type */ 235 .byte 0xcf /* flags; Limit */ 236 .byte 0x0 /* segment base 24..32 */ 237 238kerneldata: /* offset = 0x10 */ 239 240 .word 0xffff /* segment limit 0..15 */ 241 .word 0x0000 /* segment base 0..15 */ 242 .byte 0x0 /* segment base 16..23; set for 0k */ 243 .byte 0x93 /* flags; Type */ 244 .byte 0xcf /* flags; Limit */ 245 .byte 0x0 /* segment base 24..32 */ 246 247bootcode: /* offset = 0x18 */ 248 249 .word 0xffff /* segment limit 0..15 */ 250bootCodeSeg: /* this will be modified by mpInstallTramp() */ 251 .word 0x0000 /* segment base 0..15 */ 252 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 253 .byte 0x9e /* flags; Type */ 254 .byte 0xcf /* flags; Limit */ 255 .byte 0x0 /*segment base 24..32 */ 256 257bootdata: /* offset = 0x20 */ 258 259 .word 0xffff 260bootDataSeg: /* this will be modified by mpInstallTramp() */ 261 .word 0x0000 /* segment base 0..15 */ 262 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 263 .byte 0x92 264 .byte 0xcf 265 .byte 0x0 266 267/* 268 * GDT pointer for the lgdt call 269 */ 270 .globl mp_gdtbase 271 272MP_GDTptr: 273mp_gdtlimit: 274 .word 0x0028 275mp_gdtbase: /* this will be modified by mpInstallTramp() */ 276 .long 0 277 278 .space 0x100 /* space for boot_stk - 1st temporary stack */ 279boot_stk: 280 281BOOTMP2: 282 .globl bootMP_size 283bootMP_size: 284 .long BOOTMP2 - BOOTMP1 285