This also requires aligning the CPU context struct as defined in cpustate.h.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/context.c | 6 +-- arch/sparc64/context.h | 7 +-- arch/sparc64/entry.S | 17 ++++++- arch/sparc64/switch.S | 129 ++++++++++++++++++------------------------------ 4 files changed, 70 insertions(+), 89 deletions(-)
diff --git a/arch/sparc64/context.c b/arch/sparc64/context.c index 823116f..5ab0045 100644 --- a/arch/sparc64/context.c +++ b/arch/sparc64/context.c @@ -24,7 +24,6 @@ void __exit_context(void); /* assembly routine */ * to start us up. */ static struct context main_ctx = { - .regs[REG_SP] = (uint64_t) &_estack - STACK_BIAS - 96, .pc = (uint64_t) start_main, .npc = (uint64_t) start_main + 4, .return_addr = (uint64_t) __exit_context, @@ -76,7 +75,8 @@ init_context(uint8_t *stack, uint64_t stack_size, int num_params)
ctx = (struct context *) (stack_top - ALIGN_SIZE(sizeof(*ctx) + num_params*sizeof(uint64_t), sizeof(uint64_t))); - memset(ctx, 0, sizeof(*ctx)); + /* Use valid window state from startup */ + memcpy(ctx, &main_ctx, sizeof(struct context));
/* Fill in reasonable default for flat memory model */ ctx->regs[REG_SP] = virt_to_phys(stack_top - STACK_BIAS - 192); @@ -95,7 +95,7 @@ struct context *switch_to(struct context *ctx) save = __context; __context = ctx; //asm ("pushl %cs; call __switch_context"); - asm ("call __switch_context_nosave; nop"); + asm ("call __switch_context; nop"); ret = __context; __context = (struct context *)save; return ret; diff --git a/arch/sparc64/context.h b/arch/sparc64/context.h index 2756fa1..a047b9c 100644 --- a/arch/sparc64/context.h +++ b/arch/sparc64/context.h @@ -5,12 +5,13 @@
struct context { /* General registers */ - uint64_t regs[32]; + uint64_t regs[154]; uint64_t pc; uint64_t npc; -#define REG_O0 8 -#define REG_SP 14 +#define REG_O0 14 +#define REG_SP 20 #define SP_LOC(ctx) (&(ctx)->regs[REG_SP]) + uint64_t tregs[20]; /* Flags */ /* Optional stack contents */ uint64_t return_addr; diff --git a/arch/sparc64/entry.S b/arch/sparc64/entry.S index d03128a..3a46d89 100644 --- a/arch/sparc64/entry.S +++ b/arch/sparc64/entry.S @@ -11,6 +11,7 @@ #include <asm/asi.h> #include "pstate.h" #include "lsu.h" +#include "cpustate.h" #define NO_QEMU_PROTOS #define NO_OPENBIOS_PROTOS #include "arch/common/fw_cfg.h" @@ -264,6 +265,20 @@ lowmem: /* Finally, turn on traps so that we can call c-code. */ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
+ /* Set up a default context */ + setx __context, %g2, %g1 + ldx [%g1], %g1 + + SAVE_CPU_GENERAL_STATE(entry) + SAVE_CPU_WINDOW_STATE(entry) + + /* Set up local stack pointer */ + setx _estack - 2047, %o2, %sp + + /* And for the main context */ + add %sp, - 192 - 0x500, %g2 + stx %g2, [%g1 + 0xa0] + ! 100 Hz timer setx TICK_INT_DIS, %g2, %g1 rd %tick, %g2 @@ -276,7 +291,7 @@ lowmem: * Main context is statically defined in C. */
- call __switch_context_nosave + call __switch_context nop
/* We get here when the main context switches back to diff --git a/arch/sparc64/switch.S b/arch/sparc64/switch.S index d2cc7be..e6c63f0 100644 --- a/arch/sparc64/switch.S +++ b/arch/sparc64/switch.S @@ -1,5 +1,6 @@ #include "pstate.h" #include <asm/asi.h> +#include "cpustate.h" #define ASI_BP ASI_M_BYPASS #define REGWIN_SZ 0x40
@@ -22,47 +23,36 @@ * this routine to get back to the original context. */
-/* XXX: totally bogus for sparc, need to save and restore all windows */ __switch_context: - /* make sure caller's windows are on caller's stack */ flushw;
/* Save everything in current stack */ - - setx __context, %g2, %g1 - stx %g3, [%g1 + 24] - stx %g4, [%g1 + 32] - stx %g5, [%g1 + 40] - stx %g6, [%g1 + 48] - stx %g7, [%g1 + 56] - - stx %o0, [%g1 + 64] - stx %o1, [%g1 + 72] - stx %o2, [%g1 + 80] - stx %o3, [%g1 + 88] - stx %o4, [%g1 + 96] - stx %o5, [%g1 + 104] - stx %o6, [%g1 + 112] - stx %o7, [%g1 + 120] - - stx %l0, [%g1 + 128] - stx %l1, [%g1 + 136] - stx %l2, [%g1 + 144] - stx %l3, [%g1 + 152] - stx %l4, [%g1 + 160] - stx %l5, [%g1 + 168] - stx %l6, [%g1 + 176] - stx %l7, [%g1 + 184] - - stx %i0, [%g1 + 192] - stx %i1, [%g1 + 200] - stx %i2, [%g1 + 208] - stx %i3, [%g1 + 216] - stx %i4, [%g1 + 224] - stx %i5, [%g1 + 232] - stx %i6, [%g1 + 240] - stx %i7, [%g1 + 248] + stx %g1, [%sp + 2047 - 192 - 0x500 + 0x30] + stx %g2, [%sp + 2047 - 192 - 0x500 + 0x38] + stx %g3, [%sp + 2047 - 192 - 0x500 + 0x40] + stx %g4, [%sp + 2047 - 192 - 0x500 + 0x48] + stx %g5, [%sp + 2047 - 192 - 0x500 + 0x50] + stx %g6, [%sp + 2047 - 192 - 0x500 + 0x58] + stx %g7, [%sp + 2047 - 192 - 0x500 + 0x60] + + mov %sp, %g1 + add %g1, 2047 - 192 - 0x500, %g1 + + /* Return PC value */ + mov %o7, %g2 + add %g2, 0x8, %g2 + stx %g2, [%g1 + 0x4d0] + + SAVE_CPU_STATE(switch) + + /* swap context */ + setx __context, %g2, %g3 + ldx [%g3], %g2 + stx %g1, [%g3] + mov %g2, %g1 + + ba __set_context
__switch_context_nosave: /* Interrupts are not allowed... */ @@ -72,53 +62,28 @@ __switch_context_nosave: */ setx __context, %g2, %g1 ldx [%g1], %g1 - ldx [%g1 + 16], %g2 - ldx [%g1 + 24], %g3 - ldx [%g1 + 32], %g4 - ldx [%g1 + 40], %g5 - ldx [%g1 + 48], %g6 - ldx [%g1 + 56], %g7 - - ldx [%g1 + 64], %o0 - ldx [%g1 + 72], %o1 - ldx [%g1 + 80], %o2 - ldx [%g1 + 88], %o3 - ldx [%g1 + 96], %o4 - ldx [%g1 + 104], %o5 - ldx [%g1 + 112], %o6 - ldx [%g1 + 120], %o7 - - ldx [%g1 + 128], %l0 - ldx [%g1 + 136], %l1 - ldx [%g1 + 144], %l2 - ldx [%g1 + 152], %l3 - ldx [%g1 + 160], %l4 - ldx [%g1 + 168], %l5 - ldx [%g1 + 176], %l6 - ldx [%g1 + 184], %l7 - - ldx [%g1 + 192], %i0 - ldx [%g1 + 200], %i1 - ldx [%g1 + 208], %i2 - ldx [%g1 + 216], %i3 - ldx [%g1 + 224], %i4 - ldx [%g1 + 232], %i5 - ldx [%g1 + 240], %i6 - ldx [%g1 + 248], %i7 - - ldx [%g1 + 256], %g1 - /* Finally, load new %pc */ - jmp %g1 - clr %g1 + +__set_context: + RESTORE_CPU_STATE(switch) + + /* Restore globals */ + mov %g1, %g2 + add %g2, 0x30, %g2 + stx %g2, [%sp + 2047 - 192] + + ldx [%g1 + 0x38], %g2 + ldx [%g1 + 0x40], %g3 + ldx [%g1 + 0x48], %g4 + ldx [%g1 + 0x50], %g5 + ldx [%g1 + 0x58], %g6 + ldx [%g1 + 0x60], %g7 + + /* Finally, load new %pc */ + ldx [%g1 + 0x4d0], %g1 + jmpl %g1, %o7 + ldx [%sp + 2047 - 192], %g1
__exit_context: /* Get back to the original context */ - call __switch_context - nop - - /* We get here if the other context attempt to switch to this - * dead context. This should not happen. */ - -halt: - b halt + ba __switch_context nop