From owner-svn-src-stable-8@FreeBSD.ORG Sun May 23 02:31:37 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A9525106564A; Sun, 23 May 2010 02:31:37 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (unknown [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8BC0F8FC13; Sun, 23 May 2010 02:31:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o4N2VbCD041229; Sun, 23 May 2010 02:31:37 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o4N2VbI1041226; Sun, 23 May 2010 02:31:37 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201005230231.o4N2VbI1041226@svn.freebsd.org> From: Nathan Whitehorn Date: Sun, 23 May 2010 02:31:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r208429 - stable/8/sys/powerpc/aim X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 May 2010 02:31:37 -0000 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 #include #include +#include #include #include @@ -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() {