Module Name:    src
Committed By:   palle
Date:           Fri Apr  1 20:21:45 UTC 2016

Modified Files:
        src/sys/arch/sparc/include: openfirm.h
        src/sys/arch/sparc/sparc: openfirm.c promlib.c

Log Message:
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@


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sparc/include/openfirm.h
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/sparc/sparc/openfirm.c
cvs rdiff -u -r1.44 -r1.45 src/sys/arch/sparc/sparc/promlib.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc/include/openfirm.h
diff -u src/sys/arch/sparc/include/openfirm.h:1.9 src/sys/arch/sparc/include/openfirm.h:1.10
--- src/sys/arch/sparc/include/openfirm.h:1.9	Tue Oct  6 20:03:05 2015
+++ src/sys/arch/sparc/include/openfirm.h	Fri Apr  1 20:21:45 2016
@@ -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 *));

Index: src/sys/arch/sparc/sparc/openfirm.c
diff -u src/sys/arch/sparc/sparc/openfirm.c:1.20 src/sys/arch/sparc/sparc/openfirm.c:1.21
--- src/sys/arch/sparc/sparc/openfirm.c:1.20	Fri Mar 27 06:10:25 2015
+++ src/sys/arch/sparc/sparc/openfirm.c	Fri Apr  1 20:21:45 2016
@@ -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
 #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, i
 	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, i
 		l = args.actual;
 		act += l;
 	}
+#ifdef SUN4V
+#if __arch64__
+	mutex_exit(&ofcall_mtx);
+#endif
+#endif
 	return act;
 }
 

Index: src/sys/arch/sparc/sparc/promlib.c
diff -u src/sys/arch/sparc/sparc/promlib.c:1.44 src/sys/arch/sparc/sparc/promlib.c:1.45
--- src/sys/arch/sparc/sparc/promlib.c:1.44	Wed Mar 26 15:55:43 2014
+++ src/sys/arch/sparc/sparc/promlib.c	Fri Apr  1 20:21:45 2016
@@ -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();
 }
 
 /*

Reply via email to