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>


git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@918 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Mark Cave-Ayland
2010-10-24 19:55:27 +00:00
committed by Mark Cave-Ayland
parent fbfaaa780f
commit d92b811c6e
8 changed files with 252 additions and 76 deletions

View File

@@ -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);

View File

@@ -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>

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 @@ 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;
}

76
arch/sparc32/romvec.h Normal file
View File

@@ -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);