Author: mcayland Date: Sun Oct 24 21:55:27 2010 New Revision: 918 URL: http://tracker.coreboot.org/trac/openbios/changeset/918
Log: Use wrappers around all romvec functions on SPARC32 to flush register window and preserve global registers.
This appears to resolve issues with OpenBIOS crashing when calling OBP functions through the romvec interface due to stack/register issues. Note that this patch also implements pv_printf() and pv_putstr() which appears to fix issues with displaying error messages during Solaris 8 boot.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk
Added: trunk/openbios-devel/arch/sparc32/call-romvec.S trunk/openbios-devel/arch/sparc32/romvec.h Modified: trunk/openbios-devel/arch/sparc32/boot.h trunk/openbios-devel/arch/sparc32/build.xml trunk/openbios-devel/arch/sparc32/context.c trunk/openbios-devel/arch/sparc32/lib.c trunk/openbios-devel/arch/sparc32/openbios.c trunk/openbios-devel/arch/sparc32/romvec.c
Modified: trunk/openbios-devel/arch/sparc32/boot.h ============================================================================== --- trunk/openbios-devel/arch/sparc32/boot.h Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/boot.h Sun Oct 24 21:55:27 2010 (r918) @@ -13,9 +13,6 @@ extern struct context *__context; unsigned int start_elf(unsigned long entry_point, unsigned long param);
-// romvec.c -void *init_openprom(void); - // boot.c extern const char *bootpath; extern void boot(void); @@ -45,10 +42,3 @@
void ob_init_mmu(void); void init_mmu_swift(void); -char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, - unsigned int size); -void obp_dumb_munmap(__attribute__((unused)) char *va, - __attribute__((unused)) unsigned int size); -char *obp_dumb_memalloc(char *va, unsigned int size); -void obp_dumb_memfree(__attribute__((unused))char *va, - __attribute__((unused))unsigned sz);
Modified: trunk/openbios-devel/arch/sparc32/build.xml ============================================================================== --- trunk/openbios-devel/arch/sparc32/build.xml Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/build.xml Sun Oct 24 21:55:27 2010 (r918) @@ -16,6 +16,7 @@ <object source="linux_load.c"/> <object source="sys_info.c"/> <object source="romvec.c"/> + <object source="call-romvec.S"/> <object source="entry.S"/> <object source="vectors.S"/> </library>
Added: trunk/openbios-devel/arch/sparc32/call-romvec.S ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/openbios-devel/arch/sparc32/call-romvec.S Sun Oct 24 21:55:27 2010 (r918) @@ -0,0 +1,92 @@ +#include "psr.h" +#include "asm/asi.h" + + .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; + +/* Macro for romvec handlers */ +#define ROMVEC_HANDLER(type) \ + \ + .globl type##_handler; \ + \ +type##_handler: \ + \ + FLUSH_ALL_KERNEL_WINDOWS; \ + \ + save %sp, -STACKFRAME_SZ - 0x20, %sp; \ + \ + st %g1, [ %sp + STACKFRAME_SZ + 0x0]; \ + st %g2, [ %sp + STACKFRAME_SZ + 0x4]; \ + st %g3, [ %sp + STACKFRAME_SZ + 0x8]; \ + st %g4, [ %sp + STACKFRAME_SZ + 0xc]; \ + st %g5, [ %sp + STACKFRAME_SZ + 0x10]; \ + st %g6, [ %sp + STACKFRAME_SZ + 0x14]; \ + st %g7, [ %sp + STACKFRAME_SZ + 0x18]; \ + \ + mov %i0, %o0; \ + mov %i1, %o1; \ + mov %i2, %o2; \ + mov %i3, %o3; \ + mov %i4, %o4; \ + mov %i5, %o5; \ + \ + call type; \ + nop; \ + \ + mov %o0, %i0; \ + \ + ld [ %sp + STACKFRAME_SZ + 0x0], %g1; \ + ld [ %sp + STACKFRAME_SZ + 0x4], %g2; \ + ld [ %sp + STACKFRAME_SZ + 0x8], %g3; \ + ld [ %sp + STACKFRAME_SZ + 0xc], %g4; \ + ld [ %sp + STACKFRAME_SZ + 0x10], %g5; \ + ld [ %sp + STACKFRAME_SZ + 0x14], %g6; \ + ld [ %sp + STACKFRAME_SZ + 0x18], %g7; \ + \ + ret; \ + restore; \ + + +/* Generate handlers which are proxy functions to the + real C functions that correctly save the globals + and stack */ +ROMVEC_HANDLER(obp_devopen) +ROMVEC_HANDLER(obp_devclose) +ROMVEC_HANDLER(obp_rdblkdev) +ROMVEC_HANDLER(obp_nbgetchar) +ROMVEC_HANDLER(obp_nbputchar) +ROMVEC_HANDLER(obp_putstr) +ROMVEC_HANDLER(obp_printf) +ROMVEC_HANDLER(obp_reboot) +ROMVEC_HANDLER(obp_abort) +ROMVEC_HANDLER(obp_halt) +ROMVEC_HANDLER(obp_fortheval_v2) +ROMVEC_HANDLER(obp_inst2pkg) +ROMVEC_HANDLER(obp_dumb_memalloc) +ROMVEC_HANDLER(obp_dumb_memfree) +ROMVEC_HANDLER(obp_dumb_mmap) +ROMVEC_HANDLER(obp_dumb_munmap) +ROMVEC_HANDLER(obp_devread) +ROMVEC_HANDLER(obp_devwrite) +ROMVEC_HANDLER(obp_devseek) +ROMVEC_HANDLER(obp_cpustart) +ROMVEC_HANDLER(obp_cpustop) +ROMVEC_HANDLER(obp_cpuidle) +ROMVEC_HANDLER(obp_cpuresume) +ROMVEC_HANDLER(obp_nextnode) +ROMVEC_HANDLER(obp_child) +ROMVEC_HANDLER(obp_proplen) +ROMVEC_HANDLER(obp_getprop) +ROMVEC_HANDLER(obp_setprop) +ROMVEC_HANDLER(obp_nextprop) +
Modified: trunk/openbios-devel/arch/sparc32/context.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/context.c Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/context.c Sun Oct 24 21:55:27 2010 (r918) @@ -11,7 +11,7 @@ #include "openbios.h"
#define MAIN_STACK_SIZE 16384 -#define IMAGE_STACK_SIZE 4096 +#define IMAGE_STACK_SIZE 4096*2
#define debug printk
Modified: trunk/openbios-devel/arch/sparc32/lib.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/lib.c Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/lib.c Sun Oct 24 21:55:27 2010 (r918) @@ -15,6 +15,7 @@ #include "openprom.h" #include "libopenbios/sys_info.h" #include "boot.h" +#include "romvec.h"
#define NCTX_SWIFT 0x100 #define LOWMEMSZ 32 * 1024 * 1024
Modified: trunk/openbios-devel/arch/sparc32/openbios.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/openbios.c Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/openbios.c Sun Oct 24 21:55:27 2010 (r918) @@ -20,6 +20,7 @@ #include "libopenbios/sys_info.h" #include "openbios.h" #include "boot.h" +#include "romvec.h" #include "openprom.h" #include "packages/video.h" #define NO_QEMU_PROTOS
Modified: trunk/openbios-devel/arch/sparc32/romvec.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/romvec.c Sun Oct 24 20:55:59 2010 (r917) +++ trunk/openbios-devel/arch/sparc32/romvec.c Sun Oct 24 21:55:27 2010 (r918) @@ -7,12 +7,15 @@ * Public License version 2 or later */
+#include <stdarg.h> + #include "openprom.h" #include "config.h" #include "libopenbios/bindings.h" #include "drivers/drivers.h" #include "libopenbios/sys_info.h" #include "boot.h" +#include "romvec.h"
#ifdef CONFIG_DEBUG_OBP #define DPRINTF(fmt, args...) \ @@ -25,15 +28,6 @@ static int obp_fd_stdin, obp_fd_stdout; const char *obp_stdin_path, *obp_stdout_path;
-static int obp_nextnode(int node); -static int obp_child(int node); -static int obp_proplen(int node, const char *name); -static int obp_getprop(int node, const char *name, char *val); -static int obp_setprop(int node, const char *name, char *val, int len); -static const char *obp_nextprop(int node, const char *name); -static int obp_devread(int dev_desc, char *buf, int nbytes); -static int obp_devseek(int dev_desc, int hi, int lo); - struct linux_arguments_v0 obp_arg; const char *bootpath; static const struct linux_arguments_v0 * const obp_argp = &obp_arg; @@ -47,7 +41,7 @@ { }
-static int obp_nextnode(int node) +int obp_nextnode(int node) { int peer;
@@ -59,7 +53,7 @@ return peer; }
-static int obp_child(int node) +int obp_child(int node) { int child;
@@ -71,7 +65,7 @@ return child; }
-static int obp_proplen(int node, const char *name) +int obp_proplen(int node, const char *name) { int notfound;
@@ -115,7 +109,7 @@ } #endif
-static int obp_getprop(int node, const char *name, char *value) +int obp_getprop(int node, const char *name, char *value) { int notfound, found; int len; @@ -178,7 +172,7 @@ } }
-static const char *obp_nextprop(int node, const char *name) +const char *obp_nextprop(int node, const char *name) { int found;
@@ -208,7 +202,7 @@ } }
-static int obp_setprop(__attribute__((unused)) int node, +int obp_setprop(__attribute__((unused)) int node, __attribute__((unused)) const char *name, __attribute__((unused)) char *value, __attribute__((unused)) int len) @@ -219,28 +213,44 @@ }
static const struct linux_nodeops nodeops0 = { - obp_nextnode, /* int (*no_nextnode)(int node); */ - obp_child, /* int (*no_child)(int node); */ - obp_proplen, /* int (*no_proplen)(int node, char *name); */ - obp_getprop, /* int (*no_getprop)(int node,char *name,char *val); */ - obp_setprop, /* int (*no_setprop)(int node, char *name, - char *val, int len); */ - obp_nextprop /* char * (*no_nextprop)(int node, char *name); */ + obp_nextnode_handler, /* int (*no_nextnode)(int node); */ + obp_child_handler, /* int (*no_child)(int node); */ + obp_proplen_handler, /* int (*no_proplen)(int node, char *name); */ + obp_getprop_handler, /* int (*no_getprop)(int node,char *name,char *val); */ + obp_setprop_handler, /* int (*no_setprop)(int node, char *name, + char *val, int len); */ + obp_nextprop_handler /* char * (*no_nextprop)(int node, char *name); */ };
-static int obp_nbgetchar(void) +int obp_nbgetchar(void) { return getchar(); }
-static int obp_nbputchar(int ch) +int obp_nbputchar(int ch) { putchar(ch);
return 0; }
-static void obp_reboot(char *str) +void obp_putstr(char *str, int len) +{ + PUSH(pointer2cell(str)); + PUSH(len); + fword("type"); +} + +void obp_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + printk(fmt, ap); + va_end(ap); +} + +void obp_reboot(char *str) { printk("rebooting (%s)\n", str); *reset_reg = 1; @@ -248,7 +258,7 @@ for (;;) {} }
-static void obp_abort(void) +void obp_abort(void) { printk("abort, power off\n"); *power_reg = 1; @@ -256,7 +266,7 @@ for (;;) {} }
-static void obp_halt(void) +void obp_halt(void) { printk("halt, power off\n"); *power_reg = 1; @@ -264,7 +274,7 @@ for (;;) {} }
-static int obp_devopen(char *str) +int obp_devopen(char *str) { int ret;
@@ -276,7 +286,7 @@ return ret; }
-static int obp_devclose(int dev_desc) +int obp_devclose(int dev_desc) { int ret = 1;
@@ -288,7 +298,7 @@ return ret; }
-static int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf) +int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf) { int ret, hi, lo, bs;
@@ -305,7 +315,7 @@ return ret; }
-static int obp_devread(int dev_desc, char *buf, int nbytes) +int obp_devread(int dev_desc, char *buf, int nbytes) { int ret;
@@ -321,7 +331,7 @@ return ret; }
-static int obp_devwrite(int dev_desc, char *buf, int nbytes) +int obp_devwrite(int dev_desc, char *buf, int nbytes) { #ifdef CONFIG_DEBUG_OBP_DEVWRITE /* disabled, makes too much noise */ int ret; @@ -342,7 +352,7 @@ return nbytes; }
-static int obp_devseek(int dev_desc, int hi, int lo) +int obp_devseek(int dev_desc, int hi, int lo) { int ret;
@@ -358,7 +368,7 @@ return ret; }
-static int obp_inst2pkg(int dev_desc) +int obp_inst2pkg(int dev_desc) { int ret;
@@ -371,7 +381,7 @@ return ret; }
-static int obp_cpustart(__attribute__((unused))unsigned int whichcpu, +int obp_cpustart(__attribute__((unused))unsigned int whichcpu, __attribute__((unused))int ctxtbl_ptr, __attribute__((unused))int thiscontext, __attribute__((unused))char *prog_counter) @@ -391,28 +401,28 @@ thiscontext, cpu); }
-static int obp_cpustop(__attribute__((unused)) unsigned int whichcpu) +int obp_cpustop(__attribute__((unused)) unsigned int whichcpu) { DPRINTF("obp_cpustop: cpu %d\n", whichcpu);
return 0; }
-static int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu) +int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu) { DPRINTF("obp_cpuidle: cpu %d\n", whichcpu);
return 0; }
-static int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu) +int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu) { DPRINTF("obp_cpuresume: cpu %d\n", whichcpu);
return 0; }
-static void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4) +void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4) { int pusharg = 0;
@@ -454,6 +464,10 @@ void * init_openprom(void) { + /* Setup the openprom vector. Note that all functions should be invoked + via their handler (see call-romvec.S) which acts as a proxy to save + the globals and setup the stack correctly */ + // Linux wants a R/W romvec table romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC; romvec0.pv_romvers = 3; @@ -464,32 +478,33 @@ romvec0.pv_v0mem.v0_available = &ptavail; romvec0.pv_nodeops = &nodeops0; romvec0.pv_bootstr = (void *)doublewalk; - romvec0.pv_v0devops.v0_devopen = &obp_devopen; - romvec0.pv_v0devops.v0_devclose = &obp_devclose; - romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev; + romvec0.pv_v0devops.v0_devopen = &obp_devopen_handler; + romvec0.pv_v0devops.v0_devclose = &obp_devclose_handler; + romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev_handler; romvec0.pv_stdin = &obp_stdin; romvec0.pv_stdout = &obp_stdout; - romvec0.pv_getchar = obp_nbgetchar; - romvec0.pv_putchar = (void (*)(int))obp_nbputchar; - romvec0.pv_nbgetchar = obp_nbgetchar; - romvec0.pv_nbputchar = obp_nbputchar; - romvec0.pv_reboot = obp_reboot; - romvec0.pv_printf = (void (*)(const char *fmt, ...))printk; - romvec0.pv_abort = obp_abort; - romvec0.pv_halt = obp_halt; + romvec0.pv_getchar = obp_nbgetchar_handler; + romvec0.pv_putchar = (void (*)(int))obp_nbputchar_handler; + romvec0.pv_nbgetchar = obp_nbgetchar_handler; + romvec0.pv_nbputchar = obp_nbputchar_handler; + romvec0.pv_putstr = obp_putstr_handler; + romvec0.pv_reboot = obp_reboot_handler; + romvec0.pv_printf = obp_printf_handler; + romvec0.pv_abort = obp_abort_handler; + romvec0.pv_halt = obp_halt_handler; romvec0.pv_synchook = &sync_hook; romvec0.pv_v0bootargs = &obp_argp; - romvec0.pv_fortheval.v2_eval = obp_fortheval_v2; - romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg; - romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc; - romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree; - romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap; - romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap; - romvec0.pv_v2devops.v2_dev_open = obp_devopen; - romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose; - romvec0.pv_v2devops.v2_dev_read = obp_devread; - romvec0.pv_v2devops.v2_dev_write = obp_devwrite; - romvec0.pv_v2devops.v2_dev_seek = obp_devseek; + romvec0.pv_fortheval.v2_eval = obp_fortheval_v2_handler; + romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg_handler; + romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc_handler; + romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree_handler; + romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap_handler; + romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap_handler; + romvec0.pv_v2devops.v2_dev_open = obp_devopen_handler; + romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose_handler; + romvec0.pv_v2devops.v2_dev_read = obp_devread_handler; + romvec0.pv_v2devops.v2_dev_write = obp_devwrite_handler; + romvec0.pv_v2devops.v2_dev_seek = obp_devseek_handler;
romvec0.pv_v2bootargs.bootpath = &bootpath;
@@ -504,10 +519,10 @@ fword("open-dev"); obp_fd_stdout = POP();
- romvec0.v3_cpustart = obp_cpustart; - romvec0.v3_cpustop = obp_cpustop; - romvec0.v3_cpuidle = obp_cpuidle; - romvec0.v3_cpuresume = obp_cpuresume; + romvec0.v3_cpustart = obp_cpustart_handler; + romvec0.v3_cpustop = obp_cpustop_handler; + romvec0.v3_cpuidle = obp_cpuidle_handler; + romvec0.v3_cpuresume = obp_cpuresume_handler;
return &romvec0; }
Added: trunk/openbios-devel/arch/sparc32/romvec.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/openbios-devel/arch/sparc32/romvec.h Sun Oct 24 21:55:27 2010 (r918) @@ -0,0 +1,76 @@ +/* + * romvec main C function and handler declarations + */ + +void *init_openprom(void); + +int obp_devopen(char *str); +int obp_devopen_handler(char *str); +int obp_devclose(int dev_desc); +int obp_devclose_handler(int dev_desc); +int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf); +int obp_rdblkdev_handler(int dev_desc, int num_blks, int offset, char *buf); +int obp_nbgetchar(void); +int obp_nbgetchar_handler(void); +int obp_nbputchar(int ch); +int obp_nbputchar_handler(int ch); +void obp_putstr(char *str, int len); +void obp_putstr_handler(char *str, int len); +void obp_printf(__const__ char *fmt, ...); +void obp_printf_handler(__const__ char *fmt, ...); +void obp_reboot(char *str); +void obp_reboot_handler(char *str); +void obp_abort(void); +void obp_abort_handler(void); +void obp_halt(void); +void obp_halt_handler(void); +void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4); +void obp_fortheval_v2_handler(char *str, int arg0, int arg1, int arg2, int arg3, int arg4); +int obp_inst2pkg(int dev_desc); +int obp_inst2pkg_handler(int dev_desc); +char *obp_dumb_memalloc(char *va, unsigned int size); +char *obp_dumb_memalloc_handler(char *va, unsigned int size); +void obp_dumb_memfree(__attribute__((unused))char *va, __attribute__((unused))unsigned sz); +void obp_dumb_memfree_handler(__attribute__((unused))char *va, __attribute__((unused))unsigned sz); +char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, unsigned int size); +char *obp_dumb_mmap_handler(char *va, int which_io, unsigned int pa, unsigned int size); +void obp_dumb_munmap(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size); +void obp_dumb_munmap_handler(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size); +int obp_devread(int dev_desc, char *buf, int nbytes); +int obp_devread_handler(int dev_desc, char *buf, int nbytes); +int obp_devwrite(int dev_desc, char *buf, int nbytes); +int obp_devwrite_handler(int dev_desc, char *buf, int nbytes); +int obp_devseek(int dev_desc, int hi, int lo); +int obp_devseek_handler(int dev_desc, int hi, int lo); +int obp_cpustart(__attribute__((unused))unsigned int whichcpu, + __attribute__((unused))int ctxtbl_ptr, + __attribute__((unused))int thiscontext, + __attribute__((unused))char *prog_counter); +int obp_cpustart_handler(__attribute__((unused))unsigned int whichcpu, + __attribute__((unused))int ctxtbl_ptr, + __attribute__((unused))int thiscontext, + __attribute__((unused))char *prog_counter); +int obp_cpustop(__attribute__((unused)) unsigned int whichcpu); +int obp_cpustop_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuidle_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuresume_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_nextnode(int node); +int obp_nextnode_handler(int node); +int obp_child(int node); +int obp_child_handler(int node); +int obp_proplen(int node, const char *name); +int obp_proplen_handler(int node, const char *name); +int obp_getprop(int node, const char *name, char *value); +int obp_getprop_handler(int node, const char *name, char *value); +int obp_setprop(__attribute__((unused)) int node, + __attribute__((unused)) const char *name, + __attribute__((unused)) char *value, + __attribute__((unused)) int len); +int obp_setprop_handler(__attribute__((unused)) int node, + __attribute__((unused)) const char *name, + __attribute__((unused)) char *value, + __attribute__((unused)) int len); +const char *obp_nextprop(int node, const char *name); +const char *obp_nextprop_handler(int node, const char *name);