mce_intel_64.c 2.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * Intel specific MCE features.
 * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/mce.h>
#include <asm/hw_irq.h>
A
Andi Kleen 已提交
13
#include <asm/idle.h>
14
#include <asm/therm_throt.h>
L
Linus Torvalds 已提交
15 16 17

asmlinkage void smp_thermal_interrupt(void)
{
18
	__u64 msr_val;
L
Linus Torvalds 已提交
19 20 21

	ack_APIC_irq();

A
Andi Kleen 已提交
22
	exit_idle();
L
Linus Torvalds 已提交
23
	irq_enter();
24 25 26 27 28

	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
	if (therm_throt_process(msr_val & 1))
		mce_log_therm_throt_event(smp_processor_id(), msr_val);

29
	inc_irq_stat(irq_thermal_count);
L
Linus Torvalds 已提交
30 31 32
	irq_exit();
}

33
static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
{
	u32 l, h;
	int tm2 = 0;
	unsigned int cpu = smp_processor_id();

	if (!cpu_has(c, X86_FEATURE_ACPI))
		return;

	if (!cpu_has(c, X86_FEATURE_ACC))
		return;

	/* first check if TM1 is already enabled by the BIOS, in which
	 * case there might be some SMM goo which handles it, so we can't even
	 * put a handler since it might be delivered via SMI already.
	 */
	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
	h = apic_read(APIC_LVTTHMR);
	if ((l & (1 << 3)) && (h & APIC_DM_SMI)) {
		printk(KERN_DEBUG
		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
		return;
	}

	if (cpu_has(c, X86_FEATURE_TM2) && (l & (1 << 13)))
		tm2 = 1;

	if (h & APIC_VECTOR_MASK) {
		printk(KERN_DEBUG
		       "CPU%d: Thermal LVT vector (%#x) already "
		       "installed\n", cpu, (h & APIC_VECTOR_MASK));
		return;
	}

	h = THERMAL_APIC_VECTOR;
	h |= (APIC_DM_FIXED | APIC_LVT_MASKED);
69
	apic_write(APIC_LVTTHMR, h);
L
Linus Torvalds 已提交
70 71 72 73 74 75 76 77

	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h);

	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
	wrmsr(MSR_IA32_MISC_ENABLE, l | (1 << 3), h);

	l = apic_read(APIC_LVTTHMR);
78
	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
L
Linus Torvalds 已提交
79 80
	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
		cpu, tm2 ? "TM2" : "TM1");
81 82 83

	/* enable thermal throttle processing */
	atomic_set(&therm_throt_en, 1);
L
Linus Torvalds 已提交
84 85 86
	return;
}

87
void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
88 89 90
{
	intel_init_thermal(c);
}