Split off the Transmeta Crusoe Longrun code into its own file, that

way identcpu.c and machdep.c are not cluttered with foreign code.

The driver is built by default as before, but the sysctl subtree will
only be created if longrun is detected and not always as the old code
did. This matches what the FreeBSD code does.

Ok by christos@.
This commit is contained in:
xtraeme 2008-02-26 18:24:28 +00:00
parent 22e6b6b586
commit c524510b66
5 changed files with 270 additions and 215 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.i386,v 1.333 2008/02/20 21:43:34 drochner Exp $
# $NetBSD: files.i386,v 1.334 2008/02/26 18:24:28 xtraeme Exp $
#
# new style config file for i386 architecture
#
@ -82,6 +82,7 @@ file arch/i386/i386/kgdb_machdep.c kgdb
file arch/i386/i386/kobj_machdep.c modular
file arch/i386/i386/machdep.c
file arch/i386/i386/identcpu.c
file arch/i386/i386/longrun.c
file arch/i386/i386/mem.c
file arch/i386/i386/mtrr_k6.c mtrr
file arch/i386/i386/process_machdep.c

View File

@ -1,4 +1,4 @@
/* $NetBSD: identcpu.c,v 1.87 2008/01/15 16:11:29 ad Exp $ */
/* $NetBSD: identcpu.c,v 1.88 2008/02/26 18:24:28 xtraeme Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2006, 2007 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.87 2008/01/15 16:11:29 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.88 2008/02/26 18:24:28 xtraeme Exp $");
#include "opt_enhanced_speedstep.h"
#include "opt_intel_odcm.h"
@ -1097,132 +1097,11 @@ amd_family5_setup(struct cpu_info *ci)
}
}
/*
* Transmeta Crusoe LongRun Support by Tamotsu Hattori.
* Port from FreeBSD-current(August, 2001) to NetBSD by tshiozak.
*/
#define MSR_TMx86_LONGRUN 0x80868010
#define MSR_TMx86_LONGRUN_FLAGS 0x80868011
#define LONGRUN_MODE_MASK(x) ((x) & 0x0000007f)
#define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
#define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | \
LONGRUN_MODE_MASK(y))
#define LONGRUN_MODE_MINFREQUENCY 0x00
#define LONGRUN_MODE_ECONOMY 0x01
#define LONGRUN_MODE_PERFORMANCE 0x02
#define LONGRUN_MODE_MAXFREQUENCY 0x03
#define LONGRUN_MODE_UNKNOWN 0x04
#define LONGRUN_MODE_MAX 0x04
union msrinfo {
uint64_t msr;
uint32_t regs[2];
};
uint32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
/* MSR low, MSR high, flags bit0 */
{ 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
{ 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
{ 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
{ 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
};
u_int
tmx86_get_longrun_mode(void)
{
u_long eflags;
union msrinfo msrinfo;
u_int low, high, flags, mode;
eflags = x86_read_psl();
x86_disable_intr();
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
if (low == longrun_modes[mode][0] &&
high == longrun_modes[mode][1] &&
flags == longrun_modes[mode][2]) {
goto out;
}
}
mode = LONGRUN_MODE_UNKNOWN;
out:
x86_write_psl(eflags);
return (mode);
}
static u_int
tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
{
u_long eflags;
u_int descs[4];
eflags = x86_read_psl();
x86_disable_intr();
x86_cpuid(0x80860007, descs);
*frequency = descs[0];
*voltage = descs[1];
*percentage = descs[2];
x86_write_psl(eflags);
return (1);
}
u_int
tmx86_set_longrun_mode(u_int mode)
{
u_long eflags;
union msrinfo msrinfo;
if (mode >= LONGRUN_MODE_UNKNOWN) {
return (0);
}
eflags = x86_read_psl();
x86_disable_intr();
/* Write LongRun mode values to Model Specific Register. */
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
longrun_modes[mode][0]);
msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
longrun_modes[mode][1]);
wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
/* Write LongRun mode flags to Model Specific Register. */
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
x86_write_psl(eflags);
return (1);
}
u_int crusoe_longrun;
u_int crusoe_frequency;
u_int crusoe_voltage;
u_int crusoe_percentage;
void
tmx86_get_longrun_status_all(void)
{
tmx86_get_longrun_status(&crusoe_frequency,
&crusoe_voltage, &crusoe_percentage);
}
static void
transmeta_cpu_info(struct cpu_info *ci)
{
u_int descs[4], nreg;
u_int longrun, frequency, voltage, percentage;
x86_cpuid(0x80860000, descs);
nreg = descs[0];
@ -1259,13 +1138,12 @@ transmeta_cpu_info(struct cpu_info *ci)
}
if (nreg >= 0x80860007) {
crusoe_longrun = tmx86_get_longrun_mode();
tmx86_get_longrun_status(&crusoe_frequency,
&crusoe_voltage, &crusoe_percentage);
longrun = tmx86_get_longrun_mode();
tmx86_get_longrun_status(&frequency,
&voltage, &percentage);
aprint_verbose("%s: LongRun mode: %d <%dMHz %dmV %d%%>\n",
ci->ci_dev->dv_xname,
crusoe_longrun, crusoe_frequency, crusoe_voltage,
crusoe_percentage);
longrun, frequency, voltage, percentage);
}
}
@ -1276,7 +1154,7 @@ transmeta_cpu_setup(struct cpu_info *ci)
x86_cpuid(0x80860000, descs);
if (descs[0] >= 0x80860007)
tmx86_has_longrun = 1;
tmx86_init_longrun();
}
void

