mce_intel_64.c 2.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 * 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>
Y
Yinghai Lu 已提交
10
#include <asm/genapic.h>
L
Linus Torvalds 已提交
11 12 13
#include <asm/msr.h>
#include <asm/mce.h>
#include <asm/hw_irq.h>
A
Andi Kleen 已提交
14
#include <asm/idle.h>
15
#include <asm/therm_throt.h>
L
Linus Torvalds 已提交
16 17 18

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

	ack_APIC_irq();

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

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

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

34
static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
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 69
{
	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);
70
	apic_write(APIC_LVTTHMR, h);
L
Linus Torvalds 已提交
71 72 73 74 75 76 77 78

	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);
79
	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
L
Linus Torvalds 已提交
80 81
	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
		cpu, tm2 ? "TM2" : "TM1");
82 83 84

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

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