sun4v: Workaround for OpenBoot feature where a 64-bit address is truncated to a 32-bit address. This happends when a write to the console (/virtual-devices@100/console@1) is done. Avoid this by using a static buffer that is mapped below 4GB. Thanks to Tarl Neustaedter for explaining how OpenBoot works. ok martin@
This commit is contained in:
parent
8b22ec00d4
commit
0059b91df1
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: openfirm.h,v 1.9 2015/10/06 20:03:05 martin Exp $ */
|
||||
/* $NetBSD: openfirm.h,v 1.10 2016/04/01 20:21:45 palle Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
@ -61,6 +61,7 @@ typedef uint32_t cell_t;
|
||||
#define HDQ2CELL_LO(x) (cell_t)(x)
|
||||
#endif /* __sparc_v9__ */
|
||||
|
||||
void OF_init(void);
|
||||
int OF_test(const char *);
|
||||
int OF_test_method(int, const char *);
|
||||
void OF_set_symbol_lookup(void (*)(void *), void (*)(void *));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: openfirm.c,v 1.20 2015/03/27 06:10:25 nakayama Exp $ */
|
||||
/* $NetBSD: openfirm.c,v 1.21 2016/04/01 20:21:45 palle Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.20 2015/03/27 06:10:25 nakayama Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.21 2016/04/01 20:21:45 palle Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -44,6 +44,34 @@ __KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.20 2015/03/27 06:10:25 nakayama Exp $
|
||||
#include <sys/stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef SUN4V
|
||||
#ifdef __arch64__
|
||||
#define OFBOUNCE_MAXSIZE 1024
|
||||
/*
|
||||
* Sun4v OpenBoot is not always happy with 64-bit addresses - an example is the
|
||||
* addr parameter in the OF_write() call which can be truncated to a 32-bit
|
||||
* value.
|
||||
* Avoid this behaviour by using a static buffer which is assumed to be mapped
|
||||
* in on a 32-bit address.
|
||||
* Use a mutex to protect access to the buffer from multiple threads.
|
||||
*
|
||||
*/
|
||||
kmutex_t ofcall_mtx;
|
||||
static char ofbounce[OFBOUNCE_MAXSIZE];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
OF_init(void)
|
||||
{
|
||||
#ifdef SUN4V
|
||||
#ifdef __arch64__
|
||||
KASSERT(((uint64_t)&ofbounce & 0xffffffffUL)==(uint64_t)&ofbounce);
|
||||
mutex_init(&ofcall_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
OF_peer(int phandle)
|
||||
{
|
||||
@ -512,6 +540,15 @@ OF_write(int handle, const void *addr, int len)
|
||||
if (len > 1024) {
|
||||
panic("OF_write(len = %d)\n", len);
|
||||
}
|
||||
#ifdef SUN4V
|
||||
#if __arch64__
|
||||
mutex_enter(&ofcall_mtx);
|
||||
if (len > OFBOUNCE_MAXSIZE)
|
||||
panic("OF_write(len = %d) exceedes bounce buffer\n", len);
|
||||
memcpy(ofbounce, addr, len);
|
||||
addr = ofbounce;
|
||||
#endif
|
||||
#endif
|
||||
args.name = ADR2CELL("write");
|
||||
args.nargs = 3;
|
||||
args.nreturns = 1;
|
||||
@ -525,6 +562,11 @@ OF_write(int handle, const void *addr, int len)
|
||||
l = args.actual;
|
||||
act += l;
|
||||
}
|
||||
#ifdef SUN4V
|
||||
#if __arch64__
|
||||
mutex_exit(&ofcall_mtx);
|
||||
#endif
|
||||
#endif
|
||||
return act;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: promlib.c,v 1.44 2014/03/26 15:55:43 christos Exp $ */
|
||||
/* $NetBSD: promlib.c,v 1.45 2016/04/01 20:21:45 palle Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: promlib.c,v 1.44 2014/03/26 15:55:43 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: promlib.c,v 1.45 2016/04/01 20:21:45 palle Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_sparc_arch.h"
|
||||
@ -1276,6 +1276,8 @@ prom_init_opf(void)
|
||||
node = findchosen();
|
||||
OF_getprop(node, "stdin", &promops.po_stdin, sizeof(int));
|
||||
OF_getprop(node, "stdout", &promops.po_stdout, sizeof(int));
|
||||
|
||||
OF_init();
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user