blob: e4dbc9afbbd0fde4fa3a1de9cadcb2dae590b6da [file] [log] [blame]
#define __ASSEMBLY
#include "psr.h"
#include "asm/asi.h"
#include "cpustate.h"
#define ASI_BP ASI_M_BYPASS
#define REGWIN_SZ 0x40
.globl __switch_context, __switch_context_nosave, __exit_context, halt
.text
.align 4
/*
* Switch execution context
* This saves registers in the stack, then
* switches the stack, and restores everything from the new stack.
* This function takes no argument. New stack pointer is
* taken from global variable __context, and old stack pointer
* is also saved to __context. This way we can just jump to
* this routine to get back to the original context.
*/
__switch_context:
FLUSH_ALL_KERNEL_WINDOWS
/* Save everything in stack */
st %g1, [%sp - 0x260 + 0x14]
st %g2, [%sp - 0x260 + 0x18]
st %g3, [%sp - 0x260 + 0x1c]
st %g4, [%sp - 0x260 + 0x20]
st %g5, [%sp - 0x260 + 0x24]
st %g6, [%sp - 0x260 + 0x28]
st %g7, [%sp - 0x260 + 0x2c]
mov %sp, %g1
add %g1, -0x260, %g1
SAVE_CPU_STATE(switch)
/* Return PC value */
mov %o7, %g2
add %g2, 4, %g2
st %g2, [%sp - 0x260 + 0x250]
/* swap context */
set __context, %g3
ld [%g3], %g2
st %g1, [%g3]
mov %g2, %g1
ba __set_context
nop
__switch_context_nosave:
FLUSH_ALL_KERNEL_WINDOWS
set __context, %g1
ld [%g1], %g1
__set_context:
RESTORE_CPU_STATE(switch)
/* Restore globals */
mov %g1, %g2
add %g2, 0x14, %g2
st %g2, [%sp - 96]
ld [%g1 + 0x18], %g2
ld [%g1 + 0x1c], %g3
ld [%g1 + 0x20], %g4
ld [%g1 + 0x24], %g5
ld [%g1 + 0x28], %g6
ld [%g1 + 0x2c], %g7
/* Finally, load new %pc */
ld [%g1 + 0x250], %g1
jmpl %g1, %o7
ld [%sp - 96], %g1
__exit_context:
/* Get back to the original context */
ba __switch_context
nop