Author: blueswirl Date: Sun Aug 1 16:37:04 2010 New Revision: 827 URL: http://tracker.coreboot.org/trac/openbios/changeset/827
Log: sparc32: fix context switching
Remove old hack to jump to loaded code and use switch_to().
Use FLUSH_ALL_KERNEL_WINDOWS macro from Linux.
Signed-off-by: Blue Swirl blauwirbel@gmail.com
Modified: trunk/openbios-devel/arch/sparc32/boot.c trunk/openbios-devel/arch/sparc32/context.c trunk/openbios-devel/arch/sparc32/switch.S
Modified: trunk/openbios-devel/arch/sparc32/boot.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/boot.c Sun Aug 1 13:03:45 2010 (r826) +++ trunk/openbios-devel/arch/sparc32/boot.c Sun Aug 1 16:37:04 2010 (r827) @@ -15,6 +15,7 @@ #include "libopenbios/forth_load.h" #include "openprom.h" #include "boot.h" +#include "context.h"
uint32_t kernel_image; uint32_t kernel_size; @@ -22,8 +23,6 @@ uint32_t cmdline_size; char boot_device; static const void *romvec; -static int (*entry)(const void *romvec_ptr, int p2, int p3, int p4, int p5); -
static int try_path(const char *path, char *param) { @@ -107,22 +106,22 @@ switch (type) { case 0x0: /* Start ELF boot image */ - entry = (void *) address; - image_retval = entry(romvec, 0, 0, 0, 0); + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec);
break;
case 0x1: /* Start ELF image */ - entry = (void *) address; - image_retval = entry(romvec, 0, 0, 0, 0); + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec);
break;
case 0x5: /* Start a.out image */ - entry = (void *) address; - image_retval = entry(romvec, 0, 0, 0, 0); + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec);
break;
@@ -211,8 +210,7 @@
if (kernel_size) { printk("[sparc] Kernel already loaded\n"); - entry = (void *) kernel_image; - entry(romvec, 0, 0, 0, 0); + start_elf(kernel_image, (unsigned long)romvec); }
printk("[sparc] Booting file '%s' ", path);
Modified: trunk/openbios-devel/arch/sparc32/context.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/context.c Sun Aug 1 13:03:45 2010 (r826) +++ trunk/openbios-devel/arch/sparc32/context.c Sun Aug 1 16:37:04 2010 (r827) @@ -83,14 +83,24 @@ /* Switch to another context. */ struct context *switch_to(struct context *ctx) { - struct context *save, *ret; + volatile struct context *save; + struct context *ret;
debug("switching to new context:\n"); save = __context; __context = ctx; - //asm ("pushl %cs; call __switch_context"); + asm __volatile__ ("\n\tcall __switch_context" + "\n\tnop" ::: "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "i7", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", + "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", + "f30", "f31", + "memory"); ret = __context; - __context = save; + __context = (struct context *)save; return ret; }
@@ -102,10 +112,7 @@ ctx = init_context(image_stack, sizeof image_stack, 1); ctx->pc = entry_point; ctx->param[0] = param; - //ctx->eax = 0xe1fb007; - //ctx->ebx = param;
ctx = switch_to(ctx); - //return ctx->eax; - return 0; + return ctx->regs[REG_O0]; }
Modified: trunk/openbios-devel/arch/sparc32/switch.S ============================================================================== --- trunk/openbios-devel/arch/sparc32/switch.S Sun Aug 1 13:03:45 2010 (r826) +++ trunk/openbios-devel/arch/sparc32/switch.S Sun Aug 1 16:37:04 2010 (r827) @@ -8,6 +8,16 @@ .text .align 4
+#define STACKFRAME_SZ 0x60 + +/* These are just handy. */ +#define _SV save %sp, -STACKFRAME_SZ, %sp +#define _RS restore + +#define FLUSH_ALL_KERNEL_WINDOWS \ + _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ + _RS; _RS; _RS; _RS; _RS; _RS; _RS; + /* * Switch execution context * This saves registers in the stack, then @@ -18,45 +28,48 @@ * this routine to get back to the original context. */
-/* XXX: totally bogus for sparc, need to save and restore all windows */ __switch_context: - /* Save everything in current stack */ - set __context, %g1 - st %g2, [%g1 + 8] - st %g3, [%g1 + 12] - st %g4, [%g1 + 16] - st %g5, [%g1 + 20] - st %g6, [%g1 + 24] - st %g7, [%g1 + 28] - - st %o0, [%g1 + 32] - st %o1, [%g1 + 36] - st %o2, [%g1 + 40] - st %o3, [%g1 + 44] - st %o4, [%g1 + 48] - st %o5, [%g1 + 52] - st %o6, [%g1 + 56] - st %o7, [%g1 + 60] - - st %l0, [%g1 + 64] - st %l1, [%g1 + 68] - st %l2, [%g1 + 72] - st %l3, [%g1 + 76] - st %l4, [%g1 + 80] - st %l5, [%g1 + 84] - st %l6, [%g1 + 88] - st %l7, [%g1 + 92] - - st %i0, [%g1 + 96] - st %i1, [%g1 + 100] - st %i2, [%g1 + 104] - st %i3, [%g1 + 108] - st %i4, [%g1 + 112] - st %i5, [%g1 + 116] - st %i6, [%g1 + 120] - st %i7, [%g1 + 124] + FLUSH_ALL_KERNEL_WINDOWS + /* Save everything in stack */ + st %fp, [%fp + 120 -144] + add %fp, -144, %fp + st %g1, [%fp + 4] + st %g2, [%fp + 8] + st %g3, [%fp + 12] + st %g4, [%fp + 16] + st %g5, [%fp + 20] + st %g6, [%fp + 24] + st %g7, [%fp + 28] + + st %o0, [%fp + 32] + st %o1, [%fp + 36] + st %o2, [%fp + 40] + st %o3, [%fp + 44] + st %o4, [%fp + 48] + st %o5, [%fp + 52] + st %sp, [%fp + 56] + st %o7, [%fp + 60] + + st %l0, [%fp + 64] + st %l1, [%fp + 68] + st %l2, [%fp + 72] + st %l3, [%fp + 76] + st %l4, [%fp + 80] + st %l5, [%fp + 84] + st %l6, [%fp + 88] + st %l7, [%fp + 92] + + st %i0, [%fp + 96] + st %i1, [%fp + 100] + st %i2, [%fp + 104] + st %i3, [%fp + 108] + st %i4, [%fp + 112] + st %i5, [%fp + 116] + st %i7, [%fp + 124] + + /* ctx->return_address: Return to caller */ + st %o7, [%fp + 128]
-__switch_context_nosave: /* Interrupts are not allowed... */
/* Turn on Supervisor, EnableFloating, and all the PIL bits. @@ -67,49 +80,62 @@ wr %g2, 0x0, %psr #endif
- /* Load all registers - */ +__switch_context_nosave: set __context, %g1 - ld [%g1], %g1 - ld [%g1 + 8], %g2 - ld [%g1 + 12], %g3 - ld [%g1 + 16], %g4 - ld [%g1 + 20], %g5 - ld [%g1 + 24], %g6 - ld [%g1 + 28], %g7 - - ld [%g1 + 32], %o0 - ld [%g1 + 36], %o1 - ld [%g1 + 40], %o2 - ld [%g1 + 44], %o3 - ld [%g1 + 48], %o4 - ld [%g1 + 52], %o5 - ld [%g1 + 56], %o6 - ld [%g1 + 60], %o7 - - ld [%g1 + 64], %l0 - ld [%g1 + 68], %l1 - ld [%g1 + 72], %l2 - ld [%g1 + 76], %l3 - ld [%g1 + 80], %l4 - ld [%g1 + 84], %l5 - ld [%g1 + 88], %l6 - ld [%g1 + 92], %l7 - - ld [%g1 + 96], %i0 - ld [%g1 + 100], %i1 - ld [%g1 + 104], %i2 - ld [%g1 + 108], %i3 - ld [%g1 + 112], %i4 - ld [%g1 + 116], %i5 - ld [%g1 + 120], %i6 - ld [%g1 + 124], %i7 - - ld [%g1 + 128], %g1 - /* Finally, load new %pc */ + /* Swap ctx pointer with %fp */ + swap [%g1], %fp + /* Load all registers */ + /* offset 0: %g0, no need to load */ + ld [%fp + 4], %g1 + ld [%fp + 8], %g2 + ld [%fp + 12], %g3 + ld [%fp + 16], %g4 + ld [%fp + 20], %g5 + ld [%fp + 24], %g6 + ld [%fp + 28], %g7 + + /* offset 32: %o0, loaded from ctx->param */ + ld [%fp + 36], %o1 + ld [%fp + 40], %o2 + ld [%fp + 44], %o3 + ld [%fp + 48], %o4 + ld [%fp + 52], %o5 + ld [%fp + 56], %sp + /* offset 60: %o7, loaded from ctx->return_addr */ + + ld [%fp + 64], %l0 + ld [%fp + 68], %l1 + ld [%fp + 72], %l2 + ld [%fp + 76], %l3 + ld [%fp + 80], %l4 + ld [%fp + 84], %l5 + ld [%fp + 88], %l6 + ld [%fp + 92], %l7 + + ld [%fp + 96], %i0 + ld [%fp + 100], %i1 + ld [%fp + 104], %i2 + ld [%fp + 108], %i3 + ld [%fp + 112], %i4 + ld [%fp + 116], %i5 + ld [%fp + 124], %i7 + + /* ctx->return_addr */ + ld [%fp + 136], %o7 + + /* ctx->param */ + ld [%fp + 140], %o0 + + /* ctx->pc, save %g1 to %y and load to %g1 */ + mov %g1, %y + ld [%fp + 128], %g1 + /* %fp last */ + ld [%fp + 120], %fp + /* Finally, get the new %pc from %g1 and restore %g1*/ jmp %g1 - clr %g1 + mov %y, %g1
+ FLUSH_ALL_KERNEL_WINDOWS __exit_context: /* Get back to the original context */ call __switch_context