freebsd-skq/sys/alpha/alpha/locore.s

356 lines
9.4 KiB
ArmAsm

/*-
* Copyright (c) 1998 Doug Rabson
* 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.
*
* 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 AUTHOR 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <machine/asm.h>
#include <sys/syscall.h>
#include <assym.s>
#ifndef EVCNT_COUNTERS
#define _LOCORE
#include <machine/intrcnt.h>
#endif
/*
* PTmap is recursive pagemap at top of virtual address space.
* Within PTmap, the lev1 and lev0 page tables can be found.
*/
.globl PTmap,PTlev2,PTlev1,PTlev1pte
.equ PTmap,VPTBASE
.equ PTlev2,PTmap + (PTLEV1I << ALPHA_L2SHIFT)
.equ PTlev1,PTlev2 + (PTLEV1I << ALPHA_L3SHIFT)
.equ PTlev1pte,PTlev1 + (PTLEV1I * PTESIZE)
/*
* Perform actions necessary to switch to a new context. The
* hwpcb should be in a0.
*/
#define SWITCH_CONTEXT \
/* Make a note of the context we're running on. */ \
stq a0, GD_CURPCB(globalp); \
\
/* Swap in the new context. */ \
call_pal PAL_OSF1_swpctx
.text
NESTED(locorestart, 1, 0, ra, 0, 0)
br pv,1f
1: LDGP(pv)
/* Load KGP with current GP. */
or a0,zero,s0 /* save pfn */
or gp,zero,a0
call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */
or s0,zero,a0 /* restore pfn */
/*
* Call alpha_init() to do pre-main initialization.
* alpha_init() gets the arguments we were called with,
* which are already in a0, a1, a2, a3, and a4.
*/
CALL(alpha_init)
/* Set up the virtual page table pointer. */
ldiq a0, VPTBASE
call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */
/*
* Initialise globalp.
*/
call_pal PAL_OSF1_rdval /* clobbers t0, t8-t11 */
mov v0, globalp
/*
* Switch to proc0's PCB, which is at U_PCB off of proc0paddr.
*/
lda t0,proc0 /* get phys addr of pcb */
ldq a0,P_MD_PCBPADDR(t0)
SWITCH_CONTEXT
/*
* We've switched to a new page table base, so invalidate the TLB
* and I-stream. This happens automatically everywhere but here.
*/
ldiq a0, -2 /* TBIA */
call_pal PAL_OSF1_tbi
call_pal PAL_imb
/*
* Construct a fake trap frame, so execve() can work normally.
* Note that setregs() is responsible for setting its contents
* to 'reasonable' values.
*/
lda sp,-288(sp) /* space for struct trapframe */
mov sp, a0 /* arg is frame ptr */
CALL(mi_startup) /* go to mi_startup()! */
/* NOTREACHED */
END(locorestart)
#ifdef SMP
/*
* Secondary processors start executing here. They will have their
* unique value set to point at the per-cpu structure and will
* be executing on their private idle stack.
*/
NESTED(smp_init_secondary_glue, 1, 0, ra, 0, 0)
mov pv, globalp
ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */
call_pal PAL_OSF1_swpipl
br pv, 1f
1: LDGP(pv)
mov gp, a0
call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */
ldiq a0, -2 /* TBIA */
call_pal PAL_OSF1_tbi
call_pal PAL_imb
ldq a0, GD_IDLEPCBPHYS(globalp) /* switch to idle ctx */
call_pal PAL_OSF1_swpctx
CALL(smp_init_secondary) /* initialise the rest */
/*
* After initialising, we start idling for real.
* We have the kernel lock at this point.
*/
CALL(cpu_switch) /* never returns */
call_pal PAL_halt
END(smp_init_secondary_glue)
#endif
/**************************************************************************/
/*
* Signal "trampoline" code. Invoked from RTE setup by sendsig().
*
* On entry, stack & registers look like:
*
* a0 signal number
* a1 pointer to siginfo_t
* a2 pointer to signal context frame (scp)
* a3 address of handler
* sp+0 saved hardware state
* .
* .
* scp+0 beginning of signal context frame
*/
NESTED(sigcode,0,0,ra,0,0)
lda sp, -16(sp) /* save the sigcontext pointer */
stq a2, 0(sp)
jsr ra, (t12) /* call the signal handler (t12==pv) */
ldq a0, 0(sp) /* get the sigcontext pointer */
lda sp, 16(sp)
CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */
mov v0, a0 /* if that failed, get error code */
CALLSYS_NOERROR(exit) /* and call exit() with it. */
XNESTED(esigcode,0)
END(sigcode)
.data
EXPORT(szsigcode)
.quad esigcode-sigcode
.text
/**************************************************************************/
/*
* savefpstate: Save a process's floating point state.
*
* Arguments:
* a0 'struct fpstate *' to save into
*/
LEAF(savefpstate, 1)
LDGP(pv)
/* save all of the FP registers */
lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */
stt $f0, (0 * 8)(t1) /* save first register, using hw name */
stt $f1, (1 * 8)(t1) /* etc. */
stt $f2, (2 * 8)(t1)
stt $f3, (3 * 8)(t1)
stt $f4, (4 * 8)(t1)
stt $f5, (5 * 8)(t1)
stt $f6, (6 * 8)(t1)
stt $f7, (7 * 8)(t1)
stt $f8, (8 * 8)(t1)
stt $f9, (9 * 8)(t1)
stt $f10, (10 * 8)(t1)
stt $f11, (11 * 8)(t1)
stt $f12, (12 * 8)(t1)
stt $f13, (13 * 8)(t1)
stt $f14, (14 * 8)(t1)
stt $f15, (15 * 8)(t1)
stt $f16, (16 * 8)(t1)
stt $f17, (17 * 8)(t1)
stt $f18, (18 * 8)(t1)
stt $f19, (19 * 8)(t1)
stt $f20, (20 * 8)(t1)
stt $f21, (21 * 8)(t1)
stt $f22, (22 * 8)(t1)
stt $f23, (23 * 8)(t1)
stt $f24, (24 * 8)(t1)
stt $f25, (25 * 8)(t1)
stt $f26, (26 * 8)(t1)
stt $f27, (27 * 8)(t1)
stt $f28, (28 * 8)(t1)
stt $f29, (29 * 8)(t1)
stt $f30, (30 * 8)(t1)
/*
* Then save the FPCR; note that the necessary 'trapb's are taken
* care of on kernel entry and exit.
*/
mf_fpcr ft0
stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */
RET
END(savefpstate)
/**************************************************************************/
/*
* restorefpstate: Restore a process's floating point state.
*
* Arguments:
* a0 'struct fpstate *' to restore from
*/
LEAF(restorefpstate, 1)
LDGP(pv)
/*
* Restore the FPCR; note that the necessary 'trapb's are taken care of
* on kernel entry and exit.
*/
ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */
mt_fpcr ft0
/* Restore all of the FP registers. */
lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */
ldt $f0, (0 * 8)(t1) /* restore first reg., using hw name */
ldt $f1, (1 * 8)(t1) /* etc. */
ldt $f2, (2 * 8)(t1)
ldt $f3, (3 * 8)(t1)
ldt $f4, (4 * 8)(t1)
ldt $f5, (5 * 8)(t1)
ldt $f6, (6 * 8)(t1)
ldt $f7, (7 * 8)(t1)
ldt $f8, (8 * 8)(t1)
ldt $f9, (9 * 8)(t1)
ldt $f10, (10 * 8)(t1)
ldt $f11, (11 * 8)(t1)
ldt $f12, (12 * 8)(t1)
ldt $f13, (13 * 8)(t1)
ldt $f14, (14 * 8)(t1)
ldt $f15, (15 * 8)(t1)
ldt $f16, (16 * 8)(t1)
ldt $f17, (17 * 8)(t1)
ldt $f18, (18 * 8)(t1)
ldt $f19, (19 * 8)(t1)
ldt $f20, (20 * 8)(t1)
ldt $f21, (21 * 8)(t1)
ldt $f22, (22 * 8)(t1)
ldt $f23, (23 * 8)(t1)
ldt $f24, (24 * 8)(t1)
ldt $f25, (25 * 8)(t1)
ldt $f26, (26 * 8)(t1)
ldt $f27, (27 * 8)(t1)
ldt $f28, (28 * 8)(t1)
ldt $f29, (29 * 8)(t1)
ldt $f30, (30 * 8)(t1)
RET
END(restorefpstate)
/*
* When starting init, call this to configure the process for user
* mode. This will be inherited by other processes.
*/
LEAF_NOPROFILE(prepare_usermode, 0)
RET
END(prepare_usermode)
.data
EXPORT(proc0paddr)
.quad 0
.text
/* XXX: make systat/vmstat happy */
.data
EXPORT(intrnames)
.asciz "clock"
intr_n = 0
.rept INTRCNT_COUNT
.ascii "intr "
.byte intr_n / 10 + '0, intr_n % 10 + '0
.asciz " " # space for platform-specific rewrite
intr_n = intr_n + 1
.endr
EXPORT(eintrnames)
.align 3
EXPORT(intrcnt)
.fill INTRCNT_COUNT + 1, 8, 0
EXPORT(eintrcnt)
.text