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>

git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@827 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Blue Swirl
2010-08-01 14:37:04 +00:00
parent 9daf539c27
commit f4564e0dc0
3 changed files with 118 additions and 87 deletions

View File

@@ -15,6 +15,7 @@
#include "libopenbios/forth_load.h" #include "libopenbios/forth_load.h"
#include "openprom.h" #include "openprom.h"
#include "boot.h" #include "boot.h"
#include "context.h"
uint32_t kernel_image; uint32_t kernel_image;
uint32_t kernel_size; uint32_t kernel_size;
@@ -22,8 +23,6 @@ uint32_t qemu_cmdline;
uint32_t cmdline_size; uint32_t cmdline_size;
char boot_device; char boot_device;
static const void *romvec; 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) static int try_path(const char *path, char *param)
{ {
@@ -107,22 +106,22 @@ void go(void)
switch (type) { switch (type) {
case 0x0: case 0x0:
/* Start ELF boot image */ /* Start ELF boot image */
entry = (void *) address; image_retval = start_elf((unsigned long)address,
image_retval = entry(romvec, 0, 0, 0, 0); (unsigned long)romvec);
break; break;
case 0x1: case 0x1:
/* Start ELF image */ /* Start ELF image */
entry = (void *) address; image_retval = start_elf((unsigned long)address,
image_retval = entry(romvec, 0, 0, 0, 0); (unsigned long)romvec);
break; break;
case 0x5: case 0x5:
/* Start a.out image */ /* Start a.out image */
entry = (void *) address; image_retval = start_elf((unsigned long)address,
image_retval = entry(romvec, 0, 0, 0, 0); (unsigned long)romvec);
break; break;
@@ -211,8 +210,7 @@ void boot(void)
if (kernel_size) { if (kernel_size) {
printk("[sparc] Kernel already loaded\n"); printk("[sparc] Kernel already loaded\n");
entry = (void *) kernel_image; start_elf(kernel_image, (unsigned long)romvec);
entry(romvec, 0, 0, 0, 0);
} }
printk("[sparc] Booting file '%s' ", path); printk("[sparc] Booting file '%s' ", path);

View File

@@ -83,14 +83,24 @@ init_context(uint8_t *stack, uint32_t stack_size, int num_params)
/* Switch to another context. */ /* Switch to another context. */
struct context *switch_to(struct context *ctx) struct context *switch_to(struct context *ctx)
{ {
struct context *save, *ret; volatile struct context *save;
struct context *ret;
debug("switching to new context:\n"); debug("switching to new context:\n");
save = __context; save = __context;
__context = ctx; __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; ret = __context;
__context = save; __context = (struct context *)save;
return ret; return ret;
} }
@@ -102,10 +112,7 @@ unsigned int start_elf(unsigned long entry_point, unsigned long param)
ctx = init_context(image_stack, sizeof image_stack, 1); ctx = init_context(image_stack, sizeof image_stack, 1);
ctx->pc = entry_point; ctx->pc = entry_point;
ctx->param[0] = param; ctx->param[0] = param;
//ctx->eax = 0xe1fb007;
//ctx->ebx = param;
ctx = switch_to(ctx); ctx = switch_to(ctx);
//return ctx->eax; return ctx->regs[REG_O0];
return 0;
} }

View File

@@ -8,6 +8,16 @@
.text .text
.align 4 .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 * Switch execution context
* This saves registers in the stack, then * This saves registers in the stack, then
@@ -18,45 +28,48 @@
* this routine to get back to the original context. * this routine to get back to the original context.
*/ */
/* XXX: totally bogus for sparc, need to save and restore all windows */
__switch_context: __switch_context:
/* Save everything in current stack */ FLUSH_ALL_KERNEL_WINDOWS
set __context, %g1 /* Save everything in stack */
st %g2, [%g1 + 8] st %fp, [%fp + 120 -144]
st %g3, [%g1 + 12] add %fp, -144, %fp
st %g4, [%g1 + 16] st %g1, [%fp + 4]
st %g5, [%g1 + 20] st %g2, [%fp + 8]
st %g6, [%g1 + 24] st %g3, [%fp + 12]
st %g7, [%g1 + 28] st %g4, [%fp + 16]
st %g5, [%fp + 20]
st %g6, [%fp + 24]
st %g7, [%fp + 28]
st %o0, [%g1 + 32] st %o0, [%fp + 32]
st %o1, [%g1 + 36] st %o1, [%fp + 36]
st %o2, [%g1 + 40] st %o2, [%fp + 40]
st %o3, [%g1 + 44] st %o3, [%fp + 44]
st %o4, [%g1 + 48] st %o4, [%fp + 48]
st %o5, [%g1 + 52] st %o5, [%fp + 52]
st %o6, [%g1 + 56] st %sp, [%fp + 56]
st %o7, [%g1 + 60] st %o7, [%fp + 60]
st %l0, [%g1 + 64] st %l0, [%fp + 64]
st %l1, [%g1 + 68] st %l1, [%fp + 68]
st %l2, [%g1 + 72] st %l2, [%fp + 72]
st %l3, [%g1 + 76] st %l3, [%fp + 76]
st %l4, [%g1 + 80] st %l4, [%fp + 80]
st %l5, [%g1 + 84] st %l5, [%fp + 84]
st %l6, [%g1 + 88] st %l6, [%fp + 88]
st %l7, [%g1 + 92] st %l7, [%fp + 92]
st %i0, [%g1 + 96] st %i0, [%fp + 96]
st %i1, [%g1 + 100] st %i1, [%fp + 100]
st %i2, [%g1 + 104] st %i2, [%fp + 104]
st %i3, [%g1 + 108] st %i3, [%fp + 108]
st %i4, [%g1 + 112] st %i4, [%fp + 112]
st %i5, [%g1 + 116] st %i5, [%fp + 116]
st %i6, [%g1 + 120] st %i7, [%fp + 124]
st %i7, [%g1 + 124]
/* ctx->return_address: Return to caller */
st %o7, [%fp + 128]
__switch_context_nosave:
/* Interrupts are not allowed... */ /* Interrupts are not allowed... */
/* Turn on Supervisor, EnableFloating, and all the PIL bits. /* Turn on Supervisor, EnableFloating, and all the PIL bits.
@@ -67,49 +80,62 @@ __switch_context_nosave:
wr %g2, 0x0, %psr wr %g2, 0x0, %psr
#endif #endif
/* Load all registers __switch_context_nosave:
*/
set __context, %g1 set __context, %g1
ld [%g1], %g1 /* Swap ctx pointer with %fp */
ld [%g1 + 8], %g2 swap [%g1], %fp
ld [%g1 + 12], %g3 /* Load all registers */
ld [%g1 + 16], %g4 /* offset 0: %g0, no need to load */
ld [%g1 + 20], %g5 ld [%fp + 4], %g1
ld [%g1 + 24], %g6 ld [%fp + 8], %g2
ld [%g1 + 28], %g7 ld [%fp + 12], %g3
ld [%fp + 16], %g4
ld [%fp + 20], %g5
ld [%fp + 24], %g6
ld [%fp + 28], %g7
ld [%g1 + 32], %o0 /* offset 32: %o0, loaded from ctx->param */
ld [%g1 + 36], %o1 ld [%fp + 36], %o1
ld [%g1 + 40], %o2 ld [%fp + 40], %o2
ld [%g1 + 44], %o3 ld [%fp + 44], %o3
ld [%g1 + 48], %o4 ld [%fp + 48], %o4
ld [%g1 + 52], %o5 ld [%fp + 52], %o5
ld [%g1 + 56], %o6 ld [%fp + 56], %sp
ld [%g1 + 60], %o7 /* offset 60: %o7, loaded from ctx->return_addr */
ld [%g1 + 64], %l0 ld [%fp + 64], %l0
ld [%g1 + 68], %l1 ld [%fp + 68], %l1
ld [%g1 + 72], %l2 ld [%fp + 72], %l2
ld [%g1 + 76], %l3 ld [%fp + 76], %l3
ld [%g1 + 80], %l4 ld [%fp + 80], %l4
ld [%g1 + 84], %l5 ld [%fp + 84], %l5
ld [%g1 + 88], %l6 ld [%fp + 88], %l6
ld [%g1 + 92], %l7 ld [%fp + 92], %l7
ld [%g1 + 96], %i0 ld [%fp + 96], %i0
ld [%g1 + 100], %i1 ld [%fp + 100], %i1
ld [%g1 + 104], %i2 ld [%fp + 104], %i2
ld [%g1 + 108], %i3 ld [%fp + 108], %i3
ld [%g1 + 112], %i4 ld [%fp + 112], %i4
ld [%g1 + 116], %i5 ld [%fp + 116], %i5
ld [%g1 + 120], %i6 ld [%fp + 124], %i7
ld [%g1 + 124], %i7
ld [%g1 + 128], %g1 /* ctx->return_addr */
/* Finally, load new %pc */ 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 jmp %g1
clr %g1 mov %y, %g1
FLUSH_ALL_KERNEL_WINDOWS
__exit_context: __exit_context:
/* Get back to the original context */ /* Get back to the original context */
call __switch_context call __switch_context