mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
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:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user