diff options
author | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2007-04-21 21:06:16 +0000 |
---|---|---|
committer | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2007-04-21 21:06:16 +0000 |
commit | c5adacd3ca38901e85090b4cbce893ed61415b06 (patch) | |
tree | 8bdc23eb4cbf4171f38ead01cfed0e9470732c67 /sys/arch/i386 | |
parent | 1644f6fee18436748195f112e71a36a12797382a (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/i386')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/ipifuncs.c | 5 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/mainbus.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/mp_setperf.c | 138 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 19 | ||||
-rw-r--r-- | sys/arch/i386/include/intr.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/include/intrdefs.h | 7 |
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 |