mpboot.S revision 38888
1193323Sed/* 2193323Sed * Copyright (c) 1995, Jack F. Vogel 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12251662Sdim * documentation and/or other materials provided with the distribution. 13198090Srdivacky * 3. All advertising materials mentioning features or use of this software 14193323Sed * must display the following acknowledgement: 15193323Sed * This product includes software developed by Jack F. Vogel 16193323Sed * 4. The name of the developer may be used to endorse or promote products 17193323Sed * derived from this software without specific prior written permission. 18193323Sed * 19193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21263508Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22249423Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23198090Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25249423Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29193323Sed * SUCH DAMAGE. 30204792Srdivacky * 31204792Srdivacky * mpboot.s: FreeBSD machine support for the Intel MP Spec 32204792Srdivacky * multiprocessor systems. 33249423Sdim * 34198090Srdivacky * $Id: mpboot.s,v 1.6 1997/10/10 09:44:05 peter Exp $ 35193323Sed */ 36193323Sed 37193323Sed#include "opt_vm86.h" 38193323Sed 39204792Srdivacky#include <machine/asmacros.h> /* miscellaneous asm macros */ 40193323Sed#include <machine/apic.h> 41#include <machine/specialreg.h> 42 43#include "assym.s" 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) 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 movl _bootPTD-KERNBASE, %eax 80 movl %eax,%cr3 81 movl %cr0,%eax 82 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 83 movl %eax,%cr0 /* let the games begin! */ 84 movl $_idlestack_top,%esp /* boot stack end loc. */ 85 86 pushl $mp_begin /* jump to high mem */ 87 ret 88 89 /* 90 * Wait for the booting CPU to signal startup 91 */ 92mp_begin: /* now running relocated at KERNBASE */ 93 CHECKPOINT(0x37, 4) 94 call _init_secondary /* load i386 tables */ 95 CHECKPOINT(0x38, 5) 96 97#ifdef VM86 98 /* 99 * If the [BSP] CPU has support for VME, turn it on. 100 */ 101 testl $CPUID_VME, _cpu_feature /* XXX WRONG! BSP! */ 102 jz 1f 103 movl %cr4, %eax 104 orl $CR4_VME, %eax 105 movl %eax, %cr4 1061: 107#endif 108 109 /* disable the APIC, just to be SURE */ 110 movl lapic_svr, %eax /* get spurious vector reg. */ 111 andl $~APIC_SVR_SWEN, %eax /* clear software enable bit */ 112 movl %eax, lapic_svr 113 114 /* signal our startup to the BSP */ 115 movl lapic_ver, %eax /* our version reg contents */ 116 movl %eax, _cpu_apic_versions /* into [ 0 ] */ 117 incl _mp_ncpus /* signal BSP */ 118 119 CHECKPOINT(0x39, 6) 120 121 /* wait till we can get into the kernel */ 122 call _boot_get_mplock 123 124 /* Now, let's prepare for some REAL WORK :-) */ 125 call _ap_init 126 127 call _rel_mplock 1282: 129 cmpl $0, CNAME(smp_started) /* Wait for last AP to be ready */ 130 jz 2b 131 call _get_mplock 132 133 /* let her rip! (loads new stack) */ 134 jmp _cpu_switch 135 136/* 137 * This is the embedded trampoline or bootstrap that is 138 * copied into 'real-mode' low memory, it is where the 139 * secondary processor "wakes up". When it is executed 140 * the processor will eventually jump into the routine 141 * MPentry, which resides in normal kernel text above 142 * 1Meg. -jackv 143 */ 144 145#define data32 .byte 0x66 146#define addr32 .byte 0x67 147 148 .data 149 ALIGN_DATA /* just to be sure */ 150 151BOOTMP1: 152 153NON_GPROF_ENTRY(bootMP) 154 cli 155 CHECKPOINT(0x34, 1) 156 /* First guarantee a 'clean slate' */ 157 data32 158 xorl %eax, %eax 159 data32 160 movl %eax, %ebx 161 data32 162 movl %eax, %ecx 163 data32 164 movl %eax, %edx 165 data32 166 movl %eax, %esi 167 data32 168 movl %eax, %edi 169 170 /* set up data segments */ 171 mov %cs, %ax 172 mov %ax, %ds 173 mov %ax, %es 174 mov %ax, %fs 175 mov %ax, %gs 176 mov %ax, %ss 177 mov $(boot_stk-_bootMP), %sp 178 179 /* Now load the global descriptor table */ 180 addr32 181 data32 182 /* XXX: sigh: lgdt MP_GDTptr-_bootMP GAS BUG! */ 183 .byte 0x0f, 0x01, 0x15 /* XXX hand assemble! */ 184 .long MP_GDTptr-_bootMP /* XXX hand assemble! */ 185 186 /* Enable protected mode */ 187 data32 188 movl %cr0, %eax 189 data32 190 orl $CR0_PE, %eax 191 data32 192 movl %eax, %cr0 193 194 /* 195 * make intrasegment jump to flush the processor pipeline and 196 * reload CS register 197 */ 198 data32 199 pushl $0x18 200 data32 201 pushl $(protmode-_bootMP) 202 data32 203 lret 204 205protmode: 206 CHECKPOINT(0x35, 2) 207 208 /* 209 * we are NOW running for the first time with %eip 210 * having the full physical address, BUT we still 211 * are using a segment descriptor with the origin 212 * not matching the booting kernel. 213 * 214 * SO NOW... for the BIG Jump into kernel's segment 215 * and physical text above 1 Meg. 216 */ 217 mov $0x10, %ebx 218 movw %bx, %ds 219 movw %bx, %es 220 movw %bx, %fs 221 movw %bx, %gs 222 movw %bx, %ss 223 224 .globl _bigJump 225_bigJump: 226 /* this will be modified by mpInstallTramp() */ 227 ljmp $0x08, $0 /* far jmp to MPentry() */ 228 229dead: hlt /* We should never get here */ 230 jmp dead 231 232/* 233 * MP boot strap Global Descriptor Table 234 */ 235 .p2align 4 236 .globl _MP_GDT 237 .globl _bootCodeSeg 238 .globl _bootDataSeg 239_MP_GDT: 240 241nulldesc: /* offset = 0x0 */ 242 243 .word 0x0 244 .word 0x0 245 .byte 0x0 246 .byte 0x0 247 .byte 0x0 248 .byte 0x0 249 250kernelcode: /* offset = 0x08 */ 251 252 .word 0xffff /* segment limit 0..15 */ 253 .word 0x0000 /* segment base 0..15 */ 254 .byte 0x0 /* segment base 16..23; set for 0K */ 255 .byte 0x9f /* flags; Type */ 256 .byte 0xcf /* flags; Limit */ 257 .byte 0x0 /* segment base 24..32 */ 258 259kerneldata: /* offset = 0x10 */ 260 261 .word 0xffff /* segment limit 0..15 */ 262 .word 0x0000 /* segment base 0..15 */ 263 .byte 0x0 /* segment base 16..23; set for 0k */ 264 .byte 0x93 /* flags; Type */ 265 .byte 0xcf /* flags; Limit */ 266 .byte 0x0 /* segment base 24..32 */ 267 268bootcode: /* offset = 0x18 */ 269 270 .word 0xffff /* segment limit 0..15 */ 271_bootCodeSeg: /* this will be modified by mpInstallTramp() */ 272 .word 0x0000 /* segment base 0..15 */ 273 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 274 .byte 0x9e /* flags; Type */ 275 .byte 0xcf /* flags; Limit */ 276 .byte 0x0 /*segment base 24..32 */ 277 278bootdata: /* offset = 0x20 */ 279 280 .word 0xffff 281_bootDataSeg: /* this will be modified by mpInstallTramp() */ 282 .word 0x0000 /* segment base 0..15 */ 283 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 284 .byte 0x92 285 .byte 0xcf 286 .byte 0x0 287 288/* 289 * GDT pointer for the lgdt call 290 */ 291 .globl _mp_gdtbase 292 293MP_GDTptr: 294_mp_gdtlimit: 295 .word 0x0028 296_mp_gdtbase: /* this will be modified by mpInstallTramp() */ 297 .long 0 298 299 .space 0x100 /* space for boot_stk - 1st temporary stack */ 300boot_stk: 301 302BOOTMP2: 303 .globl _bootMP_size 304_bootMP_size: 305 .long BOOTMP2 - BOOTMP1 306