patch: please test buildkernel
Nate Lawson
nate at root.org
Mon Jan 31 22:58:23 PST 2005
The attached patch adds a new interface. It works on i386 but I need
compile testing on amd64, ia64, and one other arch (sparc, powerpc, etc.)
Thanks!
--
Nate
-------------- next part --------------
Index: sys/cpu.h
===================================================================
RCS file: sys/cpu.h
diff -N sys/cpu.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/cpu.h 1 Feb 2005 06:53:21 -0000
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2005 Nate Lawson (SDG)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_CPU_H_
+#define _SYS_CPU_H_
+
+/*
+ * CPU device support.
+ */
+
+#define CPU_IVAR_PCPU 1
+
+static __inline struct pcpu *cpu_get_pcpu(device_t dev)
+{
+ uintptr_t v = 0;
+ BUS_READ_IVAR(device_get_parent(dev), dev, CPU_IVAR_PCPU, &v);
+ return ((struct pcpu *)v);
+}
+
+/*
+ * CPU frequency control interface.
+ */
+
+/* Each driver's CPU frequency setting is exported in this format. */
+struct cf_setting {
+ int freq; /* Processor clock in Mhz or percent (in 100ths.) */
+ int volts; /* Voltage in mV. */
+ int power; /* Power consumed in mW. */
+ int lat; /* Transition latency in us. */
+ device_t dev; /* Driver providing this setting. */
+};
+
+/* Maximum number of settings a given driver can have. */
+#define MAX_SETTINGS 16
+
+/* A combination of settings is a level. */
+struct cf_level {
+ struct cf_setting total_set;
+ struct cf_setting abs_set;
+ struct cf_setting rel_set[MAX_SETTINGS];
+ int rel_count;
+ TAILQ_ENTRY(cf_level) link;
+};
+
+TAILQ_HEAD(cf_level_lst, cf_level);
+
+/* Drivers should set all unknown values to this. */
+#define CPUFREQ_VAL_UNKNOWN (-1)
+
+/*
+ * Every driver offers a type of CPU control. Absolute levels are mutually
+ * exclusive while relative levels modify the current absolute level. There
+ * may be multiple absolute and relative drivers available on a given
+ * system.
+ *
+ * For example, consider a system with two absolute drivers that provide
+ * frequency settings of 100, 200 and 300, 400 and a relative driver that
+ * provides settings of 50%, 100%. The cpufreq core would export frequency
+ * levels of 50, 100, 150, 200, 300, 400.
+ */
+#define CPUFREQ_TYPE_RELATIVE (1<<0)
+#define CPUFREQ_TYPE_ABSOLUTE (1<<1)
+
+/*
+ * When setting a level, the caller indicates the priority of this request.
+ * Priorities determine, among other things, whether a level can be
+ * overridden by other callers. For example, if the user sets a level but
+ * the system thermal driver needs to override it for emergency cooling,
+ * the driver would use a higher priority. Once the event has passed, the
+ * driver would call cpufreq to resume any previous level.
+ */
+#define CPUFREQ_PRIO_HIGHEST 1000000
+#define CPUFREQ_PRIO_KERN 1000
+#define CPUFREQ_PRIO_USER 100
+#define CPUFREQ_PRIO_LOWEST 0
+
+/*
+ * Register and unregister a driver with the cpufreq core. Once a driver
+ * is registered, it must support calls to its CPUFREQ_GET, CPUFREQ_GET_LEVEL,
+ * and CPUFREQ_SET methods. It must also unregister before returning from
+ * its DEVICE_DETACH method.
+ */
+int cpufreq_register(device_t dev);
+int cpufreq_unregister(device_t dev);
+
+/* Allow values to be +/- a bit since sometimes we have to estimate. */
+#define CPUFREQ_CMP(x, y) (abs((x) - (y)) < 25)
+
+/*
+ * Machine-dependent functions.
+ */
+
+/* Estimate the current clock rate for the given CPU id. */
+int cpu_est_clockrate(int cpu_id, uint64_t *rate);
+
+#endif /* !_SYS_CPU_H_ */
Index: i386/i386/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.603
diff -u -r1.603 machdep.c
--- i386/i386/machdep.c 27 Nov 2004 06:51:35 -0000 1.603
+++ i386/i386/machdep.c 1 Feb 2005 06:33:20 -0000
@@ -56,8 +56,12 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/signalvar.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -66,21 +70,18 @@
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/memrange.h>
+#include <sys/msgbuf.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
#include <sys/reboot.h>
-#include <sys/callout.h>
-#include <sys/msgbuf.h>
#include <sys/sched.h>
-#include <sys/sysent.h>
+#include <sys/signalvar.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
#include <sys/ucontext.h>
#include <sys/vmmeter.h>
-#include <sys/bus.h>
-#include <sys/eventhandler.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -104,6 +105,7 @@
#include <net/netisr.h>
+#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/reg.h>
@@ -1022,6 +1024,46 @@
{
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+ uint64_t tsc1, tsc2;
+
+ if (pcpu_find(cpu_id) == NULL || rate == NULL)
+ return (EINVAL);
+ if (!tsc_present)
+ return (EOPNOTSUPP);
+
+ /* If we're booting, trust the rate calibrated moments ago. */
+ if (cold) {
+ *rate = tsc_freq;
+ return (0);
+ }
+
+#ifdef SMP
+ /* Schedule ourselves on the indicated cpu. */
+ mtx_lock_spin(&sched_lock);
+ sched_bind(curthread, cpu_id);
+ mtx_unlock_spin(&sched_lock);
+#endif
+
+ /* Calibrate by measuring a short delay. */
+ tsc1 = rdtsc();
+ DELAY(1000);
+ tsc2 = rdtsc();
+
+#ifdef SMP
+ mtx_lock_spin(&sched_lock);
+ sched_unbind(curthread);
+ mtx_unlock_spin(&sched_lock);
+#endif
+
+ tsc_freq = (tsc2 - tsc1) * 1000;
+ *rate = tsc_freq;
+ return (0);
+}
+
/*
* Shutdown the CPU as much as possible
*/
Index: amd64/amd64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/amd64/amd64/machdep.c,v
retrieving revision 1.625
diff -u -r1.625 machdep.c
--- amd64/amd64/machdep.c 29 Nov 2004 23:27:07 -0000 1.625
+++ amd64/amd64/machdep.c 1 Feb 2005 06:44:09 -0000
@@ -56,8 +56,12 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/signalvar.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -69,19 +73,17 @@
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
#include <sys/reboot.h>
-#include <sys/callout.h>
#include <sys/msgbuf.h>
#include <sys/sched.h>
+#include <sys/signalvar.h>
#include <sys/sysent.h>
#include <sys/sysctl.h>
+#include <sys/sysproto.h>
#include <sys/ucontext.h>
#include <sys/vmmeter.h>
-#include <sys/bus.h>
-#include <sys/eventhandler.h>
+#include <machine/clock.h>
#include <machine/pcb.h>
#include <vm/vm.h>
@@ -450,6 +452,44 @@
{
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+ uint64_t tsc1, tsc2;
+
+ if (pcpu_find(cpu_id) == NULL || rate == NULL)
+ return (EINVAL);
+
+ /* If we're booting, trust the rate calibrated moments ago. */
+ if (cold) {
+ *rate = tsc_freq;
+ return (0);
+ }
+
+#ifdef SMP
+ /* Schedule ourselves on the indicated cpu. */
+ mtx_lock_spin(&sched_lock);
+ sched_bind(curthread, cpu_id);
+ mtx_unlock_spin(&sched_lock);
+#endif
+
+ /* Calibrate by measuring a short delay. */
+ tsc1 = rdtsc();
+ DELAY(1000);
+ tsc2 = rdtsc();
+
+#ifdef SMP
+ mtx_lock_spin(&sched_lock);
+ sched_unbind(curthread);
+ mtx_unlock_spin(&sched_lock);
+#endif
+
+ tsc_freq = (tsc2 - tsc1) * 1000;
+ *rate = tsc_freq;
+ return (0);
+}
+
/*
* Shutdown the CPU as much as possible
*/
Index: ia64/ia64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/ia64/ia64/machdep.c,v
retrieving revision 1.193
diff -u -r1.193 machdep.c
--- ia64/ia64/machdep.c 8 Dec 2004 05:46:54 -0000 1.193
+++ ia64/ia64/machdep.c 1 Feb 2005 06:47:52 -0000
@@ -35,6 +35,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/cpu.h>
#include <sys/eventhandler.h>
#include <sys/kdb.h>
#include <sys/sysproto.h>
@@ -287,6 +288,17 @@
efi_reset_system();
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ if (pcpu_find(cpu_id) == NULL || rate == NULL)
+ return (EINVAL);
+ *rate = processor_frequency;
+ return (0);
+}
+
void
cpu_halt()
{
Index: alpha/alpha/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/alpha/alpha/machdep.c,v
retrieving revision 1.228
diff -u -r1.228 machdep.c
--- alpha/alpha/machdep.c 5 Jan 2005 20:05:49 -0000 1.228
+++ alpha/alpha/machdep.c 1 Feb 2005 06:50:03 -0000
@@ -98,6 +98,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/cpu.h>
#include <sys/eventhandler.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
@@ -1718,6 +1719,14 @@
{
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
/*
* Shutdown the CPU as much as possible
*/
Index: arm/arm/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/arm/machdep.c,v
retrieving revision 1.9
diff -u -r1.9 machdep.c
--- arm/arm/machdep.c 10 Jan 2005 22:43:16 -0000 1.9
+++ arm/arm/machdep.c 1 Feb 2005 06:50:41 -0000
@@ -48,6 +48,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/cpu.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <sys/imgact.h>
@@ -236,6 +237,14 @@
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
void
cpu_idle(void)
{
Index: powerpc/powerpc/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/powerpc/powerpc/machdep.c,v
retrieving revision 1.79
diff -u -r1.79 machdep.c
--- powerpc/powerpc/machdep.c 7 Jan 2005 02:29:20 -0000 1.79
+++ powerpc/powerpc/machdep.c 1 Feb 2005 06:51:03 -0000
@@ -64,6 +64,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/cpu.h>
#include <sys/kdb.h>
#include <sys/eventhandler.h>
#include <sys/imgact.h>
@@ -700,6 +701,14 @@
{
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
/*
* Shutdown the CPU as much as possible.
*/
Index: sparc64/sparc64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/machdep.c,v
retrieving revision 1.117
diff -u -r1.117 machdep.c
--- sparc64/sparc64/machdep.c 27 Nov 2004 06:51:38 -0000 1.117
+++ sparc64/sparc64/machdep.c 1 Feb 2005 06:51:39 -0000
@@ -44,6 +44,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cons.h>
+#include <sys/cpu.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -669,6 +670,14 @@
openfirmware_exit(args);
}
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
/*
* Duplicate OF_exit() with a different firmware call function that restores
* the trap table, otherwise a RED state exception is triggered in at least
More information about the freebsd-current
mailing list