Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc64 Select the shutdown method for secondary CP...



details:   https://anonhg.NetBSD.org/src/rev/103fa4c03965
branches:  trunk
changeset: 752238:103fa4c03965
user:      martin <martin%NetBSD.org@localhost>
date:      Sat Feb 20 16:46:38 2010 +0000

description:
Select the shutdown method for secondary CPUs by available firmware
methods, not properties of the CPU.
Inspired by OpenSolaris, pointed out by eeh.

diffstat:

 sys/arch/sparc64/include/sparc64.h     |   5 +++-
 sys/arch/sparc64/sparc64/ipifuncs.c    |  37 ++++++++++++++++++++++++++-----
 sys/arch/sparc64/sparc64/ofw_machdep.c |  40 +++++++++++++++++++++++++++++++--
 3 files changed, 72 insertions(+), 10 deletions(-)

diffs (175 lines):

diff -r 448bdd7e16a0 -r 103fa4c03965 sys/arch/sparc64/include/sparc64.h
--- a/sys/arch/sparc64/include/sparc64.h        Sat Feb 20 15:04:03 2010 +0000
+++ b/sys/arch/sparc64/include/sparc64.h        Sat Feb 20 16:46:38 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sparc64.h,v 1.10 2009/05/18 12:15:26 nakayama Exp $    */
+/*     $NetBSD: sparc64.h,v 1.11 2010/02/20 16:46:38 martin Exp $      */
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -51,6 +51,9 @@
 paddr_t prom_get_msgbuf(int, int);
 
 void prom_stopself(void);
+bool prom_has_stopself(void);
+int  prom_stop_other(u_int);
+bool prom_has_stop_other(void);
 void prom_startcpu(u_int, void *, u_long);
 
 #endif /* _MACHINE_SPARC64_H_ */
diff -r 448bdd7e16a0 -r 103fa4c03965 sys/arch/sparc64/sparc64/ipifuncs.c
--- a/sys/arch/sparc64/sparc64/ipifuncs.c       Sat Feb 20 15:04:03 2010 +0000
+++ b/sys/arch/sparc64/sparc64/ipifuncs.c       Sat Feb 20 16:46:38 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipifuncs.c,v 1.30 2010/02/02 04:28:56 mrg Exp $ */
+/*     $NetBSD: ipifuncs.c,v 1.31 2010/02/20 16:46:38 martin Exp $ */
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.30 2010/02/02 04:28:56 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.31 2010/02/20 16:46:38 martin Exp $");
 
 #include "opt_ddb.h"
 
@@ -53,6 +53,7 @@
 
 /* CPU sets containing halted, paused and resumed cpus */
 static volatile sparc64_cpuset_t cpus_halted;
+static volatile sparc64_cpuset_t cpus_spinning;
 static volatile sparc64_cpuset_t cpus_paused;
 static volatile sparc64_cpuset_t cpus_resumed;
 
@@ -78,16 +79,19 @@
        extern void prom_printf(const char *fmt, ...);
 
        printf("cpu%d: shutting down\n", cpu_number());
-       CPUSET_ADD(cpus_halted, cpu_number());
-       if (CPU_IS_USIII_UP()) {
+       if (prom_has_stop_other() || !prom_has_stopself()) {
                /*
-                * prom_selfstop() doesn't seem to work on newer machines.
+                * just loop here, the final cpu will stop us later
                 */
+               CPUSET_ADD(cpus_spinning, cpu_number());
+               CPUSET_ADD(cpus_halted, cpu_number());
                spl0();
                while (1)
                        /* nothing */;
-       } else
+       } else {
+               CPUSET_ADD(cpus_halted, cpu_number());
                prom_stopself();
+       }
 }
 
 void
@@ -151,6 +155,7 @@
 
        /* Clear all cpu sets. */
        CPUSET_CLEAR(cpus_halted);
+       CPUSET_CLEAR(cpus_spinning);
        CPUSET_CLEAR(cpus_paused);
        CPUSET_CLEAR(cpus_resumed);
 }
@@ -272,6 +277,7 @@
 mp_halt_cpus(void)
 {
        sparc64_cpuset_t cpumask, cpuset;
+       struct cpu_info *ci;
 
        CPUSET_ASSIGN(cpuset, cpus_active);
        CPUSET_DEL(cpuset, cpu_number());
@@ -281,9 +287,28 @@
        if (CPUSET_EMPTY(cpuset))
                return;
 
+       CPUSET_CLEAR(cpus_spinning);
        sparc64_multicast_ipi(cpuset, sparc64_ipi_halt, 0, 0);
        if (sparc64_ipi_wait(&cpus_halted, cpumask))
                sparc64_ipi_error("halt", cpumask, cpus_halted);
+
+       /*
+        * Depending on available firmware methods, other cpus will
+        * either shut down themselfs, or spin and wait for us to
+        * stop them.
+        */
+       if (CPUSET_EMPTY(cpus_spinning)) {
+               /* give other cpus a few cycles to actually power down */
+               delay(10000);
+               return;
+       }
+       /* there are cpus spinning - shut them down if we can */
+       if (prom_has_stop_other()) {
+               for (ci = cpus; ci != NULL; ci = ci->ci_next) {
+                       if (!CPUSET_HAS(cpus_spinning, ci->ci_index)) continue;
+                       prom_stop_other(ci->ci_cpuid);
+               }
+       }
 }
 
 /*
diff -r 448bdd7e16a0 -r 103fa4c03965 sys/arch/sparc64/sparc64/ofw_machdep.c
--- a/sys/arch/sparc64/sparc64/ofw_machdep.c    Sat Feb 20 15:04:03 2010 +0000
+++ b/sys/arch/sparc64/sparc64/ofw_machdep.c    Sat Feb 20 16:46:38 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ofw_machdep.c,v 1.36 2009/11/26 20:15:20 mrg Exp $     */
+/*     $NetBSD: ofw_machdep.c,v 1.37 2010/02/20 16:46:38 martin Exp $  */
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -34,7 +34,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.36 2009/11/26 20:15:20 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.37 2010/02/20 16:46:38 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -575,7 +575,41 @@
        args.nreturns = 0;
 
        openfirmware_exit(&args);
-       panic("sun4u_stopself: failed.");
+       panic("prom_stopself: failed.");
+}
+
+bool
+prom_has_stopself(void)
+{
+       return OF_test("SUNW,stop-self") == 0;
+}
+
+int
+prom_stop_other(u_int id)
+{
+       static struct {
+               cell_t  name;
+               cell_t  nargs;
+               cell_t  nreturns;
+               cell_t  cpuid;
+               cell_t  result;
+       } args;
+
+       args.name = ADR2CELL(&"SUNW,stop-cpu-by-cpuid");
+       args.nargs = 1;
+       args.nreturns = 1;
+       args.cpuid = id;
+       args.result = 0;
+
+       if (openfirmware(&args) == -1)
+               return -1;
+       return args.result;
+}
+
+bool
+prom_has_stop_other(void)
+{
+       return OF_test("SUNW,stop-cpu-by-cpuid") == 0;
 }
 #endif
 



Home | Main Index | Thread Index | Old Index