#include "cpustate.h" .globl sparc64_of_client_interface, client_tba /* * SAVE_WINDOW_STATE and RESTORE_WINDOW_STATE are used to ensure * that the CPU window state is preserved across CIF calls. This is * to workaround a *BSD restriction that window fill/spill traps must * be minimised during trap table takeover, and likely emulates the * behaviour of OBP. */ .data .align 8 client_context: .xword 0 client_stack: .xword 0 client_window: .skip 2048 .text .align 4 .register %g2, #scratch .register %g3, #scratch .register %g6, #scratch .register %g7, #scratch /* make some more space on stack since linux kernel only provides 128 bytes without memory to spill registers (used by gcc in -O0 mode) */ sparc64_of_client_interface: /* Save globals on callers stack */ stx %g1, [%sp + 2047 - 248 + 192] stx %g2, [%sp + 2047 - 248 + 200] stx %g3, [%sp + 2047 - 248 + 208] stx %g4, [%sp + 2047 - 248 + 216] stx %g5, [%sp + 2047 - 248 + 224] stx %g6, [%sp + 2047 - 248 + 232] stx %g7, [%sp + 2047 - 248 + 240] /* Save existing stack */ setx client_stack, %g6, %g7 stx %sp, [%g7] /* Save windows */ setx _fcstack_ptr, %g6, %g7 ldx [%g7], %g1 add %g1, -CONTEXT_STATE_SIZE, %g1 stx %g1, [%g7] /* Save globals */ ldx [%sp + 2047 - 248 + 192], %g7 stx %g7, [%g1 + 0x30] ldx [%sp + 2047 - 248 + 200], %g7 stx %g7, [%g1 + 0x38] ldx [%sp + 2047 - 248 + 208], %g7 stx %g7, [%g1 + 0x40] ldx [%sp + 2047 - 248 + 216], %g7 stx %g7, [%g1 + 0x48] ldx [%sp + 2047 - 248 + 224], %g7 stx %g7, [%g1 + 0x50] ldx [%sp + 2047 - 248 + 232], %g7 stx %g7, [%g1 + 0x58] ldx [%sp + 2047 - 248 + 240], %g7 stx %g7, [%g1 + 0x60] /* Save %pc */ mov %o7, %g7 add %g7, 8, %g7 stx %g7, [%g1 + 0x4d0] SAVE_CPU_STATE(cif) RESET_CPU_WINDOW_STATE(cif) /* Update __context to point to saved area */ setx __context, %g6, %g7 ldx [%g7], %g3 setx client_context, %g4, %g5 stx %g3, [%g5] stx %g1, [%g7] /* Move to OpenBIOS context stack */ setx _fcstack_ptr, %g6, %g7 ldx [%g7], %g6 setx CONTEXT_STACK_SIZE, %g4, %g5 sub %g6, %g5, %g6 stx %g6, [%g7] setx - 2047 - 192, %g6, %g7 add %g1, %g7, %g7 mov %g7, %sp /* Call client inteface */ call of_client_interface ldx [%g1 + 0x70], %o0 /* Restore windows */ setx _fcstack_ptr, %g6, %g7 ldx [%g7], %g1 setx CONTEXT_STACK_SIZE, %g4, %g5 add %g1, %g5, %g1 stx %g1, [%g7] /* Return value */ stx %o0, [%g1 + 0x70] /* Restore __context */ setx client_context, %g4, %g5 ldx [%g5], %g3 setx __context, %g6, %g7 stx %g3, [%g7] RESTORE_CPU_STATE(cif) add %g1, CONTEXT_STATE_SIZE, %g5 setx _fcstack_ptr, %g6, %g7 stx %g5, [%g7] /* Restore stack */ setx client_stack, %g6, %g7 ldx [%g7], %sp /* Restore %pc */ ldx [%g1 + 0x4d0], %o7 /* Restore globals */ ldx [%g1 + 0x38], %g2 ldx [%g1 + 0x40], %g3 ldx [%g1 + 0x48], %g4 ldx [%g1 + 0x50], %g5 ldx [%g1 + 0x58], %g6 ldx [%g1 + 0x60], %g7 jmp %o7 ldx [%g1 + 0x30], %g1