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