#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