freebsd-nq/sys/alpha/alpha/swtch.s
John Baldwin e9911cf591 - Convert Alpha over to the new calling conventions for cpu_throw() and
cpu_switch() where both the old and new threads are passed in as
  arguments.  Only powerpc uses the old conventions now.
- Update comments in the Alpha swtch.s to reflect KSE changes.

Tested by:	obrien, marcel
2003-08-12 19:33:36 +00:00

218 lines
6.1 KiB
ArmAsm

/*
* 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.
*
* $NetBSD: locore.s,v 1.47 1998/03/22 07:26:32 thorpej Exp $
* $FreeBSD$
*/
#define _LOCORE
#include <machine/asm.h>
#include <machine/mutex.h>
#include "assym.s"
/**************************************************************************/
/*
* 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, PC_CURPCB(pcpup); \
\
/* Swap in the new context. */ \
call_pal PAL_OSF1_swpctx
/*
* savectx: save process context, i.e. callee-saved registers
*
* Note that savectx() only works for threads other than curthread,
* since cpu_switch will copy over the info saved here. (It _can_
* sanely be used for curthread iff cpu_switch won't be called again, e.g.
* from if called from boot().)
*
* Arguments:
* a0 'struct pcb *' of the process that needs its context saved
*
* Return:
* v0 0. (note that for child processes, it seems
* like savectx() returns 1, because the return address
* in the PCB is set to the return address from savectx().)
*/
LEAF(savectx, 1)
br pv, Lsavectx1
Lsavectx1: LDGP(pv)
stq sp, PCB_HWPCB_KSP(a0) /* store sp */
stq s0, PCB_CONTEXT+(0 * 8)(a0) /* store s0 - s6 */
stq s1, PCB_CONTEXT+(1 * 8)(a0)
stq s2, PCB_CONTEXT+(2 * 8)(a0)
stq s3, PCB_CONTEXT+(3 * 8)(a0)
stq s4, PCB_CONTEXT+(4 * 8)(a0)
stq s5, PCB_CONTEXT+(5 * 8)(a0)
stq s6, PCB_CONTEXT+(6 * 8)(a0)
stq ra, PCB_CONTEXT+(7 * 8)(a0) /* store ra */
call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */
stq v0, PCB_CONTEXT+(8 * 8)(a0) /* store ps, for ipl */
mov zero, v0
RET
END(savectx)
/**************************************************************************/
IMPORT(Lev1map, 8)
/*
* cpu_throw()
* Switch to a new thread discarding our current state.
*
* Arguments:
* a0 'struct thread *' of the old thread
* a1 'struct thread *' of the new thread
*/
LEAF(cpu_throw, 0)
LDGP(pv)
CALL(Lcs1)
END(cpu_throw)
/*
* cpu_switch()
* Switch to a new thread saving the current state in the old thread.
*
* Arguments:
* a0 'struct thread *' of the old thread
* a1 'struct thread *' of the new thread
*/
LEAF(cpu_switch, 1)
LDGP(pv)
/* do an inline savectx(), to save old context */
ldq a2, TD_PCB(a0)
/* NOTE: ksp is stored by the swpctx */
stq s0, PCB_CONTEXT+(0 * 8)(a2) /* store s0 - s6 */
stq s1, PCB_CONTEXT+(1 * 8)(a2)
stq s2, PCB_CONTEXT+(2 * 8)(a2)
stq s3, PCB_CONTEXT+(3 * 8)(a2)
stq s4, PCB_CONTEXT+(4 * 8)(a2)
stq s5, PCB_CONTEXT+(5 * 8)(a2)
stq s6, PCB_CONTEXT+(6 * 8)(a2)
stq ra, PCB_CONTEXT+(7 * 8)(a2) /* store ra */
call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */
stq v0, PCB_CONTEXT+(8 * 8)(a2) /* store ps, for ipl */
mov a0, s0 /* s0 = old curthread */
mov a2, s1 /* s1 = old pcb */
/*
* Deactivate the old address space before activating the
* new one. We need to do this before activating the
* new thread's address space in the event that new
* thread is using the same vmspace as the old. If we
* do this after we activate, then we might end up
* incorrectly marking the pmap inactive!
*
* We don't deactivate if we came here from switch_exit
* (old pmap no longer exists; vmspace has been freed).
* oldproc will be NULL in this case. We have actually
* taken care of calling pmap_deactivate() in cpu_exit(),
* before the vmspace went away.
*/
beq a0, sw1
CALL(pmap_deactivate) /* pmap_deactivate(oldthread) */
sw1:
br pv, Lcs1
Lcs1: LDGP(pv)
mov a1, s2 /* s2 = new thread */
ldq s3, TD_MD_PCBPADDR(s2) /* s3 = new pcbpaddr */
#ifdef SMP
/*
* Save fp state if we have some.
*/
mov s0, a0 /* curthread */
ldiq a1, 1 /* clear fpcurthread */
CALL(alpha_fpstate_save)
#endif
/*
* Activate the new thread's address space and perform
* the actual context swap.
*/
mov s2, a0 /* pmap_activate(newthread) */
CALL(pmap_activate) /* XXXKSE */
mov s3, a0 /* swap the context */
SWITCH_CONTEXT
/*
* Now that the switch is done, update curthread and other
* globals.
*/
stq s2, PC_CURTHREAD(pcpup) /* curthread = p */
/*
* Now running on the new pcb.
* Restore registers and return.
*/
ldq t0, TD_PCB(s2)
/* NOTE: ksp is restored by the swpctx */
ldq s0, PCB_CONTEXT+(0 * 8)(t0) /* restore s0 - s6 */
ldq s1, PCB_CONTEXT+(1 * 8)(t0)
ldq s2, PCB_CONTEXT+(2 * 8)(t0)
ldq s3, PCB_CONTEXT+(3 * 8)(t0)
ldq s4, PCB_CONTEXT+(4 * 8)(t0)
ldq s5, PCB_CONTEXT+(5 * 8)(t0)
ldq s6, PCB_CONTEXT+(6 * 8)(t0)
ldq ra, PCB_CONTEXT+(7 * 8)(t0) /* restore ra */
ldiq v0, 1 /* possible ret to savectx() */
RET
END(cpu_switch)
/*
* fork_trampoline()
*
* Arrange for a function to be invoked neatly, after a cpu_switch().
*
* Invokes fork_exit() passing in three arguments: a callout function,
* an argument to the callout, and a trapframe pointer. For child processes
* returning from fork(2), the argument is a pointer to the child process.
*
* The callout function is in s0, the address to return to after executing
* fork_exit() is in s1, and the argument is in s2.
*/
LEAF(fork_trampoline, 0)
mov s1, ra
mov s0, a0
mov s2, a1
mov sp, a2
jmp zero, fork_exit
END(fork_trampoline)