Merge branch 'linus' into perf/urgent
Merge reason: Fix upstream breakage introduced by:
de5d9bf
: Move list types from <linux/list.h> to <linux/types.h>.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -12,11 +12,11 @@ endif
|
||||
nostackp := $(call cc-option, -fno-stack-protector)
|
||||
CFLAGS_common.o := $(nostackp)
|
||||
|
||||
obj-y := intel_cacheinfo.o addon_cpuid_features.o
|
||||
obj-y := intel_cacheinfo.o scattered.o topology.o
|
||||
obj-y += proc.o capflags.o powerflags.o common.o
|
||||
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
|
||||
|
||||
obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
|
||||
obj-$(CONFIG_X86_32) += bugs.o
|
||||
obj-$(CONFIG_X86_64) += bugs_64.o
|
||||
|
||||
obj-$(CONFIG_CPU_SUP_INTEL) += intel.o
|
||||
|
@@ -466,7 +466,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
}
|
||||
if (c->x86 == 0x10 || c->x86 == 0x11)
|
||||
if (c->x86 >= 0x10)
|
||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||
|
||||
/* get apicid instead of initial apic id from cpuid */
|
||||
@@ -529,7 +529,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||
num_cache_leaves = 3;
|
||||
}
|
||||
|
||||
if (c->x86 >= 0xf && c->x86 <= 0x11)
|
||||
if (c->x86 >= 0xf)
|
||||
set_cpu_cap(c, X86_FEATURE_K8);
|
||||
|
||||
if (cpu_has_xmm2) {
|
||||
@@ -546,7 +546,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||
fam10h_check_enable_mmcfg();
|
||||
}
|
||||
|
||||
if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
|
||||
if (c == &boot_cpu_data && c->x86 >= 0xf) {
|
||||
unsigned long long tseg;
|
||||
|
||||
/*
|
||||
@@ -609,3 +609,74 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
|
||||
};
|
||||
|
||||
cpu_dev_register(amd_cpu_dev);
|
||||
|
||||
/*
|
||||
* AMD errata checking
|
||||
*
|
||||
* Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
|
||||
* AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
|
||||
* have an OSVW id assigned, which it takes as first argument. Both take a
|
||||
* variable number of family-specific model-stepping ranges created by
|
||||
* AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const
|
||||
* int[] in arch/x86/include/asm/processor.h.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* const int amd_erratum_319[] =
|
||||
* AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
|
||||
* AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
|
||||
* AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
|
||||
*/
|
||||
|
||||
const int amd_erratum_400[] =
|
||||
AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
|
||||
AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
|
||||
EXPORT_SYMBOL_GPL(amd_erratum_400);
|
||||
|
||||
const int amd_erratum_383[] =
|
||||
AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
|
||||
EXPORT_SYMBOL_GPL(amd_erratum_383);
|
||||
|
||||
bool cpu_has_amd_erratum(const int *erratum)
|
||||
{
|
||||
struct cpuinfo_x86 *cpu = ¤t_cpu_data;
|
||||
int osvw_id = *erratum++;
|
||||
u32 range;
|
||||
u32 ms;
|
||||
|
||||
/*
|
||||
* If called early enough that current_cpu_data hasn't been initialized
|
||||
* yet, fall back to boot_cpu_data.
|
||||
*/
|
||||
if (cpu->x86 == 0)
|
||||
cpu = &boot_cpu_data;
|
||||
|
||||
if (cpu->x86_vendor != X86_VENDOR_AMD)
|
||||
return false;
|
||||
|
||||
if (osvw_id >= 0 && osvw_id < 65536 &&
|
||||
cpu_has(cpu, X86_FEATURE_OSVW)) {
|
||||
u64 osvw_len;
|
||||
|
||||
rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
|
||||
if (osvw_id < osvw_len) {
|
||||
u64 osvw_bits;
|
||||
|
||||
rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
|
||||
osvw_bits);
|
||||
return osvw_bits & (1ULL << (osvw_id & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
/* OSVW unavailable or ID unknown, match family-model-stepping range */
|
||||
ms = (cpu->x86_model << 8) | cpu->x86_mask;
|
||||
while ((range = *erratum++))
|
||||
if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
|
||||
(ms >= AMD_MODEL_RANGE_START(range)) &&
|
||||
(ms <= AMD_MODEL_RANGE_END(range)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(cpu_has_amd_erratum);
|
||||
|
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* cmpxchg*() fallbacks for CPU not supporting these instructions
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifndef CONFIG_X86_CMPXCHG
|
||||
unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
|
||||
{
|
||||
u8 prev;
|
||||
unsigned long flags;
|
||||
|
||||
/* Poor man's cmpxchg for 386. Unsuitable for SMP */
|
||||
local_irq_save(flags);
|
||||
prev = *(u8 *)ptr;
|
||||
if (prev == old)
|
||||
*(u8 *)ptr = new;
|
||||
local_irq_restore(flags);
|
||||
return prev;
|
||||
}
|
||||
EXPORT_SYMBOL(cmpxchg_386_u8);
|
||||
|
||||
unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new)
|
||||
{
|
||||
u16 prev;
|
||||
unsigned long flags;
|
||||
|
||||
/* Poor man's cmpxchg for 386. Unsuitable for SMP */
|
||||
local_irq_save(flags);
|
||||
prev = *(u16 *)ptr;
|
||||
if (prev == old)
|
||||
*(u16 *)ptr = new;
|
||||
local_irq_restore(flags);
|
||||
return prev;
|
||||
}
|
||||
EXPORT_SYMBOL(cmpxchg_386_u16);
|
||||
|
||||
unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
|
||||
{
|
||||
u32 prev;
|
||||
unsigned long flags;
|
||||
|
||||
/* Poor man's cmpxchg for 386. Unsuitable for SMP */
|
||||
local_irq_save(flags);
|
||||
prev = *(u32 *)ptr;
|
||||
if (prev == old)
|
||||
*(u32 *)ptr = new;
|
||||
local_irq_restore(flags);
|
||||
return prev;
|
||||
}
|
||||
EXPORT_SYMBOL(cmpxchg_386_u32);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_X86_CMPXCHG64
|
||||
unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
|
||||
{
|
||||
u64 prev;
|
||||
unsigned long flags;
|
||||
|
||||
/* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
|
||||
local_irq_save(flags);
|
||||
prev = *(u64 *)ptr;
|
||||
if (prev == old)
|
||||
*(u64 *)ptr = new;
|
||||
local_irq_restore(flags);
|
||||
return prev;
|
||||
}
|
||||
EXPORT_SYMBOL(cmpxchg_486_u64);
|
||||
#endif
|
||||
|
@@ -140,10 +140,18 @@ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
|
||||
static int __init x86_xsave_setup(char *s)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVE);
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
|
||||
return 1;
|
||||
}
|
||||
__setup("noxsave", x86_xsave_setup);
|
||||
|
||||
static int __init x86_xsaveopt_setup(char *s)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
|
||||
return 1;
|
||||
}
|
||||
__setup("noxsaveopt", x86_xsaveopt_setup);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
static int cachesize_override __cpuinitdata = -1;
|
||||
static int disable_x86_serial_nr __cpuinitdata = 1;
|
||||
@@ -551,6 +559,16 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
|
||||
c->x86_capability[4] = excap;
|
||||
}
|
||||
|
||||
/* Additional Intel-defined flags: level 0x00000007 */
|
||||
if (c->cpuid_level >= 0x00000007) {
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if (eax > 0)
|
||||
c->x86_capability[9] = ebx;
|
||||
}
|
||||
|
||||
/* AMD-defined flags: level 0x80000001 */
|
||||
xlvl = cpuid_eax(0x80000000);
|
||||
c->extended_cpuid_level = xlvl;
|
||||
@@ -576,6 +594,7 @@ static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
|
||||
if (c->extended_cpuid_level >= 0x80000007)
|
||||
c->x86_power = cpuid_edx(0x80000007);
|
||||
|
||||
init_scattered_cpuid_features(c);
|
||||
}
|
||||
|
||||
static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
||||
@@ -731,7 +750,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
||||
|
||||
get_model_name(c); /* Default name */
|
||||
|
||||
init_scattered_cpuid_features(c);
|
||||
detect_nopl(c);
|
||||
}
|
||||
|
||||
@@ -1192,6 +1210,7 @@ void __cpuinit cpu_init(void)
|
||||
dbg_restore_debug_regs();
|
||||
|
||||
fpu_init();
|
||||
xsave_init();
|
||||
|
||||
raw_local_save_flags(kernel_eflags);
|
||||
|
||||
@@ -1252,12 +1271,7 @@ void __cpuinit cpu_init(void)
|
||||
clear_used_math();
|
||||
mxcsr_feature_mask_init();
|
||||
|
||||
/*
|
||||
* Boot processor to setup the FP and extended state context info.
|
||||
*/
|
||||
if (smp_processor_id() == boot_cpu_id)
|
||||
init_thread_xstate();
|
||||
|
||||
fpu_init();
|
||||
xsave_init();
|
||||
}
|
||||
#endif
|
||||
|
@@ -348,7 +348,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
|
||||
|
||||
freqs.old = perf->states[perf->state].core_frequency * 1000;
|
||||
freqs.new = data->freq_table[next_state].frequency;
|
||||
for_each_cpu(i, cmd.mask) {
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
}
|
||||
@@ -364,7 +364,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
|
||||
}
|
||||
}
|
||||
|
||||
for_each_cpu(i, cmd.mask) {
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
@@ -169,12 +169,9 @@ static int gx_freq_mult[16] = {
|
||||
* Low Level chipset interface *
|
||||
****************************************************************/
|
||||
static struct pci_device_id gx_chipset_tbl[] __initdata = {
|
||||
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY), },
|
||||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), },
|
||||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
@@ -199,7 +196,7 @@ static __init struct pci_dev *gx_detect_chipset(void)
|
||||
}
|
||||
|
||||
/* detect which companion chip is used */
|
||||
while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) {
|
||||
for_each_pci_dev(gx_pci) {
|
||||
if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL)
|
||||
return gx_pci;
|
||||
}
|
||||
|
@@ -426,7 +426,7 @@ static int guess_fsb(int mult)
|
||||
}
|
||||
|
||||
|
||||
static int __init longhaul_get_ranges(void)
|
||||
static int __cpuinit longhaul_get_ranges(void)
|
||||
{
|
||||
unsigned int i, j, k = 0;
|
||||
unsigned int ratio;
|
||||
@@ -530,7 +530,7 @@ static int __init longhaul_get_ranges(void)
|
||||
}
|
||||
|
||||
|
||||
static void __init longhaul_setup_voltagescaling(void)
|
||||
static void __cpuinit longhaul_setup_voltagescaling(void)
|
||||
{
|
||||
union msr_longhaul longhaul;
|
||||
struct mV_pos minvid, maxvid, vid;
|
||||
@@ -784,7 +784,7 @@ static int longhaul_setup_southbridge(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
||||
static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
char *cpuname = NULL;
|
||||
|
@@ -56,7 +56,7 @@ union msr_longhaul {
|
||||
/*
|
||||
* VIA C3 Samuel 1 & Samuel 2 (stepping 0)
|
||||
*/
|
||||
static const int __initdata samuel1_mults[16] = {
|
||||
static const int __cpuinitdata samuel1_mults[16] = {
|
||||
-1, /* 0000 -> RESERVED */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -75,7 +75,7 @@ static const int __initdata samuel1_mults[16] = {
|
||||
-1, /* 1111 -> RESERVED */
|
||||
};
|
||||
|
||||
static const int __initdata samuel1_eblcr[16] = {
|
||||
static const int __cpuinitdata samuel1_eblcr[16] = {
|
||||
50, /* 0000 -> RESERVED */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -97,7 +97,7 @@ static const int __initdata samuel1_eblcr[16] = {
|
||||
/*
|
||||
* VIA C3 Samuel2 Stepping 1->15
|
||||
*/
|
||||
static const int __initdata samuel2_eblcr[16] = {
|
||||
static const int __cpuinitdata samuel2_eblcr[16] = {
|
||||
50, /* 0000 -> 5.0x */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -119,7 +119,7 @@ static const int __initdata samuel2_eblcr[16] = {
|
||||
/*
|
||||
* VIA C3 Ezra
|
||||
*/
|
||||
static const int __initdata ezra_mults[16] = {
|
||||
static const int __cpuinitdata ezra_mults[16] = {
|
||||
100, /* 0000 -> 10.0x */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -138,7 +138,7 @@ static const int __initdata ezra_mults[16] = {
|
||||
120, /* 1111 -> 12.0x */
|
||||
};
|
||||
|
||||
static const int __initdata ezra_eblcr[16] = {
|
||||
static const int __cpuinitdata ezra_eblcr[16] = {
|
||||
50, /* 0000 -> 5.0x */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -160,7 +160,7 @@ static const int __initdata ezra_eblcr[16] = {
|
||||
/*
|
||||
* VIA C3 (Ezra-T) [C5M].
|
||||
*/
|
||||
static const int __initdata ezrat_mults[32] = {
|
||||
static const int __cpuinitdata ezrat_mults[32] = {
|
||||
100, /* 0000 -> 10.0x */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -196,7 +196,7 @@ static const int __initdata ezrat_mults[32] = {
|
||||
-1, /* 1111 -> RESERVED (12.0x) */
|
||||
};
|
||||
|
||||
static const int __initdata ezrat_eblcr[32] = {
|
||||
static const int __cpuinitdata ezrat_eblcr[32] = {
|
||||
50, /* 0000 -> 5.0x */
|
||||
30, /* 0001 -> 3.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -235,7 +235,7 @@ static const int __initdata ezrat_eblcr[32] = {
|
||||
/*
|
||||
* VIA C3 Nehemiah */
|
||||
|
||||
static const int __initdata nehemiah_mults[32] = {
|
||||
static const int __cpuinitdata nehemiah_mults[32] = {
|
||||
100, /* 0000 -> 10.0x */
|
||||
-1, /* 0001 -> 16.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -270,7 +270,7 @@ static const int __initdata nehemiah_mults[32] = {
|
||||
-1, /* 1111 -> 12.0x */
|
||||
};
|
||||
|
||||
static const int __initdata nehemiah_eblcr[32] = {
|
||||
static const int __cpuinitdata nehemiah_eblcr[32] = {
|
||||
50, /* 0000 -> 5.0x */
|
||||
160, /* 0001 -> 16.0x */
|
||||
40, /* 0010 -> 4.0x */
|
||||
@@ -315,7 +315,7 @@ struct mV_pos {
|
||||
unsigned short pos;
|
||||
};
|
||||
|
||||
static const struct mV_pos __initdata vrm85_mV[32] = {
|
||||
static const struct mV_pos __cpuinitdata vrm85_mV[32] = {
|
||||
{1250, 8}, {1200, 6}, {1150, 4}, {1100, 2},
|
||||
{1050, 0}, {1800, 30}, {1750, 28}, {1700, 26},
|
||||
{1650, 24}, {1600, 22}, {1550, 20}, {1500, 18},
|
||||
@@ -326,14 +326,14 @@ static const struct mV_pos __initdata vrm85_mV[32] = {
|
||||
{1475, 17}, {1425, 15}, {1375, 13}, {1325, 11}
|
||||
};
|
||||
|
||||
static const unsigned char __initdata mV_vrm85[32] = {
|
||||
static const unsigned char __cpuinitdata mV_vrm85[32] = {
|
||||
0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11,
|
||||
0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d,
|
||||
0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19,
|
||||
0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15
|
||||
};
|
||||
|
||||
static const struct mV_pos __initdata mobilevrm_mV[32] = {
|
||||
static const struct mV_pos __cpuinitdata mobilevrm_mV[32] = {
|
||||
{1750, 31}, {1700, 30}, {1650, 29}, {1600, 28},
|
||||
{1550, 27}, {1500, 26}, {1450, 25}, {1400, 24},
|
||||
{1350, 23}, {1300, 22}, {1250, 21}, {1200, 20},
|
||||
@@ -344,7 +344,7 @@ static const struct mV_pos __initdata mobilevrm_mV[32] = {
|
||||
{675, 3}, {650, 2}, {625, 1}, {600, 0}
|
||||
};
|
||||
|
||||
static const unsigned char __initdata mV_mobilevrm[32] = {
|
||||
static const unsigned char __cpuinitdata mV_mobilevrm[32] = {
|
||||
0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
|
||||
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
|
||||
|
@@ -165,8 +165,8 @@ static unsigned int longrun_get(unsigned int cpu)
|
||||
* TMTA rules:
|
||||
* performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
|
||||
*/
|
||||
static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
|
||||
unsigned int *high_freq)
|
||||
static unsigned int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
|
||||
unsigned int *high_freq)
|
||||
{
|
||||
u32 msr_lo, msr_hi;
|
||||
u32 save_lo, save_hi;
|
||||
@@ -258,7 +258,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
|
||||
}
|
||||
|
||||
|
||||
static int __init longrun_cpu_init(struct cpufreq_policy *policy)
|
||||
static int __cpuinit longrun_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
|
@@ -178,13 +178,8 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
|
||||
}
|
||||
}
|
||||
|
||||
if (c->x86 != 0xF) {
|
||||
if (!cpu_has(c, X86_FEATURE_EST))
|
||||
printk(KERN_WARNING PFX "Unknown CPU. "
|
||||
"Please send an e-mail to "
|
||||
"<cpufreq@vger.kernel.org>\n");
|
||||
if (c->x86 != 0xF)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* on P-4s, the TSC runs with constant frequency independent whether
|
||||
* throttling is active or not. */
|
||||
|
@@ -110,7 +110,7 @@ struct pcc_cpu {
|
||||
u32 output_offset;
|
||||
};
|
||||
|
||||
static struct pcc_cpu *pcc_cpu_info;
|
||||
static struct pcc_cpu __percpu *pcc_cpu_info;
|
||||
|
||||
static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
@@ -569,7 +569,7 @@ static int powernow_verify(struct cpufreq_policy *policy)
|
||||
* We will then get the same kind of behaviour already tested under
|
||||
* the "well-known" other OS.
|
||||
*/
|
||||
static int __init fixup_sgtc(void)
|
||||
static int __cpuinit fixup_sgtc(void)
|
||||
{
|
||||
unsigned int sgtc;
|
||||
unsigned int m;
|
||||
@@ -603,7 +603,7 @@ static unsigned int powernow_get(unsigned int cpu)
|
||||
}
|
||||
|
||||
|
||||
static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
|
||||
static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d)
|
||||
{
|
||||
printk(KERN_WARNING PFX
|
||||
"%s laptop with broken PST tables in BIOS detected.\n",
|
||||
@@ -621,7 +621,7 @@ static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
|
||||
* A BIOS update is all that can save them.
|
||||
* Mention this, and disable cpufreq.
|
||||
*/
|
||||
static struct dmi_system_id __initdata powernow_dmi_table[] = {
|
||||
static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = {
|
||||
{
|
||||
.callback = acer_cpufreq_pst,
|
||||
.ident = "Acer Aspire",
|
||||
@@ -633,7 +633,7 @@ static struct dmi_system_id __initdata powernow_dmi_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __init powernow_cpu_init(struct cpufreq_policy *policy)
|
||||
static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
union msr_fidvidstatus fidvidstatus;
|
||||
int result;
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* Based on the powernow-k7.c module written by Dave Jones.
|
||||
* (C) 2003 Dave Jones on behalf of SuSE Labs
|
||||
* (C) 2004 Dominik Brodowski <linux@brodo.de>
|
||||
* (C) 2004 Pavel Machek <pavel@suse.cz>
|
||||
* (C) 2004 Pavel Machek <pavel@ucw.cz>
|
||||
* Licensed under the terms of the GNU GPL License version 2.
|
||||
* Based upon datasheets & sample CPUs kindly provided by AMD.
|
||||
*
|
||||
@@ -806,6 +806,8 @@ static int find_psb_table(struct powernow_k8_data *data)
|
||||
* www.amd.com
|
||||
*/
|
||||
printk(KERN_ERR FW_BUG PFX "No PSB or ACPI _PSS objects\n");
|
||||
printk(KERN_ERR PFX "Make sure that your BIOS is up to date"
|
||||
" and Cool'N'Quiet support is enabled in BIOS setup\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -910,8 +912,8 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
|
||||
{
|
||||
int i;
|
||||
u32 hi = 0, lo = 0;
|
||||
rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo);
|
||||
data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT;
|
||||
rdmsr(MSR_PSTATE_CUR_LIMIT, lo, hi);
|
||||
data->max_hw_pstate = (lo & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT;
|
||||
|
||||
for (i = 0; i < data->acpi_data.state_count; i++) {
|
||||
u32 index;
|
||||
|
@@ -34,6 +34,9 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
|
||||
{
|
||||
&x86_hyper_vmware,
|
||||
&x86_hyper_ms_hyperv,
|
||||
#ifdef CONFIG_XEN_PVHVM
|
||||
&x86_hyper_xen_hvm,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct hypervisor_x86 *x86_hyper;
|
||||
|
@@ -347,8 +347,8 @@ static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
|
||||
return l3;
|
||||
}
|
||||
|
||||
static void __cpuinit
|
||||
amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
|
||||
static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
|
||||
int index)
|
||||
{
|
||||
int node;
|
||||
|
||||
@@ -396,20 +396,39 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
|
||||
this_leaf->l3 = l3_caches[node];
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether a slot used for disabling an L3 index is occupied.
|
||||
* @l3: L3 cache descriptor
|
||||
* @slot: slot number (0..1)
|
||||
*
|
||||
* @returns: the disabled index if used or negative value if slot free.
|
||||
*/
|
||||
int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot)
|
||||
{
|
||||
unsigned int reg = 0;
|
||||
|
||||
pci_read_config_dword(l3->dev, 0x1BC + slot * 4, ®);
|
||||
|
||||
/* check whether this slot is activated already */
|
||||
if (reg & (3UL << 30))
|
||||
return reg & 0xfff;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
|
||||
unsigned int slot)
|
||||
{
|
||||
struct pci_dev *dev = this_leaf->l3->dev;
|
||||
unsigned int reg = 0;
|
||||
int index;
|
||||
|
||||
if (!this_leaf->l3 || !this_leaf->l3->can_disable)
|
||||
return -EINVAL;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
index = amd_get_l3_disable_slot(this_leaf->l3, slot);
|
||||
if (index >= 0)
|
||||
return sprintf(buf, "%d\n", index);
|
||||
|
||||
pci_read_config_dword(dev, 0x1BC + slot * 4, ®);
|
||||
return sprintf(buf, "0x%08x\n", reg);
|
||||
return sprintf(buf, "FREE\n");
|
||||
}
|
||||
|
||||
#define SHOW_CACHE_DISABLE(slot) \
|
||||
@@ -451,37 +470,74 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
|
||||
const char *buf, size_t count,
|
||||
unsigned int slot)
|
||||
/*
|
||||
* disable a L3 cache index by using a disable-slot
|
||||
*
|
||||
* @l3: L3 cache descriptor
|
||||
* @cpu: A CPU on the node containing the L3 cache
|
||||
* @slot: slot number (0..1)
|
||||
* @index: index to disable
|
||||
*
|
||||
* @return: 0 on success, error status on failure
|
||||
*/
|
||||
int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
|
||||
unsigned long index)
|
||||
{
|
||||
struct pci_dev *dev = this_leaf->l3->dev;
|
||||
int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
|
||||
unsigned long val = 0;
|
||||
int ret = 0;
|
||||
|
||||
#define SUBCACHE_MASK (3UL << 20)
|
||||
#define SUBCACHE_INDEX 0xfff
|
||||
|
||||
if (!this_leaf->l3 || !this_leaf->l3->can_disable)
|
||||
/*
|
||||
* check whether this slot is already used or
|
||||
* the index is already disabled
|
||||
*/
|
||||
ret = amd_get_l3_disable_slot(l3, slot);
|
||||
if (ret >= 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* check whether the other slot has disabled the
|
||||
* same index already
|
||||
*/
|
||||
if (index == amd_get_l3_disable_slot(l3, !slot))
|
||||
return -EINVAL;
|
||||
|
||||
/* do not allow writes outside of allowed bits */
|
||||
if ((index & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
|
||||
((index & SUBCACHE_INDEX) > l3->indices))
|
||||
return -EINVAL;
|
||||
|
||||
amd_l3_disable_index(l3, cpu, slot, index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
|
||||
const char *buf, size_t count,
|
||||
unsigned int slot)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
int cpu, err = 0;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (!dev)
|
||||
if (!this_leaf->l3 || !this_leaf->l3->can_disable)
|
||||
return -EINVAL;
|
||||
|
||||
cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
|
||||
|
||||
if (strict_strtoul(buf, 10, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* do not allow writes outside of allowed bits */
|
||||
if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
|
||||
((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
|
||||
return -EINVAL;
|
||||
|
||||
amd_l3_disable_index(this_leaf->l3, cpu, slot, val);
|
||||
|
||||
err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val);
|
||||
if (err) {
|
||||
if (err == -EEXIST)
|
||||
printk(KERN_WARNING "L3 disable slot %d in use!\n",
|
||||
slot);
|
||||
return err;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -502,7 +558,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
|
||||
|
||||
#else /* CONFIG_CPU_SUP_AMD */
|
||||
static void __cpuinit
|
||||
amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
|
||||
amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
|
||||
{
|
||||
};
|
||||
#endif /* CONFIG_CPU_SUP_AMD */
|
||||
@@ -518,7 +574,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
|
||||
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
|
||||
amd_cpuid4(index, &eax, &ebx, &ecx);
|
||||
amd_check_l3_disable(index, this_leaf);
|
||||
amd_check_l3_disable(this_leaf, index);
|
||||
} else {
|
||||
cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@
|
||||
static DEFINE_MUTEX(mce_read_mutex);
|
||||
|
||||
#define rcu_dereference_check_mce(p) \
|
||||
rcu_dereference_check((p), \
|
||||
rcu_dereference_index_check((p), \
|
||||
rcu_read_lock_sched_held() || \
|
||||
lockdep_is_held(&mce_read_mutex))
|
||||
|
||||
@@ -107,8 +107,8 @@ EXPORT_SYMBOL_GPL(x86_mce_decoder_chain);
|
||||
static int default_decode_mce(struct notifier_block *nb, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
pr_emerg("No human readable MCE decoding support on this CPU type.\n");
|
||||
pr_emerg("Run the message through 'mcelog --ascii' to decode.\n");
|
||||
pr_emerg(HW_ERR "No human readable MCE decoding support on this CPU type.\n");
|
||||
pr_emerg(HW_ERR "Run the message through 'mcelog --ascii' to decode.\n");
|
||||
|
||||
return NOTIFY_STOP;
|
||||
}
|
||||
@@ -211,11 +211,11 @@ void mce_log(struct mce *mce)
|
||||
|
||||
static void print_mce(struct mce *m)
|
||||
{
|
||||
pr_emerg("CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
|
||||
pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
|
||||
m->extcpu, m->mcgstatus, m->bank, m->status);
|
||||
|
||||
if (m->ip) {
|
||||
pr_emerg("RIP%s %02x:<%016Lx> ",
|
||||
pr_emerg(HW_ERR "RIP%s %02x:<%016Lx> ",
|
||||
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
|
||||
m->cs, m->ip);
|
||||
|
||||
@@ -224,14 +224,14 @@ static void print_mce(struct mce *m)
|
||||
pr_cont("\n");
|
||||
}
|
||||
|
||||
pr_emerg("TSC %llx ", m->tsc);
|
||||
pr_emerg(HW_ERR "TSC %llx ", m->tsc);
|
||||
if (m->addr)
|
||||
pr_cont("ADDR %llx ", m->addr);
|
||||
if (m->misc)
|
||||
pr_cont("MISC %llx ", m->misc);
|
||||
|
||||
pr_cont("\n");
|
||||
pr_emerg("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
|
||||
pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
|
||||
m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
|
||||
|
||||
/*
|
||||
@@ -241,16 +241,6 @@ static void print_mce(struct mce *m)
|
||||
atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
|
||||
}
|
||||
|
||||
static void print_mce_head(void)
|
||||
{
|
||||
pr_emerg("\nHARDWARE ERROR\n");
|
||||
}
|
||||
|
||||
static void print_mce_tail(void)
|
||||
{
|
||||
pr_emerg("This is not a software problem!\n");
|
||||
}
|
||||
|
||||
#define PANIC_TIMEOUT 5 /* 5 seconds */
|
||||
|
||||
static atomic_t mce_paniced;
|
||||
@@ -291,7 +281,6 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
|
||||
if (atomic_inc_return(&mce_fake_paniced) > 1)
|
||||
return;
|
||||
}
|
||||
print_mce_head();
|
||||
/* First print corrected ones that are still unlogged */
|
||||
for (i = 0; i < MCE_LOG_LEN; i++) {
|
||||
struct mce *m = &mcelog.entry[i];
|
||||
@@ -322,16 +311,15 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
|
||||
apei_err = apei_write_mce(final);
|
||||
}
|
||||
if (cpu_missing)
|
||||
printk(KERN_EMERG "Some CPUs didn't answer in synchronization\n");
|
||||
print_mce_tail();
|
||||
pr_emerg(HW_ERR "Some CPUs didn't answer in synchronization\n");
|
||||
if (exp)
|
||||
printk(KERN_EMERG "Machine check: %s\n", exp);
|
||||
pr_emerg(HW_ERR "Machine check: %s\n", exp);
|
||||
if (!fake_panic) {
|
||||
if (panic_timeout == 0)
|
||||
panic_timeout = mce_panic_timeout;
|
||||
panic(msg);
|
||||
} else
|
||||
printk(KERN_EMERG "Fake kernel panic: %s\n", msg);
|
||||
pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg);
|
||||
}
|
||||
|
||||
/* Support code for software error injection */
|
||||
@@ -600,6 +588,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
|
||||
*/
|
||||
if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
|
||||
mce_log(&m);
|
||||
atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
|
||||
add_taint(TAINT_MACHINE_CHECK);
|
||||
}
|
||||
|
||||
@@ -1220,7 +1209,7 @@ int mce_notify_irq(void)
|
||||
schedule_work(&mce_trigger_work);
|
||||
|
||||
if (__ratelimit(&ratelimit))
|
||||
printk(KERN_INFO "Machine check events logged\n");
|
||||
pr_info(HW_ERR "Machine check events logged\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -95,19 +95,20 @@ static void cmci_discover(int banks, int boot)
|
||||
rdmsrl(MSR_IA32_MCx_CTL2(i), val);
|
||||
|
||||
/* Already owned by someone else? */
|
||||
if (val & CMCI_EN) {
|
||||
if (val & MCI_CTL2_CMCI_EN) {
|
||||
if (test_and_clear_bit(i, owned) && !boot)
|
||||
print_update("SHD", &hdr, i);
|
||||
__clear_bit(i, __get_cpu_var(mce_poll_banks));
|
||||
continue;
|
||||
}
|
||||
|
||||
val |= CMCI_EN | CMCI_THRESHOLD;
|
||||
val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK;
|
||||
val |= MCI_CTL2_CMCI_EN | CMCI_THRESHOLD;
|
||||
wrmsrl(MSR_IA32_MCx_CTL2(i), val);
|
||||
rdmsrl(MSR_IA32_MCx_CTL2(i), val);
|
||||
|
||||
/* Did the enable bit stick? -- the bank supports CMCI */
|
||||
if (val & CMCI_EN) {
|
||||
if (val & MCI_CTL2_CMCI_EN) {
|
||||
if (!test_and_set_bit(i, owned) && !boot)
|
||||
print_update("CMCI", &hdr, i);
|
||||
__clear_bit(i, __get_cpu_var(mce_poll_banks));
|
||||
@@ -155,7 +156,7 @@ void cmci_clear(void)
|
||||
continue;
|
||||
/* Disable CMCI */
|
||||
rdmsrl(MSR_IA32_MCx_CTL2(i), val);
|
||||
val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
|
||||
val &= ~(MCI_CTL2_CMCI_EN|MCI_CTL2_CMCI_THRESHOLD_MASK);
|
||||
wrmsrl(MSR_IA32_MCx_CTL2(i), val);
|
||||
__clear_bit(i, __get_cpu_var(mce_banks_owned));
|
||||
}
|
||||
|
@@ -34,15 +34,25 @@
|
||||
/* How long to wait between reporting thermal events */
|
||||
#define CHECK_INTERVAL (300 * HZ)
|
||||
|
||||
/*
|
||||
* Current thermal throttling state:
|
||||
*/
|
||||
struct thermal_state {
|
||||
bool is_throttled;
|
||||
#define THERMAL_THROTTLING_EVENT 0
|
||||
#define POWER_LIMIT_EVENT 1
|
||||
|
||||
/*
|
||||
* Current thermal event state:
|
||||
*/
|
||||
struct _thermal_state {
|
||||
bool new_event;
|
||||
int event;
|
||||
u64 next_check;
|
||||
unsigned long throttle_count;
|
||||
unsigned long last_throttle_count;
|
||||
unsigned long count;
|
||||
unsigned long last_count;
|
||||
};
|
||||
|
||||
struct thermal_state {
|
||||
struct _thermal_state core_throttle;
|
||||
struct _thermal_state core_power_limit;
|
||||
struct _thermal_state package_throttle;
|
||||
struct _thermal_state package_power_limit;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct thermal_state, thermal_state);
|
||||
@@ -53,11 +63,13 @@ static u32 lvtthmr_init __read_mostly;
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
#define define_therm_throt_sysdev_one_ro(_name) \
|
||||
static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
|
||||
static SYSDEV_ATTR(_name, 0444, \
|
||||
therm_throt_sysdev_show_##_name, \
|
||||
NULL) \
|
||||
|
||||
#define define_therm_throt_sysdev_show_func(name) \
|
||||
#define define_therm_throt_sysdev_show_func(event, name) \
|
||||
\
|
||||
static ssize_t therm_throt_sysdev_show_##name( \
|
||||
static ssize_t therm_throt_sysdev_show_##event##_##name( \
|
||||
struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, \
|
||||
char *buf) \
|
||||
@@ -66,30 +78,42 @@ static ssize_t therm_throt_sysdev_show_##name( \
|
||||
ssize_t ret; \
|
||||
\
|
||||
preempt_disable(); /* CPU hotplug */ \
|
||||
if (cpu_online(cpu)) \
|
||||
if (cpu_online(cpu)) { \
|
||||
ret = sprintf(buf, "%lu\n", \
|
||||
per_cpu(thermal_state, cpu).name); \
|
||||
else \
|
||||
per_cpu(thermal_state, cpu).event.name); \
|
||||
} else \
|
||||
ret = 0; \
|
||||
preempt_enable(); \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
define_therm_throt_sysdev_show_func(throttle_count);
|
||||
define_therm_throt_sysdev_one_ro(throttle_count);
|
||||
define_therm_throt_sysdev_show_func(core_throttle, count);
|
||||
define_therm_throt_sysdev_one_ro(core_throttle_count);
|
||||
|
||||
define_therm_throt_sysdev_show_func(core_power_limit, count);
|
||||
define_therm_throt_sysdev_one_ro(core_power_limit_count);
|
||||
|
||||
define_therm_throt_sysdev_show_func(package_throttle, count);
|
||||
define_therm_throt_sysdev_one_ro(package_throttle_count);
|
||||
|
||||
define_therm_throt_sysdev_show_func(package_power_limit, count);
|
||||
define_therm_throt_sysdev_one_ro(package_power_limit_count);
|
||||
|
||||
static struct attribute *thermal_throttle_attrs[] = {
|
||||
&attr_throttle_count.attr,
|
||||
&attr_core_throttle_count.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group thermal_throttle_attr_group = {
|
||||
static struct attribute_group thermal_attr_group = {
|
||||
.attrs = thermal_throttle_attrs,
|
||||
.name = "thermal_throttle"
|
||||
};
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
#define CORE_LEVEL 0
|
||||
#define PACKAGE_LEVEL 1
|
||||
|
||||
/***
|
||||
* therm_throt_process - Process thermal throttling event from interrupt
|
||||
* @curr: Whether the condition is current or not (boolean), since the
|
||||
@@ -106,39 +130,70 @@ static struct attribute_group thermal_throttle_attr_group = {
|
||||
* 1 : Event should be logged further, and a message has been
|
||||
* printed to the syslog.
|
||||
*/
|
||||
static int therm_throt_process(bool is_throttled)
|
||||
static int therm_throt_process(bool new_event, int event, int level)
|
||||
{
|
||||
struct thermal_state *state;
|
||||
unsigned int this_cpu;
|
||||
bool was_throttled;
|
||||
struct _thermal_state *state;
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
bool old_event;
|
||||
u64 now;
|
||||
struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
|
||||
|
||||
this_cpu = smp_processor_id();
|
||||
now = get_jiffies_64();
|
||||
state = &per_cpu(thermal_state, this_cpu);
|
||||
if (level == CORE_LEVEL) {
|
||||
if (event == THERMAL_THROTTLING_EVENT)
|
||||
state = &pstate->core_throttle;
|
||||
else if (event == POWER_LIMIT_EVENT)
|
||||
state = &pstate->core_power_limit;
|
||||
else
|
||||
return 0;
|
||||
} else if (level == PACKAGE_LEVEL) {
|
||||
if (event == THERMAL_THROTTLING_EVENT)
|
||||
state = &pstate->package_throttle;
|
||||
else if (event == POWER_LIMIT_EVENT)
|
||||
state = &pstate->package_power_limit;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
was_throttled = state->is_throttled;
|
||||
state->is_throttled = is_throttled;
|
||||
old_event = state->new_event;
|
||||
state->new_event = new_event;
|
||||
|
||||
if (is_throttled)
|
||||
state->throttle_count++;
|
||||
if (new_event)
|
||||
state->count++;
|
||||
|
||||
if (time_before64(now, state->next_check) &&
|
||||
state->throttle_count != state->last_throttle_count)
|
||||
state->count != state->last_count)
|
||||
return 0;
|
||||
|
||||
state->next_check = now + CHECK_INTERVAL;
|
||||
state->last_throttle_count = state->throttle_count;
|
||||
state->last_count = state->count;
|
||||
|
||||
/* if we just entered the thermal event */
|
||||
if (is_throttled) {
|
||||
printk(KERN_CRIT "CPU%d: Temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, state->throttle_count);
|
||||
if (new_event) {
|
||||
if (event == THERMAL_THROTTLING_EVENT)
|
||||
printk(KERN_CRIT "CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
|
||||
this_cpu,
|
||||
level == CORE_LEVEL ? "Core" : "Package",
|
||||
state->count);
|
||||
else
|
||||
printk(KERN_CRIT "CPU%d: %s power limit notification (total events = %lu)\n",
|
||||
this_cpu,
|
||||
level == CORE_LEVEL ? "Core" : "Package",
|
||||
state->count);
|
||||
|
||||
add_taint(TAINT_MACHINE_CHECK);
|
||||
return 1;
|
||||
}
|
||||
if (was_throttled) {
|
||||
printk(KERN_INFO "CPU%d: Temperature/speed normal\n", this_cpu);
|
||||
if (old_event) {
|
||||
if (event == THERMAL_THROTTLING_EVENT)
|
||||
printk(KERN_INFO "CPU%d: %s temperature/speed normal\n",
|
||||
this_cpu,
|
||||
level == CORE_LEVEL ? "Core" : "Package");
|
||||
else
|
||||
printk(KERN_INFO "CPU%d: %s power limit normal\n",
|
||||
this_cpu,
|
||||
level == CORE_LEVEL ? "Core" : "Package");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -149,13 +204,32 @@ static int therm_throt_process(bool is_throttled)
|
||||
/* Add/Remove thermal_throttle interface for CPU device: */
|
||||
static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
|
||||
{
|
||||
return sysfs_create_group(&sys_dev->kobj,
|
||||
&thermal_throttle_attr_group);
|
||||
int err;
|
||||
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
||||
|
||||
err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
err = sysfs_add_file_to_group(&sys_dev->kobj,
|
||||
&attr_core_power_limit_count.attr,
|
||||
thermal_attr_group.name);
|
||||
if (cpu_has(c, X86_FEATURE_PTS))
|
||||
err = sysfs_add_file_to_group(&sys_dev->kobj,
|
||||
&attr_package_throttle_count.attr,
|
||||
thermal_attr_group.name);
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
err = sysfs_add_file_to_group(&sys_dev->kobj,
|
||||
&attr_package_power_limit_count.attr,
|
||||
thermal_attr_group.name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
|
||||
{
|
||||
sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
|
||||
sysfs_remove_group(&sys_dev->kobj, &thermal_attr_group);
|
||||
}
|
||||
|
||||
/* Mutex protecting device creation against CPU hotplug: */
|
||||
@@ -226,14 +300,50 @@ device_initcall(thermal_throttle_init_device);
|
||||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
/*
|
||||
* Set up the most two significant bit to notify mce log that this thermal
|
||||
* event type.
|
||||
* This is a temp solution. May be changed in the future with mce log
|
||||
* infrasture.
|
||||
*/
|
||||
#define CORE_THROTTLED (0)
|
||||
#define CORE_POWER_LIMIT ((__u64)1 << 62)
|
||||
#define PACKAGE_THROTTLED ((__u64)2 << 62)
|
||||
#define PACKAGE_POWER_LIMIT ((__u64)3 << 62)
|
||||
|
||||
/* Thermal transition interrupt handler */
|
||||
static void intel_thermal_interrupt(void)
|
||||
{
|
||||
__u64 msr_val;
|
||||
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
||||
|
||||
rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
|
||||
if (therm_throt_process((msr_val & THERM_STATUS_PROCHOT) != 0))
|
||||
mce_log_therm_throt_event(msr_val);
|
||||
|
||||
if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT,
|
||||
THERMAL_THROTTLING_EVENT,
|
||||
CORE_LEVEL) != 0)
|
||||
mce_log_therm_throt_event(CORE_THROTTLED | msr_val);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
if (therm_throt_process(msr_val & THERM_STATUS_POWER_LIMIT,
|
||||
POWER_LIMIT_EVENT,
|
||||
CORE_LEVEL) != 0)
|
||||
mce_log_therm_throt_event(CORE_POWER_LIMIT | msr_val);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_PTS)) {
|
||||
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
|
||||
if (therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
|
||||
THERMAL_THROTTLING_EVENT,
|
||||
PACKAGE_LEVEL) != 0)
|
||||
mce_log_therm_throt_event(PACKAGE_THROTTLED | msr_val);
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
if (therm_throt_process(msr_val &
|
||||
PACKAGE_THERM_STATUS_POWER_LIMIT,
|
||||
POWER_LIMIT_EVENT,
|
||||
PACKAGE_LEVEL) != 0)
|
||||
mce_log_therm_throt_event(PACKAGE_POWER_LIMIT
|
||||
| msr_val);
|
||||
}
|
||||
}
|
||||
|
||||
static void unexpected_thermal_interrupt(void)
|
||||
@@ -335,8 +445,26 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
|
||||
apic_write(APIC_LVTTHMR, h);
|
||||
|
||||
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
|
||||
wrmsr(MSR_IA32_THERM_INTERRUPT,
|
||||
l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
wrmsr(MSR_IA32_THERM_INTERRUPT,
|
||||
l | (THERM_INT_LOW_ENABLE
|
||||
| THERM_INT_HIGH_ENABLE | THERM_INT_PLN_ENABLE), h);
|
||||
else
|
||||
wrmsr(MSR_IA32_THERM_INTERRUPT,
|
||||
l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_PTS)) {
|
||||
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
|
||||
if (cpu_has(c, X86_FEATURE_PLN))
|
||||
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
l | (PACKAGE_THERM_INT_LOW_ENABLE
|
||||
| PACKAGE_THERM_INT_HIGH_ENABLE
|
||||
| PACKAGE_THERM_INT_PLN_ENABLE), h);
|
||||
else
|
||||
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
l | (PACKAGE_THERM_INT_LOW_ENABLE
|
||||
| PACKAGE_THERM_INT_HIGH_ENABLE), h);
|
||||
}
|
||||
|
||||
smp_thermal_vector = intel_thermal_interrupt;
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
struct ms_hyperv_info ms_hyperv;
|
||||
EXPORT_SYMBOL_GPL(ms_hyperv);
|
||||
|
||||
static bool __init ms_hyperv_platform(void)
|
||||
{
|
||||
|
@@ -632,9 +632,9 @@ static void __init mtrr_print_out_one_result(int i)
|
||||
unsigned long gran_base, chunk_base, lose_base;
|
||||
char gran_factor, chunk_factor, lose_factor;
|
||||
|
||||
gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
|
||||
chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
|
||||
lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
|
||||
gran_base = to_size_factor(result[i].gran_sizek, &gran_factor);
|
||||
chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor);
|
||||
lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor);
|
||||
|
||||
pr_info("%sgran_size: %ld%c \tchunk_size: %ld%c \t",
|
||||
result[i].bad ? "*BAD*" : " ",
|
||||
|
@@ -433,13 +433,12 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
|
||||
{
|
||||
unsigned int mask_lo, mask_hi, base_lo, base_hi;
|
||||
unsigned int tmp, hi;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* get_mtrr doesn't need to update mtrr_state, also it could be called
|
||||
* from any cpu, so try to print it out directly.
|
||||
*/
|
||||
cpu = get_cpu();
|
||||
get_cpu();
|
||||
|
||||
rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <linux/types.h> /* FIXME: kvm_para.h needs this */
|
||||
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/kvm_para.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
@@ -143,22 +144,28 @@ struct set_mtrr_data {
|
||||
mtrr_type smp_type;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct cpu_stop_work, mtrr_work);
|
||||
|
||||
/**
|
||||
* ipi_handler - Synchronisation handler. Executed by "other" CPUs.
|
||||
* mtrr_work_handler - Synchronisation handler. Executed by "other" CPUs.
|
||||
* @info: pointer to mtrr configuration data
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
static void ipi_handler(void *info)
|
||||
static int mtrr_work_handler(void *info)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
struct set_mtrr_data *data = info;
|
||||
unsigned long flags;
|
||||
|
||||
atomic_dec(&data->count);
|
||||
while (!atomic_read(&data->gate))
|
||||
cpu_relax();
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
atomic_dec(&data->count);
|
||||
while (!atomic_read(&data->gate))
|
||||
while (atomic_read(&data->gate))
|
||||
cpu_relax();
|
||||
|
||||
/* The master has cleared me to execute */
|
||||
@@ -173,12 +180,13 @@ static void ipi_handler(void *info)
|
||||
}
|
||||
|
||||
atomic_dec(&data->count);
|
||||
while (atomic_read(&data->gate))
|
||||
while (!atomic_read(&data->gate))
|
||||
cpu_relax();
|
||||
|
||||
atomic_dec(&data->count);
|
||||
local_irq_restore(flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int types_compatible(mtrr_type type1, mtrr_type type2)
|
||||
@@ -198,7 +206,7 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
|
||||
*
|
||||
* This is kinda tricky, but fortunately, Intel spelled it out for us cleanly:
|
||||
*
|
||||
* 1. Send IPI to do the following:
|
||||
* 1. Queue work to do the following on all processors:
|
||||
* 2. Disable Interrupts
|
||||
* 3. Wait for all procs to do so
|
||||
* 4. Enter no-fill cache mode
|
||||
@@ -215,14 +223,17 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
|
||||
* 15. Enable interrupts.
|
||||
*
|
||||
* What does that mean for us? Well, first we set data.count to the number
|
||||
* of CPUs. As each CPU disables interrupts, it'll decrement it once. We wait
|
||||
* until it hits 0 and proceed. We set the data.gate flag and reset data.count.
|
||||
* Meanwhile, they are waiting for that flag to be set. Once it's set, each
|
||||
* of CPUs. As each CPU announces that it started the rendezvous handler by
|
||||
* decrementing the count, We reset data.count and set the data.gate flag
|
||||
* allowing all the cpu's to proceed with the work. As each cpu disables
|
||||
* interrupts, it'll decrement data.count once. We wait until it hits 0 and
|
||||
* proceed. We clear the data.gate flag and reset data.count. Meanwhile, they
|
||||
* are waiting for that flag to be cleared. Once it's cleared, each
|
||||
* CPU goes through the transition of updating MTRRs.
|
||||
* The CPU vendors may each do it differently,
|
||||
* so we call mtrr_if->set() callback and let them take care of it.
|
||||
* When they're done, they again decrement data->count and wait for data.gate
|
||||
* to be reset.
|
||||
* to be set.
|
||||
* When we finish, we wait for data.count to hit 0 and toggle the data.gate flag
|
||||
* Everyone then enables interrupts and we all continue on.
|
||||
*
|
||||
@@ -234,6 +245,9 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
{
|
||||
struct set_mtrr_data data;
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
|
||||
preempt_disable();
|
||||
|
||||
data.smp_reg = reg;
|
||||
data.smp_base = base;
|
||||
@@ -246,8 +260,23 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
atomic_set(&data.gate, 0);
|
||||
|
||||
/* Start the ball rolling on other CPUs */
|
||||
if (smp_call_function(ipi_handler, &data, 0) != 0)
|
||||
panic("mtrr: timed out waiting for other CPUs\n");
|
||||
for_each_online_cpu(cpu) {
|
||||
struct cpu_stop_work *work = &per_cpu(mtrr_work, cpu);
|
||||
|
||||
if (cpu == smp_processor_id())
|
||||
continue;
|
||||
|
||||
stop_one_cpu_nowait(cpu, mtrr_work_handler, &data, work);
|
||||
}
|
||||
|
||||
|
||||
while (atomic_read(&data.count))
|
||||
cpu_relax();
|
||||
|
||||
/* Ok, reset count and toggle gate */
|
||||
atomic_set(&data.count, num_booting_cpus() - 1);
|
||||
smp_wmb();
|
||||
atomic_set(&data.gate, 1);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
@@ -257,7 +286,7 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
/* Ok, reset count and toggle gate */
|
||||
atomic_set(&data.count, num_booting_cpus() - 1);
|
||||
smp_wmb();
|
||||
atomic_set(&data.gate, 1);
|
||||
atomic_set(&data.gate, 0);
|
||||
|
||||
/* Do our MTRR business */
|
||||
|
||||
@@ -279,7 +308,7 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
|
||||
atomic_set(&data.count, num_booting_cpus() - 1);
|
||||
smp_wmb();
|
||||
atomic_set(&data.gate, 0);
|
||||
atomic_set(&data.gate, 1);
|
||||
|
||||
/*
|
||||
* Wait here for everyone to have seen the gate change
|
||||
@@ -289,6 +318,7 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
||||
cpu_relax();
|
||||
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
63
arch/x86/kernel/cpu/scattered.c
Normal file
63
arch/x86/kernel/cpu/scattered.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Routines to indentify additional cpu features that are scattered in
|
||||
* cpuid space.
|
||||
*/
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/pat.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#include <asm/apic.h>
|
||||
|
||||
struct cpuid_bit {
|
||||
u16 feature;
|
||||
u8 reg;
|
||||
u8 bit;
|
||||
u32 level;
|
||||
u32 sub_leaf;
|
||||
};
|
||||
|
||||
enum cpuid_regs {
|
||||
CR_EAX = 0,
|
||||
CR_ECX,
|
||||
CR_EDX,
|
||||
CR_EBX
|
||||
};
|
||||
|
||||
void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 max_level;
|
||||
u32 regs[4];
|
||||
const struct cpuid_bit *cb;
|
||||
|
||||
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
|
||||
{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 },
|
||||
{ X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 },
|
||||
{ X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 },
|
||||
{ X86_FEATURE_PTS, CR_EAX, 6, 0x00000006, 0 },
|
||||
{ X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 },
|
||||
{ X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 },
|
||||
{ X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 },
|
||||
{ X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 },
|
||||
{ X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 },
|
||||
{ X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 },
|
||||
{ X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 },
|
||||
{ X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a, 0 },
|
||||
{ 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
for (cb = cpuid_bits; cb->feature; cb++) {
|
||||
|
||||
/* Verify that the level is valid */
|
||||
max_level = cpuid_eax(cb->level & 0xffff0000);
|
||||
if (max_level < cb->level ||
|
||||
max_level > (cb->level | 0xffff))
|
||||
continue;
|
||||
|
||||
cpuid_count(cb->level, cb->sub_leaf, ®s[CR_EAX],
|
||||
®s[CR_EBX], ®s[CR_ECX], ®s[CR_EDX]);
|
||||
|
||||
if (regs[cb->reg] & (1 << cb->bit))
|
||||
set_cpu_cap(c, cb->feature);
|
||||
}
|
||||
}
|
@@ -1,62 +1,14 @@
|
||||
/*
|
||||
* Routines to indentify additional cpu features that are scattered in
|
||||
* cpuid space.
|
||||
* Check for extended topology enumeration cpuid leaf 0xb and if it
|
||||
* exists, use it for populating initial_apicid and cpu topology
|
||||
* detection.
|
||||
*/
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/pat.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#include <asm/apic.h>
|
||||
|
||||
struct cpuid_bit {
|
||||
u16 feature;
|
||||
u8 reg;
|
||||
u8 bit;
|
||||
u32 level;
|
||||
};
|
||||
|
||||
enum cpuid_regs {
|
||||
CR_EAX = 0,
|
||||
CR_ECX,
|
||||
CR_EDX,
|
||||
CR_EBX
|
||||
};
|
||||
|
||||
void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 max_level;
|
||||
u32 regs[4];
|
||||
const struct cpuid_bit *cb;
|
||||
|
||||
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
|
||||
{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
|
||||
{ X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
|
||||
{ X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006 },
|
||||
{ X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 },
|
||||
{ X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a },
|
||||
{ X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a },
|
||||
{ X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a },
|
||||
{ X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
for (cb = cpuid_bits; cb->feature; cb++) {
|
||||
|
||||
/* Verify that the level is valid */
|
||||
max_level = cpuid_eax(cb->level & 0xffff0000);
|
||||
if (max_level < cb->level ||
|
||||
max_level > (cb->level | 0xffff))
|
||||
continue;
|
||||
|
||||
cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX],
|
||||
®s[CR_ECX], ®s[CR_EDX]);
|
||||
|
||||
if (regs[cb->reg] & (1 << cb->bit))
|
||||
set_cpu_cap(c, cb->feature);
|
||||
}
|
||||
}
|
||||
|
||||
/* leaf 0xb SMT level */
|
||||
#define SMT_LEVEL 0
|
||||
|
@@ -51,7 +51,7 @@ static inline int __vmware_platform(void)
|
||||
|
||||
static unsigned long vmware_get_tsc_khz(void)
|
||||
{
|
||||
uint64_t tsc_hz;
|
||||
uint64_t tsc_hz, lpj;
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
|
||||
@@ -62,6 +62,13 @@ static unsigned long vmware_get_tsc_khz(void)
|
||||
printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n",
|
||||
(unsigned long) tsc_hz / 1000,
|
||||
(unsigned long) tsc_hz % 1000);
|
||||
|
||||
if (!preset_lpj) {
|
||||
lpj = ((u64)tsc_hz * 1000);
|
||||
do_div(lpj, HZ);
|
||||
preset_lpj = lpj;
|
||||
}
|
||||
|
||||
return tsc_hz;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user