svn commit: r208429 - stable/8/sys/powerpc/aim

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sun May 23 02:31:37 UTC 2010


Author: nwhitehorn
Date: Sun May 23 02:31:37 2010
New Revision: 208429
URL: http://svn.freebsd.org/changeset/base/208429

Log:
  MFC r205497,208364,208405:
  
  Fix a long-standing bug in the PowerPC OFW call function on SMP machines
  by forcing all secondary CPUs into a busy wait with interrupts off during
  the call. This bug caused ofwdump -a to hang the system.
  
  Following section 8.4 of the Open Firmware PowerPC processor binding,
  the firmware is free to overwrite the system interrupt handlers during
  OF calls, restoring the OS handlers on exit. On single CPU systems, this
  process is invisible to the operating system. On multiple CPU systems,
  taking any exception on a secondary CPU while an OF call is in progress
  ends with that exception vectored into OF, resulting in a slow movement
  of the entire system into firmware context and a machine hang.

Modified:
  stable/8/sys/powerpc/aim/ofw_machdep.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/geom/sched/   (props changed)

Modified: stable/8/sys/powerpc/aim/ofw_machdep.c
==============================================================================
--- stable/8/sys/powerpc/aim/ofw_machdep.c	Sun May 23 02:20:26 2010	(r208428)
+++ stable/8/sys/powerpc/aim/ofw_machdep.c	Sun May 23 02:31:37 2010	(r208429)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/disk.h>
 #include <sys/fcntl.h>
 #include <sys/malloc.h>
+#include <sys/smp.h>
 #include <sys/stat.h>
 
 #include <net/ethernet.h>
@@ -344,16 +345,13 @@ ofw_quiesce(void)
 }
 
 static int
-openfirmware(void *args)
+openfirmware_core(void *args)
 {
 	long	oldmsr;
 	int	result;
 	u_int	srsave[16];
 	u_int   i;
 
-	if (pmap_bootstrapped && ofw_real_mode)
-		args = (void *)pmap_kextract((vm_offset_t)args);
-
 	__asm __volatile(	"\t"
 		"sync\n\t"
 		"mfmsr  %0\n\t"
@@ -409,6 +407,61 @@ openfirmware(void *args)
 	return (result);
 }
 
+#ifdef SMP
+struct ofw_rv_args {
+	void *args;
+	int retval;
+	volatile int in_progress;
+};
+
+static void
+ofw_rendezvous_dispatch(void *xargs)
+{
+	struct ofw_rv_args *rv_args = xargs;
+
+	/* NOTE: Interrupts are disabled here */
+
+	if (PCPU_GET(cpuid) == 0) {
+		/*
+		 * Execute all OF calls on CPU 0
+		 */
+		rv_args->retval = openfirmware_core(rv_args->args);
+		rv_args->in_progress = 0;
+	} else {
+		/*
+		 * Spin with interrupts off on other CPUs while OF has
+		 * control of the machine.
+		 */
+		while (rv_args->in_progress)
+			cpu_spinwait();
+	}
+}
+#endif
+
+static int
+openfirmware(void *args)
+{
+	int result;
+	#ifdef SMP
+	struct ofw_rv_args rv_args;
+	#endif
+
+	if (pmap_bootstrapped && ofw_real_mode)
+		args = (void *)pmap_kextract((vm_offset_t)args);
+
+	#ifdef SMP
+	rv_args.args = args;
+	rv_args.in_progress = 1;
+	smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,
+	    smp_no_rendevous_barrier, &rv_args);
+	result = rv_args.retval;
+	#else
+	result = openfirmware_core(args);
+	#endif
+
+	return (result);
+}
+
 void
 OF_halt()
 {


More information about the svn-src-stable-8 mailing list