From owner-freebsd-current@FreeBSD.ORG Tue Feb 1 06:58:22 2005 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id ED42A16A4CE for ; Tue, 1 Feb 2005 06:58:22 +0000 (GMT) Received: from ylpvm43.prodigy.net (ylpvm43-ext.prodigy.net [207.115.57.74]) by mx1.FreeBSD.org (Postfix) with ESMTP id 28B4C43D48 for ; Tue, 1 Feb 2005 06:58:20 +0000 (GMT) (envelope-from nate@root.org) Received: from [10.0.5.51] (adsl-64-171-186-233.dsl.snfc21.pacbell.net [64.171.186.233])j116wU2Y016123 for ; Tue, 1 Feb 2005 01:58:31 -0500 Message-ID: <41FF280F.1050102@root.org> Date: Mon, 31 Jan 2005 22:56:15 -0800 From: Nate Lawson User-Agent: Mozilla Thunderbird 1.0RC1 (X11/20041205) X-Accept-Language: en-us, en MIME-Version: 1.0 To: FreeBSD Current Content-Type: multipart/mixed; boundary="------------000405090204000606090607" Subject: patch: please test buildkernel X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Feb 2005 06:58:23 -0000 This is a multi-part message in MIME format. --------------000405090204000606090607 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------000405090204000606090607 Content-Type: text/plain; name="cpu_est_clockrate.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cpu_est_clockrate.diff" 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 #include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -66,21 +70,18 @@ #include #include #include +#include #include #include #include -#include -#include #include -#include -#include #include -#include +#include #include +#include +#include #include #include -#include -#include #include #include @@ -104,6 +105,7 @@ #include +#include #include #include #include @@ -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 #include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -69,19 +73,17 @@ #include #include #include -#include -#include #include -#include #include #include +#include #include #include +#include #include #include -#include -#include +#include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 --------------000405090204000606090607--