/*
* systrap.S
*
* This file contains emulated system calls using software trap 0.
* The following calls are supported:
*
* + SYS_exit (halt)
* + SYS_irqdis (disable interrupts)
* + SYS_irqset (set interrupt level)
*
* COPYRIGHT (c) 2010. Gedare Bloom.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <rtems/asm.h>
#include "sparc64-syscall.h"
.seg "text"
/*
* system call
*
* On entry:
* g4[AG | GL=1] = tstate (from trap table)
* g2[AG | GL=1] = trap vector # (256)
* g3[AG | GL=1] = address of SYM(syscall)
* g4[AG | GL-1] = system call id
* if arch = sun4v:
* We need to back to GL-1 to read the system call id.
* on sun4u:
* We need to go back to the normal globals to read the system call id.
*
* First thing is to return to the previous set of globals, so
* that the system call id can be read. The syscall code needs
* to re-read tstate.
*
* syscall should only ever be entered by ta 0 being called explicitly
* by a function that knows what is happening. This means the syscall
* code can safely use any scratch registers and the %o registers.
*/
PUBLIC(syscall)
SYM(syscall):
mov %g0, %g4 ! clear %g4 at this GL
#if defined (SUN4U)
rdpr %pstate, %g1
andn %g1, SPARC_PSTATE_AG_MASK, %g1
wrpr %g1, %g0, %pstate ! go to regular globals
#elif defined (SUN4V)
rdpr %gl, %g1
dec %g1
wrpr %g0, %g1, %gl ! go back to GL = GL - 1
#endif
subcc %g4, 2, %g0
bne 3f
rdpr %tstate, %g5 ! re-read tstate, use delay slot
! syscall 2, disable interrupts
rdpr %pil, %g1
and %g5, SPARC_TSTATE_IE_MASK, %o0
or %o0, %g1, %o0 ! return TSTATE_IE | PIL
wrpr %g0, 0xf, %pil ! set PIL to 15
andn %g5, SPARC_TSTATE_IE_MASK, %g1
wrpr %g0, %g1, %tstate ! disable interrupts in trap state
ba,a 9f
3: ! syscall 3, enable interrupts
subcc %g4, 3, %g0
bne 1f
and %o0, 0xf, %g1
wrpr %g0, %g1, %pil ! restore PIL
! and %o0, SPARC_TSTATE_IE_MASK, %g1
! or %g5, %g1, %g1 ! restore saved IE
or %g5, SPARC_TSTATE_IE_MASK, %g1 ! restore IE (safe?)
wrpr %g0, %g1, %tstate
ba,a 9f
1:
ba,a 1b ! spin. taking a trap here -> htrap
9: ! leave
mov 0, %g4 ! clear %g4
DONE
PUBLIC(sparc_disable_interrupts)
SYM(sparc_disable_interrupts):
mov SYS_irqdis, %g4
ta 0
#if 0
rdpr %pstate, %g5
rdpr %pil, %g1
and %g5, SPARC_PSTATE_IE_MASK, %o0
or %o0, %g1, %o0 ! return PSTATE_IE | PIL
wrpr %g0, 0xf, %pil ! set PIL to 15
andn %g5, SPARC_PSTATE_IE_MASK, %g1
wrpr %g0, %g1, %pstate ! disable interrupts
#endif
retl
nop
PUBLIC(sparc_enable_interrupts)
SYM(sparc_enable_interrupts):
mov SYS_irqen, %g4
ta 0
#if 0
rdpr %pstate, %g5
and %o0, 0xf, %g1
wrpr %g0, %g1, %pil ! restore PIL
and %o0, SPARC_PSTATE_IE_MASK, %g1
or %g5, %g1, %g1 ! restore saved IE
! or %g5, SPARC_PSTATE_IE_MASK, %g1 ! set IE regardless of old (safe?)
wrpr %g0, %g1, %pstate
#endif
retl
nop
/* end of file */