mpboot.s revision 282065
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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * mpboot.s: FreeBSD machine support for the Intel MP Spec 27 * multiprocessor systems. 28 * 29 * $FreeBSD: stable/10/sys/i386/i386/mpboot.s 282065 2015-04-27 08:02:12Z kib $ 30 */ 31 32#include "opt_pmap.h" 33 34#include <machine/asmacros.h> /* miscellaneous asm macros */ 35#include <x86/apicreg.h> 36#include <machine/specialreg.h> 37 38#include "assym.s" 39 40#define R(x) ((x)-KERNBASE) 41 42/* 43 * this code MUST be enabled here and in mp_machdep.c 44 * it follows the very early stages of AP boot by placing values in CMOS ram. 45 * it NORMALLY will never be needed and thus the primitive method for enabling. 46 * 47#define CHECK_POINTS 48 */ 49 50#if defined(CHECK_POINTS) && !defined(PC98) 51 52#define CMOS_REG (0x70) 53#define CMOS_DATA (0x71) 54 55#define CHECKPOINT(A,D) \ 56 movb $(A),%al ; \ 57 outb %al,$CMOS_REG ; \ 58 movb $(D),%al ; \ 59 outb %al,$CMOS_DATA 60 61#else 62 63#define CHECKPOINT(A,D) 64 65#endif /* CHECK_POINTS */ 66 67 68/* 69 * the APs enter here from their trampoline code (bootMP, below) 70 */ 71 .p2align 4 72 73NON_GPROF_ENTRY(MPentry) 74 CHECKPOINT(0x36, 3) 75 /* 76 * Enable features on this processor. We don't support SMP on 77 * CPUs older than a Pentium, so we know that we can use the cpuid 78 * instruction. 79 */ 80 movl $1,%eax 81 cpuid /* Retrieve features */ 82 movl %cr4,%eax 83#ifndef DISABLE_PSE 84 testl $CPUID_PSE,%edx 85 jz 1f 86 orl $CR4_PSE,%eax /* Enable PSE */ 871: 88#endif 89#ifndef DISABLE_PG_G 90 testl $CPUID_PGE,%edx 91 jz 1f 92 orl $CR4_PGE,%eax /* Enable PGE */ 931: 94#endif 95 testl $CPUID_VME,%edx 96 jz 1f 97 orl $CR4_VME,%eax /* Enable VME */ 981: 99 movl %eax,%cr4 100 101 /* Now enable paging mode */ 102#if defined(PAE) || defined(PAE_TABLES) 103 movl R(IdlePDPT), %eax 104 movl %eax, %cr3 105 movl %cr4, %eax 106 orl $CR4_PAE, %eax 107 movl %eax, %cr4 108#else 109 movl R(IdlePTD), %eax 110 movl %eax,%cr3 111#endif 112 movl %cr0,%eax 113 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 114 movl %eax,%cr0 /* let the games begin! */ 115 movl bootSTK,%esp /* boot stack end loc. */ 116 117 pushl $mp_begin /* jump to high mem */ 118 ret 119 120 /* 121 * Wait for the booting CPU to signal startup 122 */ 123mp_begin: /* now running relocated at KERNBASE */ 124 CHECKPOINT(0x37, 4) 125 call init_secondary /* load i386 tables */ 126 127/* 128 * This is the embedded trampoline or bootstrap that is 129 * copied into 'real-mode' low memory, it is where the 130 * secondary processor "wakes up". When it is executed 131 * the processor will eventually jump into the routine 132 * MPentry, which resides in normal kernel text above 133 * 1Meg. -jackv 134 */ 135 136 .data 137 ALIGN_DATA /* just to be sure */ 138 139BOOTMP1: 140 141NON_GPROF_ENTRY(bootMP) 142 .code16 143 cli 144 CHECKPOINT(0x34, 1) 145 /* First guarantee a 'clean slate' */ 146 xorl %eax, %eax 147 movl %eax, %ebx 148 movl %eax, %ecx 149 movl %eax, %edx 150 movl %eax, %esi 151 movl %eax, %edi 152 153 /* set up data segments */ 154 mov %cs, %ax 155 mov %ax, %ds 156 mov %ax, %es 157 mov %ax, %fs 158 mov %ax, %gs 159 mov %ax, %ss 160 mov $(boot_stk-bootMP), %esp 161 162 /* Now load the global descriptor table */ 163 lgdt MP_GDTptr-bootMP 164 165 /* Enable protected mode */ 166 movl %cr0, %eax 167 orl $CR0_PE, %eax 168 movl %eax, %cr0 169 170 /* 171 * make intrasegment jump to flush the processor pipeline and 172 * reload CS register 173 */ 174 pushl $0x18 175 pushl $(protmode-bootMP) 176 lretl 177 178 .code32 179protmode: 180 CHECKPOINT(0x35, 2) 181 182 /* 183 * we are NOW running for the first time with %eip 184 * having the full physical address, BUT we still 185 * are using a segment descriptor with the origin 186 * not matching the booting kernel. 187 * 188 * SO NOW... for the BIG Jump into kernel's segment 189 * and physical text above 1 Meg. 190 */ 191 mov $0x10, %ebx 192 movw %bx, %ds 193 movw %bx, %es 194 movw %bx, %fs 195 movw %bx, %gs 196 movw %bx, %ss 197 198 .globl bigJump 199bigJump: 200 /* this will be modified by mpInstallTramp() */ 201 ljmp $0x08, $0 /* far jmp to MPentry() */ 202 203dead: hlt /* We should never get here */ 204 jmp dead 205 206/* 207 * MP boot strap Global Descriptor Table 208 */ 209 .p2align 4 210 .globl MP_GDT 211 .globl bootCodeSeg 212 .globl bootDataSeg 213MP_GDT: 214 215nulldesc: /* offset = 0x0 */ 216 217 .word 0x0 218 .word 0x0 219 .byte 0x0 220 .byte 0x0 221 .byte 0x0 222 .byte 0x0 223 224kernelcode: /* offset = 0x08 */ 225 226 .word 0xffff /* segment limit 0..15 */ 227 .word 0x0000 /* segment base 0..15 */ 228 .byte 0x0 /* segment base 16..23; set for 0K */ 229 .byte 0x9f /* flags; Type */ 230 .byte 0xcf /* flags; Limit */ 231 .byte 0x0 /* segment base 24..32 */ 232 233kerneldata: /* offset = 0x10 */ 234 235 .word 0xffff /* segment limit 0..15 */ 236 .word 0x0000 /* segment base 0..15 */ 237 .byte 0x0 /* segment base 16..23; set for 0k */ 238 .byte 0x93 /* flags; Type */ 239 .byte 0xcf /* flags; Limit */ 240 .byte 0x0 /* segment base 24..32 */ 241 242bootcode: /* offset = 0x18 */ 243 244 .word 0xffff /* segment limit 0..15 */ 245bootCodeSeg: /* this will be modified by mpInstallTramp() */ 246 .word 0x0000 /* segment base 0..15 */ 247 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 248 .byte 0x9e /* flags; Type */ 249 .byte 0xcf /* flags; Limit */ 250 .byte 0x0 /*segment base 24..32 */ 251 252bootdata: /* offset = 0x20 */ 253 254 .word 0xffff 255bootDataSeg: /* this will be modified by mpInstallTramp() */ 256 .word 0x0000 /* segment base 0..15 */ 257 .byte 0x00 /* segment base 16...23; set for 0x000xx000 */ 258 .byte 0x92 259 .byte 0xcf 260 .byte 0x0 261 262/* 263 * GDT pointer for the lgdt call 264 */ 265 .globl mp_gdtbase 266 267MP_GDTptr: 268mp_gdtlimit: 269 .word 0x0028 270mp_gdtbase: /* this will be modified by mpInstallTramp() */ 271 .long 0 272 273 .space 0x100 /* space for boot_stk - 1st temporary stack */ 274boot_stk: 275 276BOOTMP2: 277 .globl bootMP_size 278bootMP_size: 279 .long BOOTMP2 - BOOTMP1 280