diff options
author | sobomax <sobomax@FreeBSD.org> | 2004-01-25 09:59:16 +0000 |
---|---|---|
committer | sobomax <sobomax@FreeBSD.org> | 2004-01-25 09:59:16 +0000 |
commit | 602ddad2956ca69294a132f44d58b92ef4544154 (patch) | |
tree | 5070e240d86e9bd7dcc416af4dc14bfbe3631191 /sys/i386 | |
parent | 66e25930ecf3c1629e6f76978cd0b2dfc2417676 (diff) | |
download | FreeBSD-src-602ddad2956ca69294a132f44d58b92ef4544154.zip FreeBSD-src-602ddad2956ca69294a132f44d58b92ef4544154.tar.gz |
Move LongRun support out of identcpu.c, where it hardly belongs, into its
own file and make it opt-in, not mandatory, depending on CPU_ENABLE_LONGRUN
config(8) option.
Discussed with: nate
MFC after: 2 weeks
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/conf/NOTES | 4 | ||||
-rw-r--r-- | sys/i386/i386/identcpu.c | 263 | ||||
-rw-r--r-- | sys/i386/i386/longrun.c | 307 |
3 files changed, 311 insertions, 263 deletions
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index ef49763..1b5382b 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -119,6 +119,10 @@ cpu I686_CPU # aka Pentium Pro(tm) # sysctls. This operates independently of SpeedStep and is useful on # systems where other mechanisms such as apm(4) or acpi(4) don't work. # +# CPU_ENABLE_LONGRUN enables support for Transmeta Crusoe LongRun +# technology which allows to restrict power consumption of the CPU by +# using group of hw.crusoe.* sysctls. +# # CPU_FASTER_5X86_FPU enables faster FPU exception handler. # # CPU_GEODE is for the SC1100 Geode embedded processor. This option diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index 3dab43d..b5b1e9d 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -82,7 +82,6 @@ static void print_AMD_features(void); static void print_AMD_info(void); static void print_AMD_assoc(int i); static void print_transmeta_info(void); -static void setup_tmx86_longrun(void); int cpu_class; u_int cpu_exthigh; /* Highest arg to extended CPUID */ @@ -702,10 +701,6 @@ printcpuinfo(void) printf("\n"); #endif - if (strcmp(cpu_vendor, "GenuineTMx86") == 0 || - strcmp(cpu_vendor, "TransmetaCPU") == 0) { - setup_tmx86_longrun(); - } if (!bootverbose) return; @@ -1110,258 +1105,6 @@ print_AMD_features(void) } #endif -/* - * Transmeta Crusoe LongRun Support by Tamotsu Hattori. - */ - -#define MSR_TMx86_LONGRUN 0x80868010 -#define MSR_TMx86_LONGRUN_FLAGS 0x80868011 - -#define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f) -#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 { - u_int64_t msr; - u_int32_t regs[2]; -}; - -static u_int32_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_get_longrun_mode(void) -{ - u_long eflags; - union msrinfo msrinfo; - u_int low, high, flags, mode; - - eflags = read_eflags(); - 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: - write_eflags(eflags); - return (mode); -} - -static u_int -tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage) -{ - u_long eflags; - u_int regs[4]; - - eflags = read_eflags(); - disable_intr(); - - do_cpuid(0x80860007, regs); - *frequency = regs[0]; - *voltage = regs[1]; - *percentage = regs[2]; - - write_eflags(eflags); - return (1); -} - -static u_int -tmx86_set_longrun_mode(u_int mode) -{ - u_long eflags; - union msrinfo msrinfo; - - if (mode >= LONGRUN_MODE_UNKNOWN) { - return (0); - } - - eflags = read_eflags(); - 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); - - write_eflags(eflags); - return (1); -} - -static u_int crusoe_longrun; -static u_int crusoe_frequency; -static u_int crusoe_voltage; -static u_int crusoe_percentage; -static u_int crusoe_performance_longrun = LONGRUN_MODE_PERFORMANCE; -static u_int crusoe_economy_longrun = LONGRUN_MODE_ECONOMY; -static struct sysctl_ctx_list crusoe_sysctl_ctx; -static struct sysctl_oid *crusoe_sysctl_tree; - -static void -tmx86_longrun_power_profile(void *arg) -{ - int state; - u_int new; - - state = power_profile_get_state(); - if (state != POWER_PROFILE_PERFORMANCE && - state != POWER_PROFILE_ECONOMY) { - return; - } - - switch (state) { - case POWER_PROFILE_PERFORMANCE: - new =crusoe_performance_longrun; - break; - case POWER_PROFILE_ECONOMY: - new = crusoe_economy_longrun; - break; - default: - new = tmx86_get_longrun_mode(); - break; - } - - if (tmx86_get_longrun_mode() != new) { - tmx86_set_longrun_mode(new); - } -} - -static int -tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS) -{ - u_int mode; - int error; - - crusoe_longrun = tmx86_get_longrun_mode(); - mode = crusoe_longrun; - error = sysctl_handle_int(oidp, &mode, 0, req); - if (error || !req->newptr) { - return (error); - } - if (mode >= LONGRUN_MODE_UNKNOWN) { - error = EINVAL; - return (error); - } - if (crusoe_longrun != mode) { - crusoe_longrun = mode; - tmx86_set_longrun_mode(crusoe_longrun); - } - - return (error); -} - -static int -tmx86_status_sysctl(SYSCTL_HANDLER_ARGS) -{ - u_int val; - int error; - - tmx86_get_longrun_status(&crusoe_frequency, - &crusoe_voltage, &crusoe_percentage); - val = *(u_int *)oidp->oid_arg1; - error = sysctl_handle_int(oidp, &val, 0, req); - return (error); -} - -static int -tmx86_longrun_profile_sysctl(SYSCTL_HANDLER_ARGS) -{ - u_int32_t *argp; - u_int32_t arg; - int error; - - argp = (u_int32_t *)oidp->oid_arg1; - arg = *argp; - error = sysctl_handle_int(oidp, &arg, 0, req); - - /* error or no new value */ - if ((error != 0) || (req->newptr == NULL)) - return (error); - - /* range check */ - if (arg >= LONGRUN_MODE_UNKNOWN) - return (EINVAL); - - /* set new value and possibly switch */ - *argp = arg; - - tmx86_longrun_power_profile(NULL); - - return (0); - -} - -static void -setup_tmx86_longrun(void) -{ - static int done = 0; - - if (done) - return; - done++; - - sysctl_ctx_init(&crusoe_sysctl_ctx); - crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, - "crusoe", CTLFLAG_RD, 0, - "Transmeta Crusoe LongRun support"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW, - &crusoe_longrun, 0, tmx86_longrun_sysctl, "I", - "LongRun mode [0-3]"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_frequency, 0, tmx86_status_sysctl, "I", - "Current frequency (MHz)"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_voltage, 0, tmx86_status_sysctl, "I", - "Current voltage (mV)"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_percentage, 0, tmx86_status_sysctl, "I", - "Processing performance (%)"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "performance_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW, - &crusoe_performance_longrun, 0, tmx86_longrun_profile_sysctl, "I", ""); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "economy_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW, - &crusoe_economy_longrun, 0, tmx86_longrun_profile_sysctl, "I", ""); - - /* register performance profile change handler */ - EVENTHANDLER_REGISTER(power_profile_change, tmx86_longrun_power_profile, NULL, 0); - -} - static void print_transmeta_info() { @@ -1395,10 +1138,4 @@ print_transmeta_info() info[64] = 0; printf(" %s\n", info); } - - crusoe_longrun = tmx86_get_longrun_mode(); - tmx86_get_longrun_status(&crusoe_frequency, - &crusoe_voltage, &crusoe_percentage); - printf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun, - crusoe_frequency, crusoe_voltage, crusoe_percentage); } diff --git a/sys/i386/i386/longrun.c b/sys/i386/i386/longrun.c new file mode 100644 index 0000000..9cc625b --- /dev/null +++ b/sys/i386/i386/longrun.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2001 Tamotsu Hattori. + * 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> +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/power.h> +#include <sys/sysctl.h> +#include <sys/types.h> + +#include <machine/md_var.h> +#include <machine/specialreg.h> + +/* + * Transmeta Crusoe LongRun Support by Tamotsu Hattori. + */ + +#define MSR_TMx86_LONGRUN 0x80868010 +#define MSR_TMx86_LONGRUN_FLAGS 0x80868011 + +#define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f) +#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 { + u_int64_t msr; + u_int32_t regs[2]; +}; + +static u_int32_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_get_longrun_mode(void) +{ + u_long eflags; + union msrinfo msrinfo; + u_int low, high, flags, mode; + + eflags = read_eflags(); + 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: + write_eflags(eflags); + return (mode); +} + +static u_int +tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage) +{ + u_long eflags; + u_int regs[4]; + + eflags = read_eflags(); + disable_intr(); + + do_cpuid(0x80860007, regs); + *frequency = regs[0]; + *voltage = regs[1]; + *percentage = regs[2]; + + write_eflags(eflags); + return (1); +} + +static u_int +tmx86_set_longrun_mode(u_int mode) +{ + u_long eflags; + union msrinfo msrinfo; + + if (mode >= LONGRUN_MODE_UNKNOWN) { + return (0); + } + + eflags = read_eflags(); + 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); + + write_eflags(eflags); + return (1); +} + +static u_int crusoe_longrun; +static u_int crusoe_frequency; +static u_int crusoe_voltage; +static u_int crusoe_percentage; +static u_int crusoe_performance_longrun = LONGRUN_MODE_PERFORMANCE; +static u_int crusoe_economy_longrun = LONGRUN_MODE_ECONOMY; +static struct sysctl_ctx_list crusoe_sysctl_ctx; +static struct sysctl_oid *crusoe_sysctl_tree; + +static void +tmx86_longrun_power_profile(void *arg) +{ + int state; + u_int new; + + state = power_profile_get_state(); + if (state != POWER_PROFILE_PERFORMANCE && + state != POWER_PROFILE_ECONOMY) { + return; + } + + switch (state) { + case POWER_PROFILE_PERFORMANCE: + new =crusoe_performance_longrun; + break; + case POWER_PROFILE_ECONOMY: + new = crusoe_economy_longrun; + break; + default: + new = tmx86_get_longrun_mode(); + break; + } + + if (tmx86_get_longrun_mode() != new) { + tmx86_set_longrun_mode(new); + } +} + +static int +tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS) +{ + u_int mode; + int error; + + crusoe_longrun = tmx86_get_longrun_mode(); + mode = crusoe_longrun; + error = sysctl_handle_int(oidp, &mode, 0, req); + if (error || !req->newptr) { + return (error); + } + if (mode >= LONGRUN_MODE_UNKNOWN) { + error = EINVAL; + return (error); + } + if (crusoe_longrun != mode) { + crusoe_longrun = mode; + tmx86_set_longrun_mode(crusoe_longrun); + } + + return (error); +} + +static int +tmx86_status_sysctl(SYSCTL_HANDLER_ARGS) +{ + u_int val; + int error; + + tmx86_get_longrun_status(&crusoe_frequency, + &crusoe_voltage, &crusoe_percentage); + val = *(u_int *)oidp->oid_arg1; + error = sysctl_handle_int(oidp, &val, 0, req); + return (error); +} + +static int +tmx86_longrun_profile_sysctl(SYSCTL_HANDLER_ARGS) +{ + u_int32_t *argp; + u_int32_t arg; + int error; + + argp = (u_int32_t *)oidp->oid_arg1; + arg = *argp; + error = sysctl_handle_int(oidp, &arg, 0, req); + + /* error or no new value */ + if ((error != 0) || (req->newptr == NULL)) + return (error); + + /* range check */ + if (arg >= LONGRUN_MODE_UNKNOWN) + return (EINVAL); + + /* set new value and possibly switch */ + *argp = arg; + + tmx86_longrun_power_profile(NULL); + + return (0); + +} + +static void +setup_tmx86_longrun(void *dummy __unused) +{ + if (strcmp(cpu_vendor, "GenuineTMx86") != 0 || + strcmp(cpu_vendor, "TransmetaCPU") != 0) + return; + + crusoe_longrun = tmx86_get_longrun_mode(); + tmx86_get_longrun_status(&crusoe_frequency, + &crusoe_voltage, &crusoe_percentage); + printf("Crusoe LongRun support enabled, current mode: %d " + "<%dMHz %dmV %d%%>\n", crusoe_longrun, crusoe_frequency, + crusoe_voltage, crusoe_percentage); + + sysctl_ctx_init(&crusoe_sysctl_ctx); + crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, + "crusoe", CTLFLAG_RD, 0, + "Transmeta Crusoe LongRun support"); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW, + &crusoe_longrun, 0, tmx86_longrun_sysctl, "I", + "LongRun mode [0-3]"); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD, + &crusoe_frequency, 0, tmx86_status_sysctl, "I", + "Current frequency (MHz)"); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD, + &crusoe_voltage, 0, tmx86_status_sysctl, "I", + "Current voltage (mV)"); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD, + &crusoe_percentage, 0, tmx86_status_sysctl, "I", + "Processing performance (%)"); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "performance_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW, + &crusoe_performance_longrun, 0, tmx86_longrun_profile_sysctl, "I", ""); + SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), + OID_AUTO, "economy_longrun", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_RW, + &crusoe_economy_longrun, 0, tmx86_longrun_profile_sysctl, "I", ""); + + /* register performance profile change handler */ + EVENTHANDLER_REGISTER(power_profile_change, tmx86_longrun_power_profile, NULL, 0); +} +SYSINIT(setup_tmx86_longrun, SI_SUB_CPU, SI_ORDER_ANY, setup_tmx86_longrun, + NULL); |