diff --git a/arch/sparc32/boot.h b/arch/sparc32/boot.h index 73d8451..fa701e5 100644 --- a/arch/sparc32/boot.h +++ b/arch/sparc32/boot.h @@ -13,9 +13,6 @@ int linux_load(struct sys_info *info, const char *file, const char *cmdline); 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 @@ extern struct linux_mlist_v0 *ptavail; 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); diff --git a/arch/sparc32/build.xml b/arch/sparc32/build.xml index d2eadce..222dfb7 100644 --- a/arch/sparc32/build.xml +++ b/arch/sparc32/build.xml @@ -16,6 +16,7 @@ + diff --git a/arch/sparc32/call-romvec.S b/arch/sparc32/call-romvec.S new file mode 100644 index 0000000..1e8f754 --- /dev/null +++ b/arch/sparc32/call-romvec.S @@ -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) + diff --git a/arch/sparc32/context.c b/arch/sparc32/context.c index 8a34a16..d4d8530 100644 --- a/arch/sparc32/context.c +++ b/arch/sparc32/context.c @@ -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 diff --git a/arch/sparc32/lib.c b/arch/sparc32/lib.c index 720fe43..9f4f0ac 100644 --- a/arch/sparc32/lib.c +++ b/arch/sparc32/lib.c @@ -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 diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index 22c04c3..e368d6c 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -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 diff --git a/arch/sparc32/romvec.c b/arch/sparc32/romvec.c index f6e0ca6..e915731 100644 --- a/arch/sparc32/romvec.c +++ b/arch/sparc32/romvec.c @@ -7,12 +7,15 @@ * Public License version 2 or later */ +#include + #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 @@ char obp_stdin, obp_stdout; 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 void doublewalk(__attribute__((unused)) unsigned int ptab1, { } -static int obp_nextnode(int node) +int obp_nextnode(int node) { int peer; @@ -59,7 +53,7 @@ static int obp_nextnode(int node) return peer; } -static int obp_child(int node) +int obp_child(int node) { int child; @@ -71,7 +65,7 @@ static int obp_child(int node) 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 @@ static int looks_like_string(const char *str, int len) } #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 int obp_getprop(int node, const char *name, char *value) } } -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 const char *obp_nextprop(int node, const char *name) } } -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 int obp_setprop(__attribute__((unused)) int node, } 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 @@ static void obp_reboot(char *str) for (;;) {} } -static void obp_abort(void) +void obp_abort(void) { printk("abort, power off\n"); *power_reg = 1; @@ -256,7 +266,7 @@ static void obp_abort(void) for (;;) {} } -static void obp_halt(void) +void obp_halt(void) { printk("halt, power off\n"); *power_reg = 1; @@ -264,7 +274,7 @@ static void obp_halt(void) for (;;) {} } -static int obp_devopen(char *str) +int obp_devopen(char *str) { int ret; @@ -276,7 +286,7 @@ static int obp_devopen(char *str) return ret; } -static int obp_devclose(int dev_desc) +int obp_devclose(int dev_desc) { int ret = 1; @@ -288,7 +298,7 @@ static int obp_devclose(int dev_desc) 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 @@ static int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf) 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 @@ static int obp_devread(int dev_desc, char *buf, int nbytes) 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 @@ static int obp_devwrite(int dev_desc, char *buf, int nbytes) 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 @@ static int obp_devseek(int dev_desc, int hi, int lo) return ret; } -static int obp_inst2pkg(int dev_desc) +int obp_inst2pkg(int dev_desc) { int ret; @@ -371,7 +381,7 @@ static int obp_inst2pkg(int dev_desc) 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 @@ static int obp_cpustart(__attribute__((unused))unsigned int whichcpu, 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 @@ static void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, 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 @@ init_openprom(void) 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 @@ init_openprom(void) 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; } diff --git a/arch/sparc32/romvec.h b/arch/sparc32/romvec.h new file mode 100644 index 0000000..d5103d1 --- /dev/null +++ b/arch/sparc32/romvec.h @@ -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);