mpboot.S revision 64325
1102166Stjr/* 2102166Stjr * Copyright (c) 1995, Jack F. Vogel 3102166Stjr * All rights reserved. 4102166Stjr * 5102166Stjr * Redistribution and use in source and binary forms, with or without 6102166Stjr * modification, are permitted provided that the following conditions 7102166Stjr * are met: 8102166Stjr * 1. Redistributions of source code must retain the above copyright 9102166Stjr * notice, this list of conditions and the following disclaimer. 10102166Stjr * 2. Redistributions in binary form must reproduce the above copyright 11102166Stjr * notice, this list of conditions and the following disclaimer in the 12102166Stjr * documentation and/or other materials provided with the distribution. 13102166Stjr * 3. All advertising materials mentioning features or use of this software 14102166Stjr * must display the following acknowledgement: 15102166Stjr * This product includes software developed by Jack F. Vogel 16102166Stjr * 4. The name of the developer may be used to endorse or promote products 17102166Stjr * derived from this software without specific prior written permission. 18102166Stjr * 19102166Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20102166Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21102166Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22102166Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23102166Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24102166Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25102166Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26107706Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27107706Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28102166Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29102166Stjr * SUCH DAMAGE. 30102166Stjr * 31102166Stjr * mpboot.s: FreeBSD machine support for the Intel MP Spec 32102166Stjr * multiprocessor systems. 33102166Stjr * 34102166Stjr * $FreeBSD: head/sys/amd64/amd64/mpboot.S 64325 2000-08-07 02:28:37Z tegge $ 35102166Stjr */ 36102166Stjr 37102166Stjr#include <machine/asmacros.h> /* miscellaneous asm macros */ 38102166Stjr#include <machine/apic.h> 39102166Stjr#include <machine/specialreg.h> 40102166Stjr 41102166Stjr#include "assym.s" 42102166Stjr 43102166Stjr/* 44102166Stjr * this code MUST be enabled here and in mp_machdep.c 45102166Stjr * it follows the very early stages of AP boot by placing values in CMOS ram. 46102166Stjr * it NORMALLY will never be needed and thus the primitive method for enabling. 47102166Stjr * 48102166Stjr#define CHECK_POINTS 49102166Stjr */ 50102166Stjr 51102166Stjr#if defined(CHECK_POINTS) && !defined(PC98) 52102166Stjr 53107706Sru#define CMOS_REG (0x70) 54102166Stjr#define CMOS_DATA (0x71) 55102166Stjr 56102166Stjr#define CHECKPOINT(A,D) \ 57102166Stjr movb $(A),%al ; \ 58102166Stjr outb %al,$CMOS_REG ; \ 59102166Stjr movb $(D),%al ; \ 60102166Stjr outb %al,$CMOS_DATA 61102166Stjr 62102166Stjr#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 _IdlePTD-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 _bootSTK,%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 /* 96 * If the [BSP] CPU has support for VME, turn it on. 97 */ 98 testl $CPUID_VME, _cpu_feature /* XXX WRONG! BSP! */ 99 jz 1f 100 movl %cr4, %eax 101 orl $CR4_VME, %eax 102 movl %eax, %cr4 1031: 104 105 /* disable the APIC, just to be SURE */ 106 movl lapic_svr, %eax /* get spurious vector reg. */ 107 andl $~APIC_SVR_SWEN, %eax /* clear software enable bit */ 108 movl %eax, lapic_svr 109 110 /* signal our startup to the BSP */ 111 movl lapic_ver, %eax /* our version reg contents */ 112 movl %eax, _cpu_apic_versions /* into [ 0 ] */ 113 incl _mp_ncpus /* signal BSP */ 114 115 CHECKPOINT(0x39, 6) 116 117 /* wait till we can get into the kernel */ 118 call _boot_get_mplock 119 120 /* Now, let's prepare for some REAL WORK :-) */ 121 call _ap_init 122 123 call _rel_mplock 124 lock /* Avoid livelock (PIII Errata 39) */ 125 addl $0,-4(%esp) 1262: 127 cmpl $0, CNAME(smp_started) /* Wait for last AP to be ready */ 128 jz 2b 129 call _get_mplock 130 131 /* let her rip! (loads new stack) */ 132 jmp _cpu_switch 133 134NON_GPROF_ENTRY(wait_ap) 135 pushl %ebp 136 movl %esp, %ebp 137 call _rel_mplock 138 lock /* Avoid livelock (PIII Errata 39) */ 139 addl $0,0(%esp) 140 movl %eax, 8(%ebp) 1411: 142 cmpl $0, CNAME(smp_started) 143 jnz 2f 144 decl %eax 145 cmpl $0, %eax 146 jge 1b 1472: 148 call _get_mplock 149 movl %ebp, %esp 150 popl %ebp 151 ret 152 153 154/* 155 * This is the embedded trampoline or bootstrap that is 156 * copied into 'real-mode' low memory, it is where the 157 * secondary processor "wakes up". When it is executed 158 * the processor will eventually jump into the routine 159 * MPentry, which resides in normal kernel text above 160 * 1Meg. -jackv 161 */ 162 163 .data 164 ALIGN_DATA /* just to be sure */ 165 166BOOTMP1: 167 168NON_GPROF_ENTRY(bootMP) 169 .code16 170 cli 171 CHECKPOINT(0x34, 1) 172 /* First guarantee a 'clean slate' */ 173 xorl %eax, %eax 174 movl %eax, %ebx 175 movl %eax, %ecx 176 movl %eax, %edx 177 movl %eax, %esi 178 movl %eax, %edi 179 180 /* set up data segments */ 181 mov %cs, %ax 182 mov %ax, %ds 183 mov %ax, %es 184 mov %ax, %fs 185 mov %ax, %gs 186 mov %ax, %ss 187 mov $(boot_stk-_bootMP), %esp 188 189 /* Now load the global descriptor table */ 190 lgdt MP_GDTptr-_bootMP 191 192 /* Enable protected mode */ 193 movl %cr0, %eax 194 orl $CR0_PE, %eax 195 movl %eax, %cr0 196 197 /* 198 * make intrasegment jump to flush the processor pipeline and 199 * reload CS register 200 */ 201 pushl $0x18 202 pushl $(protmode-_bootMP) 203 lretl 204 205 .code32 206protmode: 207 CHECKPOINT(0x35, 2) 208 209 /* 210 * we are NOW running for the first time with %eip 211 * having the full physical address, BUT we still 212 * are using a segment descriptor with the origin 213 * not matching the booting kernel. 214 * 215 * SO NOW... for the BIG Jump into kernel's segment 216 * and physical text above 1 Meg. 217 */ 218 mov $0x10, %ebx 219 movw %bx, %ds 220 movw %bx, %es 221 movw %bx, %fs 222 movw %bx, %gs 223 movw %bx, %ss 224 225 .globl _bigJump 226_bigJump: 227 /* this will be modified by mpInstallTramp() */ 228 ljmp $0x08, $0 /* far jmp to MPentry() */ 229 230dead: hlt /* We should never get here */ 231 jmp dead 232 233/* 234 * MP boot strap Global Descriptor Table 235 */ 236 .p2align 4 237 .globl _MP_GDT 238 .globl _bootCodeSeg 239 .globl _bootDataSeg 240_MP_GDT: 241 242nulldesc: /* offset = 0x0 */ 243 244 .word 0x0 245 .word 0x0 246 .byte 0x0 247 .byte 0x0 248 .byte 0x0 249 .byte 0x0 250 251kernelcode: /* offset = 0x08 */ 252 253 .word 0xffff /* segment limit 0..15 */ 254 .word 0x0000 /* segment base 0..15 */ 255 .byte 0x0 /* segment base 16..23; set for 0K */ 256 .byte 0x9f /* flags; Type */ 257 .byte 0xcf /* flags; Limit */ 258 .byte 0x0 /* segment base 24..32 */ 259 260kerneldata: /* offset = 0x10 */ 261 262 .word 0xffff /* segment limit 0..15 */ 263 .word 0x0000 /* segment base 0..15 */ 264 .byte 0x0 /* segment base 16..23; set for 0k */ 265 .byte 0x93 /* flags; Type */ 266 .byte 0xcf /* flags; Limit */ 267 .byte 0x0 /* segment base 24..32 */ 268 269bootcode: /* offset = 0x18 */ 270 271 .word 0xffff /* segment limit 0..15 */ 272_bootCodeSeg: /* this will be modified by mpInstallTramp() */ 273 .word 0x0000 /* segment base 0..15 */ 274 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 275 .byte 0x9e /* flags; Type */ 276 .byte 0xcf /* flags; Limit */ 277 .byte 0x0 /*segment base 24..32 */ 278 279bootdata: /* offset = 0x20 */ 280 281 .word 0xffff 282_bootDataSeg: /* this will be modified by mpInstallTramp() */ 283 .word 0x0000 /* segment base 0..15 */ 284 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 285 .byte 0x92 286 .byte 0xcf 287 .byte 0x0 288 289/* 290 * GDT pointer for the lgdt call 291 */ 292 .globl _mp_gdtbase 293 294MP_GDTptr: 295_mp_gdtlimit: 296 .word 0x0028 297_mp_gdtbase: /* this will be modified by mpInstallTramp() */ 298 .long 0 299 300 .space 0x100 /* space for boot_stk - 1st temporary stack */ 301boot_stk: 302 303BOOTMP2: 304 .globl _bootMP_size 305_bootMP_size: 306 .long BOOTMP2 - BOOTMP1 307