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