vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| This has already been tested by a few people with Thinkpad X60s, using enhanced speedstep. Its important that if you test that you dont have acpicpu enabled it needs MP fixups. Secondly I would appreciate it if people running i386 on dual core or 2 way amd64 machines running i386 could give it a shot. Testing consists of scaling the hw.setperf and running md5 -t or someother kind of benchmark in a loop looking for wildly diverging times (indicating that one cpu is still running at full speed and the other is not). Of course deadlocks, panics and any odd behaviour is also important to report. If you do test with est or powernow-k8 please run your benchmarks at hw.setperf=0 and 100 before reporting any failures, there is an unresolved bug in est and powernow related to how they determin what speed to run at when they only have two states to choose from. Thanks, gwk Index: sys/arch/i386/i386/mainbus.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/i386/mainbus.c,v retrieving revision 1.35 diff -u -p -u -p -r1.35 mainbus.c --- sys/arch/i386/i386/mainbus.c 19 Mar 2007 14:33:28 -0000 1.35 +++ sys/arch/i386/i386/mainbus.c 24 Mar 2007 20:05:26 -0000 @@ -210,6 +210,10 @@ mainbus_attach(struct device *parent, st setperf_setup(&cpu_info_primary); } +#ifdef MULTIPROCESSOR + mp_setperf_init(); +#endif + #if NVESABIOS > 0 if (vbeprobe()) { mba.mba_busname = "vesabios"; Index: sys/arch/i386/i386/mp_setperf.c ================================================== ================= RCS file: sys/arch/i386/i386/mp_setperf.c diff -N sys/arch/i386/i386/mp_setperf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/i386/i386/mp_setperf.c 25 Mar 2007 20:37:14 -0000 @@ -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); +} Index: sys/arch/i386/i386/ipifuncs.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/i386/ipifuncs.c,v retrieving revision 1.6 diff -u -p -u -p -r1.6 ipifuncs.c --- sys/arch/i386/i386/ipifuncs.c 29 May 2006 09:54:16 -0000 1.6 +++ sys/arch/i386/i386/ipifuncs.c 24 Mar 2007 20:05:26 -0000 @@ -90,6 +90,7 @@ void (*ipifunc[I386_NIPI])(struct cpu_in #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 Index: sys/arch/i386/i386/machdep.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/i386/machdep.c,v retrieving revision 1.380 diff -u -p -u -p -r1.380 machdep.c --- sys/arch/i386/i386/machdep.c 19 Mar 2007 09:29:33 -0000 1.380 +++ sys/arch/i386/i386/machdep.c 24 Mar 2007 20:05:26 -0000 @@ -1408,7 +1408,7 @@ amd_family5_setup(struct cpu_info *ci) } } -#if !defined(SMALL_KERNEL) && defined(I686_CPU) && !defined(MULTIPROCESSOR) +#if !defined(SMALL_KERNEL) && defined(I686_CPU) void amd_family6_setperf_setup(struct cpu_info *ci) { @@ -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_inf { #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); Index: sys/arch/i386/include/intr.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/intr.h,v retrieving revision 1.28 diff -u -p -u -p -r1.28 intr.h --- sys/arch/i386/include/intr.h 23 Mar 2007 16:03:52 -0000 1.28 +++ sys/arch/i386/include/intr.h 24 Mar 2007 20:05:26 -0000 @@ -146,6 +146,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 Index: sys/arch/i386/include/intrdefs.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/intrdefs.h,v retrieving revision 1.6 diff -u -p -u -p -r1.6 intrdefs.h --- sys/arch/i386/include/intrdefs.h 12 Mar 2006 02:04:16 -0000 1.6 +++ sys/arch/i386/include/intrdefs.h 24 Mar 2007 20:05:26 -0000 @@ -113,13 +113,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 Index: sys/arch/i386/include/cpu.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/cpu.h,v retrieving revision 1.89 diff -u -p -u -p -r1.89 cpu.h --- sys/arch/i386/include/cpu.h 19 Mar 2007 09:29:33 -0000 1.89 +++ sys/arch/i386/include/cpu.h 24 Mar 2007 20:05:26 -0000 @@ -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 */ @@ -136,6 +136,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 }; /* @@ -401,6 +407,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 */ Index: sys/arch/i386/conf/files.i386 ================================================== ================= RCS file: /cvs/src/sys/arch/i386/conf/files.i386,v retrieving revision 1.157 diff -u -p -u -p -r1.157 files.i386 --- sys/arch/i386/conf/files.i386 19 Mar 2007 14:33:28 -0000 1.157 +++ sys/arch/i386/conf/files.i386 24 Mar 2007 20:05:26 -0000 @@ -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 |