e9911cf591
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
218 lines
6.1 KiB
ArmAsm
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)
|