freebsd-nq/sys/i386/i386/mpboot.s
Peter Wemm 98823b2366 Convert the VM86 option from a global option to an option only depended
on by the files that use it.  Changing the VM86 option now only causes
a recompile of a dozen files or so rather than the entire kernel.
1997-10-10 09:44:12 +00:00

300 lines
7.2 KiB
ArmAsm

/*
* Copyright (c) 1995, Jack F. Vogel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Jack F. Vogel
* 4. The name of the developer may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* mpboot.s: FreeBSD machine support for the Intel MP Spec
* multiprocessor systems.
*
* $Id: mpboot.s,v 1.5 1997/09/22 05:03:03 peter Exp $
*/
#include "opt_vm86.h"
#include <machine/asmacros.h> /* miscellaneous asm macros */
#include <machine/apic.h>
#include <machine/specialreg.h>
#include "assym.s"
/*
* this code MUST be enabled here and in mp_machdep.c
* it follows the very early stages of AP boot by placing values in CMOS ram.
* it NORMALLY will never be needed and thus the primitive method for enabling.
*
#define CHECK_POINTS
*/
#if defined(CHECK_POINTS)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define CHECKPOINT(A,D) \
movb $(A),%al ; \
outb %al,$CMOS_REG ; \
movb $(D),%al ; \
outb %al,$CMOS_DATA
#else
#define CHECKPOINT(A,D)
#endif /* CHECK_POINTS */
/*
* the APs enter here from their trampoline code (bootMP, below)
*/
.p2align 4
NON_GPROF_ENTRY(MPentry)
CHECKPOINT(0x36, 3)
/* Now enable paging mode */
movl _bootPTD-KERNBASE, %eax
movl %eax,%cr3
movl %cr0,%eax
orl $CR0_PE|CR0_PG,%eax /* enable paging */
movl %eax,%cr0 /* let the games begin! */
movl $_idlestack_top,%esp /* boot stack end loc. */
pushl $mp_begin /* jump to high mem */
ret
/*
* Wait for the booting CPU to signal startup
*/
mp_begin: /* now running relocated at KERNBASE */
CHECKPOINT(0x37, 4)
call _init_secondary /* load i386 tables */
CHECKPOINT(0x38, 5)
#ifdef VM86
/*
* If the [BSP] CPU has support for VME, turn it on.
*/
testl $CPUID_VME, _cpu_feature /* XXX WRONG! BSP! */
jz 1f
movl %cr4, %eax
orl $CR4_VME, %eax
movl %eax, %cr4
1:
#endif
/* disable the APIC, just to be SURE */
movl lapic_svr, %eax /* get spurious vector reg. */
andl $~APIC_SVR_SWEN, %eax /* clear software enable bit */
movl %eax, lapic_svr
/* signal our startup to the BSP */
movl lapic_ver, %eax /* our version reg contents */
movl %eax, _cpu_apic_versions /* into [ 0 ] */
incl _mp_ncpus /* signal BSP */
CHECKPOINT(0x39, 6)
/* wait till we can get into the kernel */
call _boot_get_mplock
/* Now, let's prepare for some REAL WORK :-) */
call _ap_init
/* let her rip! (loads new stack) */
jmp _cpu_switch
/*
* This is the embedded trampoline or bootstrap that is
* copied into 'real-mode' low memory, it is where the
* secondary processor "wakes up". When it is executed
* the processor will eventually jump into the routine
* MPentry, which resides in normal kernel text above
* 1Meg. -jackv
*/
#define data32 .byte 0x66
#define addr32 .byte 0x67
.data
ALIGN_DATA /* just to be sure */
BOOTMP1:
NON_GPROF_ENTRY(bootMP)
cli
CHECKPOINT(0x34, 1)
/* First guarantee a 'clean slate' */
data32
xorl %eax, %eax
data32
movl %eax, %ebx
data32
movl %eax, %ecx
data32
movl %eax, %edx
data32
movl %eax, %esi
data32
movl %eax, %edi
/* set up data segments */
mov %cs, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov $(boot_stk-_bootMP), %sp
/* Now load the global descriptor table */
addr32
data32
/* XXX: sigh: lgdt MP_GDTptr-_bootMP GAS BUG! */
.byte 0x0f, 0x01, 0x15 /* XXX hand assemble! */
.long MP_GDTptr-_bootMP /* XXX hand assemble! */
/* Enable protected mode */
data32
movl %cr0, %eax
data32
orl $CR0_PE, %eax
data32
movl %eax, %cr0
/*
* make intrasegment jump to flush the processor pipeline and
* reload CS register
*/
data32
pushl $0x18
data32
pushl $(protmode-_bootMP)
data32
lret
protmode:
CHECKPOINT(0x35, 2)
/*
* we are NOW running for the first time with %eip
* having the full physical address, BUT we still
* are using a segment descriptor with the origin
* not matching the booting kernel.
*
* SO NOW... for the BIG Jump into kernel's segment
* and physical text above 1 Meg.
*/
mov $0x10, %ebx
movw %bx, %ds
movw %bx, %es
movw %bx, %fs
movw %bx, %gs
movw %bx, %ss
.globl _bigJump
_bigJump:
/* this will be modified by mpInstallTramp() */
ljmp $0x08, $0 /* far jmp to MPentry() */
dead: hlt /* We should never get here */
jmp dead
/*
* MP boot strap Global Descriptor Table
*/
.p2align 4
.globl _MP_GDT
.globl _bootCodeSeg
.globl _bootDataSeg
_MP_GDT:
nulldesc: /* offset = 0x0 */
.word 0x0
.word 0x0
.byte 0x0
.byte 0x0
.byte 0x0
.byte 0x0
kernelcode: /* offset = 0x08 */
.word 0xffff /* segment limit 0..15 */
.word 0x0000 /* segment base 0..15 */
.byte 0x0 /* segment base 16..23; set for 0K */
.byte 0x9f /* flags; Type */
.byte 0xcf /* flags; Limit */
.byte 0x0 /* segment base 24..32 */
kerneldata: /* offset = 0x10 */
.word 0xffff /* segment limit 0..15 */
.word 0x0000 /* segment base 0..15 */
.byte 0x0 /* segment base 16..23; set for 0k */
.byte 0x93 /* flags; Type */
.byte 0xcf /* flags; Limit */
.byte 0x0 /* segment base 24..32 */
bootcode: /* offset = 0x18 */
.word 0xffff /* segment limit 0..15 */
_bootCodeSeg: /* this will be modified by mpInstallTramp() */
.word 0x0000 /* segment base 0..15 */
.byte 0x00 /* segment base 16...23; set for 0x000xx000 */
.byte 0x9e /* flags; Type */
.byte 0xcf /* flags; Limit */
.byte 0x0 /*segment base 24..32 */
bootdata: /* offset = 0x20 */
.word 0xffff
_bootDataSeg: /* this will be modified by mpInstallTramp() */
.word 0x0000 /* segment base 0..15 */
.byte 0x00 /* segment base 16...23; set for 0x000xx000 */
.byte 0x92
.byte 0xcf
.byte 0x0
/*
* GDT pointer for the lgdt call
*/
.globl _mp_gdtbase
MP_GDTptr:
_mp_gdtlimit:
.word 0x0028
_mp_gdtbase: /* this will be modified by mpInstallTramp() */
.long 0
.space 0x100 /* space for boot_stk - 1st temporary stack */
boot_stk:
BOOTMP2:
.globl _bootMP_size
_bootMP_size:
.long BOOTMP2 - BOOTMP1