Author: blueswirl Date: 2009-07-11 14:25:26 +0200 (Sat, 11 Jul 2009) New Revision: 508
Modified: trunk/openbios-devel/arch/sparc64/aoutload.c trunk/openbios-devel/arch/sparc64/boot.c trunk/openbios-devel/arch/sparc64/boot.h trunk/openbios-devel/arch/sparc64/build.xml trunk/openbios-devel/arch/sparc64/context.c trunk/openbios-devel/arch/sparc64/context.h trunk/openbios-devel/arch/sparc64/switch.S Log: sparc64: fix registers dealing with client (Igor Kovalenko)
Signed-off-by: igor.v.kovalenko@gmail.com
Modified: trunk/openbios-devel/arch/sparc64/aoutload.c =================================================================== --- trunk/openbios-devel/arch/sparc64/aoutload.c 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/aoutload.c 2009-07-11 12:25:26 UTC (rev 508) @@ -125,19 +125,10 @@ debug("entry point is %#lx\n", start); printf("Jumping to entry point...\n");
-#if 1 { - int (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5); - extern int of_client_interface( int *params ); - - entry = (void *) addr_fixup(start); - - __asm__ __volatile__("clr %i3\n"); - - image_retval = entry(0, 0, 0, 0, (unsigned long)&of_client_interface); + extern int sparc64_of_client_interface( int *params ); + image_retval = start_client_image(addr_fixup(start), (uint64_t)&sparc64_of_client_interface); } -#endif
printf("Image returned with return value %#x\n", image_retval); retval = 0;
Modified: trunk/openbios-devel/arch/sparc64/boot.c =================================================================== --- trunk/openbios-devel/arch/sparc64/boot.c 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/boot.c 2009-07-11 12:25:26 UTC (rev 508) @@ -26,11 +26,11 @@ if (kernel_size) { void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5); - extern int of_client_interface( int *params ); + extern int sparc64_of_client_interface( int *params );
printk("[sparc64] Kernel already loaded\n"); entry = (void *) (unsigned long)kernel_image; - entry(0, 0, 0, 0, (unsigned long)&of_client_interface); + entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface); }
if(!path) {
Modified: trunk/openbios-devel/arch/sparc64/boot.h =================================================================== --- trunk/openbios-devel/arch/sparc64/boot.h 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/boot.h 2009-07-11 12:25:26 UTC (rev 508) @@ -22,8 +22,9 @@ int fcode_load(const char *filename);
// context.c -extern struct context *__context; +extern struct context * volatile __context; uint64_t start_elf(uint64_t entry_point, uint64_t param); +uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler);
// boot.c extern struct sys_info sys_info;
Modified: trunk/openbios-devel/arch/sparc64/build.xml =================================================================== --- trunk/openbios-devel/arch/sparc64/build.xml 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/build.xml 2009-07-11 12:25:26 UTC (rev 508) @@ -29,6 +29,10 @@ <rule><![CDATA[ $(SRCDIR)/arch/sparc64/vectors.S $(CC) $$EXTRACFLAGS $(AS_FLAGS) $(CFLAGS) $(INCLUDES) -c -o $@ $^]]></rule> </executable> + <executable name="target/arch/sparc64/call-client.o" target="target"> + <rule><![CDATA[ $(SRCDIR)/arch/sparc64/call-client.S + $(CC) $$EXTRACFLAGS $(AS_FLAGS) $(CFLAGS) $(INCLUDES) -c -o $@ $^]]></rule> + </executable>
<executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF"> <rule> @@ -39,6 +43,7 @@ <object source="plainboot.c"/> <external-object source="target/arch/sparc64/vectors.o"/> <external-object source="target/arch/sparc64/entry.o"/> + <external-object source="target/arch/sparc64/call-client.o"/> <external-object source="libsparc64.a"/> <external-object source="libbootstrap.a"/> <external-object source="libdrivers.a"/> @@ -77,6 +82,7 @@ <external-object source="target/arch/sparc64/vectors.o"/> <external-object source="target/arch/sparc64/entry.o"/> <external-object source="target/arch/sparc64/builtin.o"/> + <external-object source="target/arch/sparc64/call-client.o"/> <external-object source="libsparc64.a"/> <external-object source="libbootstrap.a"/> <external-object source="libdrivers.a"/>
Modified: trunk/openbios-devel/arch/sparc64/context.c =================================================================== --- trunk/openbios-devel/arch/sparc64/context.c 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/context.c 2009-07-11 12:25:26 UTC (rev 508) @@ -10,7 +10,7 @@ #include "boot.h"
#define MAIN_STACK_SIZE 16384 -#define IMAGE_STACK_SIZE 4096 +#define IMAGE_STACK_SIZE 4096*2
#define debug printk
@@ -23,7 +23,7 @@ * to start us up. */ static struct context main_ctx = { - .regs[REG_SP] = (uint64_t) &_estack - 2047 - 96, + .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, @@ -31,7 +31,7 @@
/* This is used by assembly routine to load/store the context which * it is to switch/switched. */ -struct context *__context = &main_ctx; +struct context * volatile __context = &main_ctx;
/* Stack for loaded ELF image */ static uint8_t image_stack[IMAGE_STACK_SIZE]; @@ -62,19 +62,25 @@ __context = boot_ctx; }
+static uint64_t ALIGN_SIZE(uint64_t x, uint64_t a) +{ + return (x + a - 1) & ~(a-1); +} + /* Setup a new context using the given stack. */ struct context * init_context(uint8_t *stack, uint64_t stack_size, int num_params) { struct context *ctx; + uint8_t *stack_top = stack + stack_size;
ctx = (struct context *) - (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t))); + (stack_top - ALIGN_SIZE(sizeof(*ctx) + num_params*sizeof(uint64_t), sizeof(uint64_t))); memset(ctx, 0, sizeof(*ctx));
/* Fill in reasonable default for flat memory model */ - ctx->regs[REG_SP] = virt_to_phys(SP_LOC(ctx)); + ctx->regs[REG_SP] = virt_to_phys(stack_top - STACK_BIAS - 192); ctx->return_addr = virt_to_phys(__exit_context);
return ctx; @@ -85,10 +91,11 @@ { struct context *save, *ret;
- debug("switching to new context:\n"); + debug("switching to new context: entry point %#llx stack 0x%016llx\n", ctx->pc, ctx->regs[REG_SP]); save = __context; __context = ctx; //asm ("pushl %cs; call __switch_context"); + asm ("call __switch_context_nosave; nop"); ret = __context; __context = save; return ret; @@ -109,3 +116,18 @@ //return ctx->eax; return 0; } + +/* Start client image */ +uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 0); + ctx->pc = entry_point; + ctx->npc = entry_point+4; + ctx->regs[REG_O0+4] = cif_handler; + + ctx = switch_to(ctx); + + return 0; +}
Modified: trunk/openbios-devel/arch/sparc64/context.h =================================================================== --- trunk/openbios-devel/arch/sparc64/context.h 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/context.h 2009-07-11 12:25:26 UTC (rev 508) @@ -1,6 +1,8 @@ #ifndef SPARC64_CONTEXT_H #define SPARC64_CONTEXT_H
+#define STACK_BIAS 2047 + struct context { /* General registers */ uint64_t regs[32];
Modified: trunk/openbios-devel/arch/sparc64/switch.S =================================================================== --- trunk/openbios-devel/arch/sparc64/switch.S 2009-07-11 12:23:24 UTC (rev 507) +++ trunk/openbios-devel/arch/sparc64/switch.S 2009-07-11 12:25:26 UTC (rev 508) @@ -24,7 +24,12 @@
/* 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] @@ -61,7 +66,8 @@
__switch_context_nosave: /* Interrupts are not allowed... */ - + /* make sure caller's windows are on caller's stack */ + flushw /* Load all registers */ setx __context, %g2, %g1