changeset 12885:f838b80bfd58

6951326 prom_vprintf() resulted in "kern_postprom: not owner" panic
author Trevor Thompson <Trevor.Thompson@Sun.COM>
date Tue, 20 Jul 2010 16:00:05 +0100
parents 0124c84da000
children 4e09ded00759
files usr/src/psm/promif/ieee1275/common/prom_io.c
diffstat 1 files changed, 32 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/psm/promif/ieee1275/common/prom_io.c	Tue Jul 20 05:04:01 2010 -0700
+++ b/usr/src/psm/promif/ieee1275/common/prom_io.c	Tue Jul 20 16:00:05 2010 +0100
@@ -20,12 +20,9 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/promif.h>
 #include <sys/promimpl.h>
 
@@ -154,7 +151,21 @@
 	static char smallbuf[256];
 
 	ASSERT(buf);
+#endif
 
+	/*
+	 * If the callback address is set, attempt to redirect
+	 * console output back into kernel terminal emulator.
+	 */
+	if (promif_redirect != NULL && fd == prom_stdout_ihandle()) {
+		ow = promif_preout();
+		rlen = promif_redirect(promif_redirect_arg, (uchar_t *)buf,
+		    len);
+		promif_postout(ow);
+		return (rlen);
+	}
+
+#ifdef PROM_32BIT_ADDRS
 	if ((uintptr_t)buf > (uint32_t)-1) {
 		/*
 		 * This is a hack for kernel message output.
@@ -167,7 +178,6 @@
 		 * promplat_alloc() can block on a mutex and so
 		 * is called here before calling promif_preprom().
 		 */
-
 		if (len > sizeof (smallbuf)) {
 			obuf = buf;
 			buf = promplat_alloc(len);
@@ -179,11 +189,17 @@
 	}
 #endif
 
+	/*
+	 * Normally we'd call promif_preprom() just before
+	 * calling into the prom (to enforce single-threaded
+	 * access) but here we need to call it before accessing
+	 * smallbuf, since smallbuf is statically allocated and
+	 * hence can only be accessed by one thread at a time.
+	 */
 	ow = promif_preout();
 	promif_preprom();
 
 #ifdef PROM_32BIT_ADDRS
-
 	if ((uintptr_t)buf > (uint32_t)-1) {
 		/*
 		 * If buf is small enough, use smallbuf
@@ -198,33 +214,17 @@
 		}
 	}
 #endif
-	/*
-	 * If the callback address is set, attempt to redirect
-	 * console output back into kernel terminal emulator.
-	 */
-	if (promif_redirect != NULL &&
-	    fd == prom_stdout_ihandle()) {
-		/*
-		 * even if we're re-directing output to the kernel
-		 * console device, we still have to call promif_preout()
-		 * and promif_preprom() because these functions make sure
-		 * that the console device is powered up before sending
-		 * output to it.
-		 */
-		rlen = promif_redirect(promif_redirect_arg,
-		    (uchar_t *)buf, len);
-	} else {
-		ci[0] = p1275_ptr2cell("write");	/* Service name */
-		ci[1] = (cell_t)3;			/* #argument cells */
-		ci[2] = (cell_t)1;			/* #result cells */
-		ci[3] = p1275_uint2cell((uint_t)fd);	/* Arg1: ihandle */
-		ci[4] = p1275_ptr2cell(buf);		/* Arg2: buffer addr */
-		ci[5] = p1275_size2cell(len);		/* Arg3: buffer len */
-		ci[6] = (cell_t)-1;			/* Res1: Prime result */
 
-		(void) p1275_cif_handler(&ci);
-		rlen = p1275_cell2size(ci[6]);		/* Res1: actual len */
-	}
+	ci[0] = p1275_ptr2cell("write");	/* Service name */
+	ci[1] = (cell_t)3;			/* #argument cells */
+	ci[2] = (cell_t)1;			/* #result cells */
+	ci[3] = p1275_uint2cell((uint_t)fd);	/* Arg1: ihandle */
+	ci[4] = p1275_ptr2cell(buf);		/* Arg2: buffer addr */
+	ci[5] = p1275_size2cell(len);		/* Arg3: buffer len */
+	ci[6] = (cell_t)-1;			/* Res1: Prime result */
+
+	(void) p1275_cif_handler(&ci);
+	rlen = p1275_cell2size(ci[6]);		/* Res1: actual len */
 
 	promif_postprom();
 	promif_postout(ow);