summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorGordon Willem Klok <gwk@cvs.openbsd.org>2007-04-21 21:06:16 +0000
committerGordon Willem Klok <gwk@cvs.openbsd.org>2007-04-21 21:06:16 +0000
commitc5adacd3ca38901e85090b4cbce893ed61415b06 (patch)
tree8bdc23eb4cbf4171f38ead01cfed0e9470732c67 /sys/arch
parent1644f6fee18436748195f112e71a36a12797382a (diff)
Introduce a smp aware hw.setperf mechanism, it will scale all CPUs or
cores by the same amount, i.e. if you do hw.setperf=50 both cores will be scaled to the opearting state corresponing to 50%. Tested by many with est (mainly on core2duo machines like X60 thinkpads). Only enable est during GENERIC.MP build no one tested powernow. ok art@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/ipifuncs.c5
-rw-r--r--sys/arch/i386/i386/machdep.c6
-rw-r--r--sys/arch/i386/i386/mainbus.c6
-rw-r--r--sys/arch/i386/i386/mp_setperf.c138
-rw-r--r--sys/arch/i386/include/cpu.h19
-rw-r--r--sys/arch/i386/include/intr.h3
-rw-r--r--sys/arch/i386/include/intrdefs.h7
8 files changed, 171 insertions, 16 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index b659ed772dd..e19df5e86f8 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.157 2007/03/19 14:33:28 dlg Exp $
+# $OpenBSD: files.i386,v 1.158 2007/04/21 21:06:15 gwk Exp $
#
# new style config file for i386 architecture
#
@@ -45,6 +45,7 @@ file arch/i386/i386/dkcsum.c bios
file lib/libz/adler32.c !ppp_deflate & !ipsec & !crypto
file dev/cninit.c
file arch/i386/i386/mptramp.s multiprocessor
+file arch/i386/i386/mp_setperf.c multiprocessor
file arch/i386/i386/lock_machdep.c multiprocessor
file arch/i386/i386/ipifuncs.c multiprocessor
file arch/i386/i386/db_mp.c multiprocessor & ddb
diff --git a/sys/arch/i386/i386/ipifuncs.c b/sys/arch/i386/i386/ipifuncs.c
index a90e586dc54..e679fcb6a64 100644
--- a/sys/arch/i386/i386/ipifuncs.c
+++ b/sys/arch/i386/i386/ipifuncs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipifuncs.c,v 1.6 2006/05/29 09:54:16 mickey Exp $ */
+/* $OpenBSD: ipifuncs.c,v 1.7 2007/04/21 21:06:14 gwk Exp $ */
/* $NetBSD: ipifuncs.c,v 1.1.2.3 2000/06/26 02:04:06 sommerfeld Exp $ */
/*-
@@ -90,6 +90,7 @@ void (*ipifunc[I386_NIPI])(struct cpu_info *) =
#else
0,
#endif
+ i386_setperf_ipi,
};
void
@@ -169,7 +170,7 @@ i386_broadcast_ipi(int ipimask)
if (!count)
return;
- i386_ipi(LAPIC_IPI_VECTOR, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED);
+ i386_ipi(LAPIC_IPI_VECTOR, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED);
}
void
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 78445594e39..6555ed29b86 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.382 2007/04/12 20:22:58 art Exp $ */
+/* $OpenBSD: machdep.c,v 1.383 2007/04/21 21:06:14 gwk Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -1444,7 +1444,7 @@ amd_family6_setup(struct cpu_info *ci)
#endif
}
-#if !defined(SMALL_KERNEL) && defined(I686_CPU) && !defined(MULTIPROCESSOR)
+#if !defined(SMALL_KERNEL) && defined(I686_CPU)
void
intel686_setperf_setup(struct cpu_info *ci)
{
@@ -1468,9 +1468,7 @@ intel686_common_cpu_setup(struct cpu_info *ci)
{
#if !defined(SMALL_KERNEL) && defined(I686_CPU)
-#if !defined(MULTIPROCESSOR)
setperf_setup = intel686_setperf_setup;
-#endif
{
extern void (*pagezero)(void *, size_t);
extern void sse2_pagezero(void *, size_t);
diff --git a/sys/arch/i386/i386/mainbus.c b/sys/arch/i386/i386/mainbus.c
index 4ae0d4f0da8..cb396c4024d 100644
--- a/sys/arch/i386/i386/mainbus.c
+++ b/sys/arch/i386/i386/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.35 2007/03/19 14:33:28 dlg Exp $ */
+/* $OpenBSD: mainbus.c,v 1.36 2007/04/21 21:06:14 gwk Exp $ */
/* $NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej Exp $ */
/*
@@ -210,6 +210,10 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
setperf_setup(&cpu_info_primary);
}
+#ifdef MULTIPROCESSOR
+ mp_setperf_init();
+#endif
+
#if NVESABIOS > 0
if (vbeprobe()) {
mba.mba_busname = "vesabios";
diff --git a/sys/arch/i386/i386/mp_setperf.c b/sys/arch/i386/i386/mp_setperf.c
new file mode 100644
index 00000000000..0c661160592
--- /dev/null
+++ b/sys/arch/i386/i386/mp_setperf.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+
+#include <machine/cpu.h>
+
+#include <machine/intr.h>
+
+struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
+
+/* underlying setperf mechanism e.g. k8_powernow_setperf() */
+void (*ul_setperf)(int);
+
+#define MP_SETPERF_STEADY 0 /* steady state - normal operation */
+#define MP_SETPERF_INTRANSIT 1 /* in transition */
+#define MP_SETPERF_PROCEED 2 /* proceed with transition */
+#define MP_SETPERF_FINISH 3 /* return from IPI */
+
+
+/* protected by setperf_mp_mutex */
+volatile int mp_setperf_state = MP_SETPERF_STEADY;
+volatile int mp_perflevel;
+
+void mp_setperf(int);
+
+void
+mp_setperf(int level)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+ int notready, s;
+
+ if (mp_setperf_state == MP_SETPERF_STEADY) {
+ mtx_enter(&setperf_mp_mutex);
+ mp_perflevel = level;
+
+ curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT;
+ /* ask all other processors to drop what they are doing */
+ CPU_INFO_FOREACH(cii, ci) {
+ if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) {
+ ci->ci_setperf_state =
+ CI_SETPERF_SHOULDSTOP;
+ i386_send_ipi(ci, I386_IPI_SETPERF);
+ }
+ }
+
+
+ /* Loop until all processors report ready */
+ do {
+ CPU_INFO_FOREACH(cii, ci) {
+ if ((notready = (ci->ci_setperf_state
+ != CI_SETPERF_INTRANSIT)))
+ break;
+ }
+ } while (notready);
+
+ mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */
+
+ s = splipi();
+
+ ul_setperf(mp_perflevel);
+
+ splx(s);
+
+ curcpu()->ci_setperf_state = CI_SETPERF_DONE;
+ /* Loop until all processors report done */
+ do {
+ CPU_INFO_FOREACH(cii, ci) {
+ if ((notready = (ci->ci_setperf_state
+ != CI_SETPERF_DONE)))
+ break;
+ }
+ } while (notready);
+
+ mp_setperf_state = MP_SETPERF_FINISH;
+ /* delay a little for potential straglers */
+ DELAY(2);
+ curcpu()->ci_setperf_state = CI_SETPERF_READY;
+ mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */
+ mtx_leave(&setperf_mp_mutex);
+ }
+
+}
+
+void
+i386_setperf_ipi(struct cpu_info *ci)
+{
+
+ if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP)
+ ci->ci_setperf_state = CI_SETPERF_INTRANSIT;
+
+ while (mp_setperf_state != MP_SETPERF_PROCEED)
+ ;
+
+ ul_setperf(mp_perflevel);
+
+ ci->ci_setperf_state = CI_SETPERF_DONE;
+
+ while (mp_setperf_state != MP_SETPERF_FINISH)
+ ;
+ ci->ci_setperf_state = CI_SETPERF_READY;
+}
+
+void
+mp_setperf_init()
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+
+ if (!cpu_setperf)
+ return;
+ ul_setperf = cpu_setperf;
+
+ cpu_setperf = mp_setperf;
+
+ CPU_INFO_FOREACH(cii, ci) {
+ ci->ci_setperf_state = CI_SETPERF_READY;
+ }
+ mtx_init(&setperf_mp_mutex, IPL_HIGH);
+}
diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h
index af74850d454..b69f1f78dd3 100644
--- a/sys/arch/i386/include/cpu.h
+++ b/sys/arch/i386/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.91 2007/04/12 20:22:58 art Exp $ */
+/* $OpenBSD: cpu.h,v 1.92 2007/04/21 21:06:15 gwk Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@@ -65,7 +65,7 @@
#define clockframe intrframe
#include <sys/device.h>
-#include <sys/lock.h> /* will also get LOCKDEBUG */
+#include <sys/lock.h> /* will also get LOCKDEBUG */
#include <sys/sched.h>
struct intrsource;
@@ -76,7 +76,7 @@ struct cpu_info {
struct cpu_info *ci_self; /* pointer to this structure */
struct schedstate_percpu ci_schedstate; /* scheduler state */
struct cpu_info *ci_next; /* next cpu */
-
+
/*
* Public members.
*/
@@ -113,7 +113,7 @@ struct cpu_info {
u_int32_t ci_ipis; /* interprocessor interrupts pending */
int sc_apic_version;/* local APIC version */
u_int64_t ci_tscbase;
-
+
u_int32_t ci_level;
u_int32_t ci_vendor[4];
u_int32_t ci_signature; /* X86 cpuid type */
@@ -135,6 +135,12 @@ struct cpu_info {
#define CI_DDB_STOPPED 2
#define CI_DDB_ENTERDDB 3
#define CI_DDB_INDDB 4
+
+ volatile int ci_setperf_state;
+#define CI_SETPERF_READY 0
+#define CI_SETPERF_SHOULDSTOP 1
+#define CI_SETPERF_INTRANSIT 2
+#define CI_SETPERF_DONE 3
};
/*
@@ -402,6 +408,11 @@ void pmap_bootstrap(vaddr_t);
/* vm_machdep.c */
int kvtop(caddr_t);
+#ifdef MULTIPROCESSOR
+/* mp_setperf.c */
+void mp_setperf_init(void);
+#endif
+
#ifdef VM86
/* vm86.c */
void vm86_gpfault(struct proc *, int);
diff --git a/sys/arch/i386/include/intr.h b/sys/arch/i386/include/intr.h
index 63f1e93bbc0..90faf62a0bb 100644
--- a/sys/arch/i386/include/intr.h
+++ b/sys/arch/i386/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.29 2007/04/03 10:14:47 art Exp $ */
+/* $OpenBSD: intr.h,v 1.30 2007/04/21 21:06:15 gwk Exp $ */
/* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */
/*
@@ -145,6 +145,7 @@ void i386_intlock(int);
void i386_intunlock(int);
void i386_softintlock(void);
void i386_softintunlock(void);
+void i386_setperf_ipi(struct cpu_info *);
extern void (*ipifunc[I386_NIPI])(struct cpu_info *);
#endif
diff --git a/sys/arch/i386/include/intrdefs.h b/sys/arch/i386/include/intrdefs.h
index 4f5083a79fe..babc8966c3e 100644
--- a/sys/arch/i386/include/intrdefs.h
+++ b/sys/arch/i386/include/intrdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intrdefs.h,v 1.7 2007/04/12 20:22:58 art Exp $ */
+/* $OpenBSD: intrdefs.h,v 1.8 2007/04/21 21:06:15 gwk Exp $ */
/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */
#ifndef _i386_INTRDEFS_H
@@ -115,13 +115,14 @@
#define I386_IPI_MTRR 0x00000020
#define I386_IPI_GDT 0x00000040
#define I386_IPI_DDB 0x00000080 /* synchronize while in ddb */
+#define I386_IPI_SETPERF 0x00000100
-#define I386_NIPI 8
+#define I386_NIPI 9
#define I386_IPI_NAMES { "halt IPI", "timeset IPI", "FPU flush IPI", \
"FPU synch IPI", "TLB shootdown IPI", \
"MTRR update IPI", "GDT update IPI", \
- "DDB IPI" }
+ "DDB IPI", "setperf IPI" }
#define IREENT_MAGIC 0x18041969