View File

@ -0,0 +1,249 @@
/* $NetBSD: longrun.c,v 1.1 2008/02/26 18:24:28 xtraeme Exp $ */
/*-
* Copyright (c) 2001 Tamotsu Hattori.
* Copyright (c) 2001 Mitsuru IWASAKI.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: longrun.c,v 1.1 2008/02/26 18:24:28 xtraeme Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <machine/specialreg.h>
#include <machine/cpu.h>
/*
* Transmeta Crusoe LongRun Support by Tamotsu Hattori.
* Port from FreeBSD-current(August, 2001) to NetBSD by tshiozak.
*/
#define MSR_TMx86_LONGRUN 0x80868010
#define MSR_TMx86_LONGRUN_FLAGS 0x80868011
#define LONGRUN_MODE_MASK(x) ((x) & 0x0000007f)
#define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
#define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | \
LONGRUN_MODE_MASK(y))
#define LONGRUN_MODE_MINFREQUENCY 0x00
#define LONGRUN_MODE_ECONOMY 0x01
#define LONGRUN_MODE_PERFORMANCE 0x02
#define LONGRUN_MODE_MAXFREQUENCY 0x03
#define LONGRUN_MODE_UNKNOWN 0x04
#define LONGRUN_MODE_MAX 0x04
union msrinfo {
uint64_t msr;
uint32_t regs[2];
};
static u_int crusoe_longrun = 0;
static u_int crusoe_frequency = 0;
static u_int crusoe_voltage = 0;
static u_int crusoe_percentage = 0;
static const uint32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
/* MSR low, MSR high, flags bit0 */
{ 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
{ 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
{ 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
{ 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
};
static u_int tmx86_set_longrun_mode(u_int);
static void tmx86_get_longrun_status_all(void);
static int sysctl_machdep_tm_longrun(SYSCTLFN_PROTO);
void
tmx86_init_longrun(void)
{
/* create the sysctl machdep.tm_longrun_* nodes */
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "machdep", NULL,
NULL, 0, NULL, 0,
CTL_MACHDEP, CTL_EOL);
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "tm_longrun_mode", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_MODE, CTL_EOL);
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_frequency", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_FREQUENCY, CTL_EOL);
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_voltage", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_VOLTAGE, CTL_EOL);
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_percentage", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_PERCENTAGE, CTL_EOL);
}
u_int
tmx86_get_longrun_mode(void)
{
u_long eflags;
union msrinfo msrinfo;
u_int low, high, flags, mode;
eflags = x86_read_psl();
x86_disable_intr();
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
if (low == longrun_modes[mode][0] &&
high == longrun_modes[mode][1] &&
flags == longrun_modes[mode][2]) {
goto out;
}
}
mode = LONGRUN_MODE_UNKNOWN;
out:
x86_write_psl(eflags);
return mode;
}
void
tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
{
u_long eflags;
u_int descs[4];
eflags = x86_read_psl();
x86_disable_intr();
x86_cpuid(0x80860007, descs);
*frequency = descs[0];
*voltage = descs[1];
*percentage = descs[2];
x86_write_psl(eflags);
}
static u_int
tmx86_set_longrun_mode(u_int mode)
{
u_long eflags;
union msrinfo msrinfo;
if (mode >= LONGRUN_MODE_UNKNOWN)
return 0;
eflags = x86_read_psl();
x86_disable_intr();
/* Write LongRun mode values to Model Specific Register. */
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
longrun_modes[mode][0]);
msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
longrun_modes[mode][1]);
wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
/* Write LongRun mode flags to Model Specific Register. */
msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
x86_write_psl(eflags);
return 1;
}
static void
tmx86_get_longrun_status_all(void)
{
tmx86_get_longrun_status(&crusoe_frequency,
&crusoe_voltage, &crusoe_percentage);
}
/*
* sysctl helper routine for machdep.tm* nodes.
*/
static int
sysctl_machdep_tm_longrun(SYSCTLFN_ARGS)
{
struct sysctlnode node;
int io, error;
node = *rnode;
node.sysctl_data = &io;
switch (rnode->sysctl_num) {
case CPU_TMLR_MODE:
io = (int)(crusoe_longrun = tmx86_get_longrun_mode());
break;
case CPU_TMLR_FREQUENCY:
tmx86_get_longrun_status_all();
io = crusoe_frequency;
break;
case CPU_TMLR_VOLTAGE:
tmx86_get_longrun_status_all();
io = crusoe_voltage;
break;
case CPU_TMLR_PERCENTAGE:
tmx86_get_longrun_status_all();
io = crusoe_percentage;
break;
default:
return EOPNOTSUPP;
}
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
if (rnode->sysctl_num == CPU_TMLR_MODE) {
if (tmx86_set_longrun_mode(io))
crusoe_longrun = (u_int)io;
else
return EINVAL;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.626 2008/02/12 17:52:18 joerg Exp $ */
/* $NetBSD: machdep.c,v 1.627 2008/02/26 18:24:28 xtraeme Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008 The NetBSD Foundation, Inc.
@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.626 2008/02/12 17:52:18 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.627 2008/02/26 18:24:28 xtraeme Exp $");
#include "opt_beep.h"
#include "opt_compat_ibcs2.h"
@ -262,8 +262,6 @@ int i386_use_fxsave;
int i386_has_sse;
int i386_has_sse2;
int tmx86_has_longrun;
vaddr_t msgbuf_vaddr;
struct {
paddr_t paddr;
@ -617,55 +615,6 @@ cpu_init_tss(struct cpu_info *ci)
}
#endif /* XEN */
/*
* sysctl helper routine for machdep.tm* nodes.
*/
static int
sysctl_machdep_tm_longrun(SYSCTLFN_ARGS)
{
struct sysctlnode node;
int io, error;
if (!tmx86_has_longrun)
return (EOPNOTSUPP);
node = *rnode;
node.sysctl_data = &io;
switch (rnode->sysctl_num) {
case CPU_TMLR_MODE:
io = (int)(crusoe_longrun = tmx86_get_longrun_mode());
break;
case CPU_TMLR_FREQUENCY:
tmx86_get_longrun_status_all();
io = crusoe_frequency;
break;
case CPU_TMLR_VOLTAGE:
tmx86_get_longrun_status_all();
io = crusoe_voltage;
break;
case CPU_TMLR_PERCENTAGE:
tmx86_get_longrun_status_all();
io = crusoe_percentage;
break;
default:
return (EOPNOTSUPP);
}
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return (error);
if (rnode->sysctl_num == CPU_TMLR_MODE) {
if (tmx86_set_longrun_mode(io))
crusoe_longrun = (u_int)io;
else
return (EINVAL);
}
return (0);
}
/*
* sysctl helper routine for machdep.booted_kernel
*/
@ -766,26 +715,6 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
CTLTYPE_STRING, "cpu_brand", NULL,
NULL, 0, &cpu_brand_string, 0,
CTL_MACHDEP, CTL_CREATE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "tm_longrun_mode", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_MODE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_frequency", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_FREQUENCY, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_voltage", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_VOLTAGE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "tm_longrun_percentage", NULL,
sysctl_machdep_tm_longrun, 0, NULL, 0,
CTL_MACHDEP, CPU_TMLR_PERCENTAGE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "sparse_dump", NULL,

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.161 2008/02/10 14:37:41 ad Exp $ */
/* $NetBSD: cpu.h,v 1.162 2008/02/26 18:24:28 xtraeme Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -383,15 +383,13 @@ void dumpconf(void);
void cpu_reset(void);
void i386_proc0_tss_ldt_init(void);
extern int tmx86_has_longrun;
extern u_int crusoe_longrun;
extern u_int crusoe_frequency;
extern u_int crusoe_voltage;
extern u_int crusoe_percentage;
extern u_int tmx86_set_longrun_mode(u_int);
void tmx86_get_longrun_status_all(void);
u_int tmx86_get_longrun_mode(void);
void identifycpu(struct cpu_info *);
/* longrun.c */
u_int tmx86_get_longrun_mode(void);
void tmx86_get_longrun_status(u_int *, u_int *, u_int *);
void tmx86_init_longrun(void);
/* identcpu.c */
void identifycpu(struct cpu_info *);
/* vm_machdep.c */
void cpu_proc_fork(struct proc *, struct proc *);
@ -479,7 +477,7 @@ void x86_bus_space_mallocok(void);
* 3: maximum frequency
*/
#define CPU_TMLR_FREQUENCY 12 /* int: current frequency */
#define CPU_TMLR_VOLTAGE 13 /* int: curret voltage */
#define CPU_TMLR_VOLTAGE 13 /* int: current voltage */
#define CPU_TMLR_PERCENTAGE 14 /* int: current clock percentage */
#define CPU_MAXID 15 /* number of valid machdep ids */