* [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events.
@ 2006-09-22 0:48 Dmitriy Zavin
2006-09-22 0:48 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Dmitriy Zavin
2006-09-22 5:49 ` [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Andi Kleen
0 siblings, 2 replies; 8+ messages in thread
From: Dmitriy Zavin @ 2006-09-22 0:48 UTC (permalink / raw)
To: linux-kernel; +Cc: ak, akpm
This patch-set factors out the thermal throttle processing code
from i386 and x86_64 into a separate file (therm_throt.c).
This allows consistent reporting of CPU thermal throttle events.
Furthermore, a counter is added to /sys that keeps track of the
number of thermal events, such that the user knows how bad the
thermal problem might be (since the logging to syslog and mcelog
is rate limited).
Tested on 32bit and 64bit Intel P4 Xeons.
Differences from last cut:
- No more #ifdef CONFIG_X86_64.. sorry Andi :). x86_64 specific
code is in arch/x86_64/kernel/mce.c
- Commented the need/use for time_before64/time_after64.
(I addressed Andi Kleen's concern about these macros in a
followup from last attempt, but never got a response.)
- More comments in therm_throt.c and individual patch descriptions
arch/i386/kernel/cpu/mcheck/Makefile | 2
arch/i386/kernel/cpu/mcheck/p4.c | 26 +---
arch/i386/kernel/cpu/mcheck/therm_throt.c | 171 ++++++++++++++++++++++++++++++
arch/x86_64/kernel/Makefile | 4
arch/x86_64/kernel/mce.c | 27 ++++
arch/x86_64/kernel/mce_intel.c | 30 +----
include/asm-i386/therm_throt.h | 9 +
include/asm-x86_64/mce.h | 4
include/asm-x86_64/therm_throt.h | 1
include/linux/jiffies.h | 15 ++
10 files changed, 248 insertions(+), 41 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing 2006-09-22 0:48 [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Dmitriy Zavin @ 2006-09-22 0:48 ` Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 2/4] jiffies: Add 64bit jiffies compares (for use with get_jiffies_64) Dmitriy Zavin 2006-09-22 5:50 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Andi Kleen 2006-09-22 5:49 ` [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Andi Kleen 1 sibling, 2 replies; 8+ messages in thread From: Dmitriy Zavin @ 2006-09-22 0:48 UTC (permalink / raw) To: linux-kernel; +Cc: ak, akpm Refactor the event processing (syslog messaging and rate limiting) into separate file therm_throt.c. This allows consistent reporting of CPU thermal throttle events. After ACK'ing the interrupt, if the event is current, the user (p4.c/mce_intel.c) calls therm_throt_process to log (and rate limit) the event. If that function returns 1, the user has the option to log things further (such as to mce_log in x86_64). Signed-off-by: Dmitriy Zavin <dmitriyz@google.com> --- arch/i386/kernel/cpu/mcheck/Makefile | 2 + arch/i386/kernel/cpu/mcheck/p4.c | 23 +++--------- arch/i386/kernel/cpu/mcheck/therm_throt.c | 58 +++++++++++++++++++++++++++++ arch/x86_64/kernel/Makefile | 4 +- arch/x86_64/kernel/mce.c | 27 ++++++++++++++ arch/x86_64/kernel/mce_intel.c | 27 +++----------- include/asm-i386/therm_throt.h | 6 +++ include/asm-x86_64/mce.h | 4 ++ include/asm-x86_64/therm_throt.h | 1 + 9 files changed, 111 insertions(+), 41 deletions(-) diff --git a/arch/i386/kernel/cpu/mcheck/Makefile b/arch/i386/kernel/cpu/mcheck/Makefile index 30808f3..f1ebe1c 100644 --- a/arch/i386/kernel/cpu/mcheck/Makefile +++ b/arch/i386/kernel/cpu/mcheck/Makefile @@ -1,2 +1,2 @@ -obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o +obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o therm_throt.o obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index b95f1b3..d83a669 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -13,6 +13,8 @@ #include <asm/system.h> #include <asm/msr.h> #include <asm/apic.h> +#include <asm/therm_throt.h> + #include "mce.h" /* as supported by the P4/Xeon family */ @@ -44,25 +46,12 @@ static void unexpected_thermal_interrupt /* P4/Xeon Thermal transition interrupt handler */ static void intel_thermal_interrupt(struct pt_regs *regs) { - u32 l, h; - unsigned int cpu = smp_processor_id(); - static unsigned long next[NR_CPUS]; + __u64 msr_val; ack_APIC_irq(); - if (time_after(next[cpu], jiffies)) - return; - - next[cpu] = jiffies + HZ*5; - rdmsr(MSR_IA32_THERM_STATUS, l, h); - if (l & 0x1) { - printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu); - printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n", - cpu); - add_taint(TAINT_MACHINE_CHECK); - } else { - printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); - } + rdmsrl(MSR_IA32_THERM_STATUS, msr_val); + therm_throt_process(msr_val & 0x1); } /* Thermal interrupt handler for this CPU setup */ @@ -122,7 +111,7 @@ static void intel_init_thermal(struct cp rdmsr (MSR_IA32_MISC_ENABLE, l, h); wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h); - + l = apic_read (APIC_LVTTHMR); apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED); printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c new file mode 100644 index 0000000..85eba00 --- /dev/null +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -0,0 +1,58 @@ +/* + * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c + * + * Thermal throttle event support code. + * + * Author: Dmitriy Zavin (dmitriyz@google.com) + * + * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c. + * + */ + +#include <linux/percpu.h> +#include <linux/cpu.h> +#include <asm/cpu.h> +#include <linux/notifier.h> +#include <asm/therm_throt.h> + +/* How long to wait between reporting thermal events */ +#define CHECK_INTERVAL (300 * HZ) + +static DEFINE_PER_CPU(unsigned long, next_check); + +/*** + * therm_throt_process - Process thermal throttling event + * @curr: Whether the condition is current or not (boolean), since the + * thermal interrupt normally gets called both when the thermal + * event begins and once the event has ended. + * + * This function is normally called by the thermal interrupt after the + * IRQ has been acknowledged. + * + * It will take care of rate limiting and printing messages to the syslog. + * + * Returns: 0 : Event should NOT be further logged, i.e. still in + * "timeout" from previous log message. + * 1 : Event should be logged further, and a message has been + * printed to the syslog. + */ +int therm_throt_process(int curr) +{ + unsigned int cpu = smp_processor_id(); + + if (time_before(jiffies, __get_cpu_var(next_check))) + return 0; + + __get_cpu_var(next_check) = jiffies + CHECK_INTERVAL; + + /* if we just entered the thermal event */ + if (curr) { + printk(KERN_CRIT "CPU%d: Temperature above threshold, " + "cpu clock throttled\n", cpu); + add_taint(TAINT_MACHINE_CHECK); + } else { + printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu); + } + + return 1; +} diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index b5aaeaf..d97cec0 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := process.o signal.o entry.o trap pci-dma.o pci-nommu.o alternative.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_X86_MCE) += mce.o +obj-$(CONFIG_X86_MCE) += mce.o therm_throt.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ @@ -45,6 +45,7 @@ obj-y += intel_cacheinfo.o CFLAGS_vsyscall.o := $(PROFILING) -g0 +therm_throt-y += ../../i386/kernel/cpu/mcheck/therm_throt.o bootflag-y += ../../i386/kernel/bootflag.o cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/kernel/topology.o @@ -54,4 +55,3 @@ quirks-y += ../../i386/kernel/quirks.o i8237-y += ../../i386/kernel/i8237.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o alternative-y += ../../i386/kernel/alternative.o - diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 4e017fb..6314389 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -274,6 +274,33 @@ void do_machine_check(struct pt_regs * r atomic_dec(&mce_entry); } +#ifdef CONFIG_X86_MCE_INTEL +/*** + * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog + * @cpu: The CPU on which the event occured. + * @status: Event status information + * + * This function should be called by the thermal interrupt after the + * event has been processed and the decision was made to log the event + * further. + * + * The status parameter will be saved to the 'status' field of 'struct mce' + * and historically has been the register value of the + * MSR_IA32_THERMAL_STATUS (Intel) msr. + */ +void mce_log_therm_throt_event(unsigned int cpu, __u64 status) +{ + struct mce m; + + memset(&m, 0, sizeof(m)); + m.cpu = cpu; + m.bank = MCE_THERMAL_BANK; + m.status = status; + rdtscll(m.tsc); + mce_log(&m); +} +#endif /* CONFIG_X86_MCE_INTEL */ + /* * Periodic polling timer for "silent" machine check errors. */ diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c index 8f533d2..dec1121 100644 --- a/arch/x86_64/kernel/mce_intel.c +++ b/arch/x86_64/kernel/mce_intel.c @@ -11,36 +11,21 @@ #include <asm/msr.h> #include <asm/mce.h> #include <asm/hw_irq.h> #include <asm/idle.h> - -static DEFINE_PER_CPU(unsigned long, next_check); +#include <asm/therm_throt.h> asmlinkage void smp_thermal_interrupt(void) { - struct mce m; + __u64 msr_val; ack_APIC_irq(); exit_idle(); irq_enter(); - if (time_before(jiffies, __get_cpu_var(next_check))) - goto done; - - __get_cpu_var(next_check) = jiffies + HZ*300; - memset(&m, 0, sizeof(m)); - m.cpu = smp_processor_id(); - m.bank = MCE_THERMAL_BANK; - rdtscll(m.tsc); - rdmsrl(MSR_IA32_THERM_STATUS, m.status); - if (m.status & 0x1) { - printk(KERN_EMERG - "CPU%d: Temperature above threshold, cpu clock throttled\n", m.cpu); - add_taint(TAINT_MACHINE_CHECK); - } else { - printk(KERN_EMERG "CPU%d: Temperature/speed normal\n", m.cpu); - } - mce_log(&m); -done: + rdmsrl(MSR_IA32_THERM_STATUS, msr_val); + if (therm_throt_process(msr_val & 1)) + mce_log_therm_throt_event(smp_processor_id(), msr_val); + irq_exit(); } diff --git a/include/asm-i386/therm_throt.h b/include/asm-i386/therm_throt.h new file mode 100644 index 0000000..3c9c22c --- /dev/null +++ b/include/asm-i386/therm_throt.h @@ -0,0 +1,6 @@ +#ifndef __ASM_I386_THERM_THROT_H__ +#define __ASM_I386_THERM_THROT_H__ 1 + +int therm_throt_process(int curr); + +#endif /* __ASM_I386_THERM_THROT_H__ */ diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h index d13687d..5a0def5 100644 --- a/include/asm-x86_64/mce.h +++ b/include/asm-x86_64/mce.h @@ -99,6 +99,10 @@ static inline void mce_amd_feature_init( } #endif +#ifdef CONFIG_X86_MCE_INTEL +void mce_log_therm_throt_event(unsigned int cpu, __u64 status); +#endif + extern atomic_t mce_entry; #endif diff --git a/include/asm-x86_64/therm_throt.h b/include/asm-x86_64/therm_throt.h new file mode 100644 index 0000000..5aac059 --- /dev/null +++ b/include/asm-x86_64/therm_throt.h @@ -0,0 +1 @@ +#include <asm-i386/therm_throt.h> -- 1.4.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] jiffies: Add 64bit jiffies compares (for use with get_jiffies_64) 2006-09-22 0:48 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Dmitriy Zavin @ 2006-09-22 0:48 ` Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 3/4] therm_throt: Make the jiffies compares use the 64bit safe macros Dmitriy Zavin 2006-09-22 5:50 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Andi Kleen 1 sibling, 1 reply; 8+ messages in thread From: Dmitriy Zavin @ 2006-09-22 0:48 UTC (permalink / raw) To: linux-kernel; +Cc: ak, akpm The current time_before/time_after macros will fail typechecks when passed u64 values (as returned by get_jiffies_64()). On 64bit systems, this will just result in a warning about mismatching types without explicit casts, but since unsigned long and u64 (unsigned long long) are of same size, it will still work. On 32bit systems, a long is 32bits, so the value from get_jiffies_64() will be truncated by the cast and thus lose all the precision gained by 64bit jiffies. Signed-off-by: Dmitriy Zavin <dmitriyz@google.com> --- include/linux/jiffies.h | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 329ebcf..c8d5f20 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -115,6 +115,21 @@ #define time_after_eq(a,b) \ ((long)(a) - (long)(b) >= 0)) #define time_before_eq(a,b) time_after_eq(b,a) +/* Same as above, but does so with platform independent 64bit types. + * These must be used when utilizing jiffies_64 (i.e. return value of + * get_jiffies_64() */ +#define time_after64(a,b) \ + (typecheck(__u64, a) && \ + typecheck(__u64, b) && \ + ((__s64)(b) - (__s64)(a) < 0)) +#define time_before64(a,b) time_after64(b,a) + +#define time_after_eq64(a,b) \ + (typecheck(__u64, a) && \ + typecheck(__u64, b) && \ + ((__s64)(a) - (__s64)(b) >= 0)) +#define time_before_eq64(a,b) time_after_eq64(b,a) + /* * Have the 32 bit jiffies value wrap 5 minutes after boot * so jiffies wrap bugs show up earlier. -- 1.4.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] therm_throt: Make the jiffies compares use the 64bit safe macros. 2006-09-22 0:48 ` [PATCH 2/4] jiffies: Add 64bit jiffies compares (for use with get_jiffies_64) Dmitriy Zavin @ 2006-09-22 0:48 ` Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 4/4] therm_throt: Add a cumulative thermal throttle event counter Dmitriy Zavin 0 siblings, 1 reply; 8+ messages in thread From: Dmitriy Zavin @ 2006-09-22 0:48 UTC (permalink / raw) To: linux-kernel; +Cc: ak, akpm Signed-off-by: Dmitriy Zavin <dmitriyz@google.com> --- arch/i386/kernel/cpu/mcheck/therm_throt.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c index 85eba00..101f7ac 100644 --- a/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -18,7 +18,7 @@ #include <asm/therm_throt.h> /* How long to wait between reporting thermal events */ #define CHECK_INTERVAL (300 * HZ) -static DEFINE_PER_CPU(unsigned long, next_check); +static DEFINE_PER_CPU(__u64, next_check); /*** * therm_throt_process - Process thermal throttling event @@ -39,11 +39,12 @@ static DEFINE_PER_CPU(unsigned long, nex int therm_throt_process(int curr) { unsigned int cpu = smp_processor_id(); + __u64 tmp_jiffs = get_jiffies_64(); - if (time_before(jiffies, __get_cpu_var(next_check))) + if (time_before64(tmp_jiffs, __get_cpu_var(next_check))) return 0; - __get_cpu_var(next_check) = jiffies + CHECK_INTERVAL; + __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL; /* if we just entered the thermal event */ if (curr) { -- 1.4.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] therm_throt: Add a cumulative thermal throttle event counter. 2006-09-22 0:48 ` [PATCH 3/4] therm_throt: Make the jiffies compares use the 64bit safe macros Dmitriy Zavin @ 2006-09-22 0:48 ` Dmitriy Zavin 2006-09-22 5:51 ` Andi Kleen 0 siblings, 1 reply; 8+ messages in thread From: Dmitriy Zavin @ 2006-09-22 0:48 UTC (permalink / raw) To: linux-kernel; +Cc: ak, akpm The counter is exported to /sys that keeps track of the number of thermal events, such that the user knows how bad the thermal problem might be (since the logging to syslog and mcelog is rate limited). Signed-off-by: Dmitriy Zavin <dmitriyz@google.com> --- arch/i386/kernel/cpu/mcheck/p4.c | 3 + arch/i386/kernel/cpu/mcheck/therm_throt.c | 124 ++++++++++++++++++++++++++++- arch/x86_64/kernel/mce_intel.c | 3 + include/asm-i386/therm_throt.h | 3 + 4 files changed, 127 insertions(+), 6 deletions(-) diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index d83a669..504434a 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -115,6 +115,9 @@ static void intel_init_thermal(struct cp l = apic_read (APIC_LVTTHMR); apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED); printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); + + /* enable thermal throttle processing */ + atomic_set(&therm_throt_en, 1); return; } #endif /* CONFIG_X86_MCE_P4THERMAL */ diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c index 101f7ac..227c695 100644 --- a/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -1,15 +1,22 @@ /* * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c * - * Thermal throttle event support code. + * Thermal throttle event support code (such as syslog messaging and rate + * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c). + * This allows consistent reporting of CPU thermal throttle events. + * + * Maintains a counter in /sys that keeps track of the number of thermal + * events, such that the user knows how bad the thermal problem might be + * (since the logging to syslog and mcelog is rate limited). * * Author: Dmitriy Zavin (dmitriyz@google.com) * * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c. - * + * Inspired by Ross Biro's and Al Borchers' counter code. */ #include <linux/percpu.h> +#include <linux/sysdev.h> #include <linux/cpu.h> #include <asm/cpu.h> #include <linux/notifier.h> @@ -18,15 +25,53 @@ #include <asm/therm_throt.h> /* How long to wait between reporting thermal events */ #define CHECK_INTERVAL (300 * HZ) -static DEFINE_PER_CPU(__u64, next_check); +static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES; +static DEFINE_PER_CPU(unsigned long, thermal_throttle_count); +atomic_t therm_throt_en = ATOMIC_INIT(0); + +#ifdef CONFIG_SYSFS +#define define_therm_throt_sysdev_one_ro(_name) \ + static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) + +#define define_therm_throt_sysdev_show_func(name) \ +static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ + char *buf) \ +{ \ + unsigned int cpu = dev->id; \ + ssize_t ret; \ + \ + preempt_disable(); /* CPU hotplug */ \ + if (cpu_online(cpu)) \ + ret = sprintf(buf, "%lu\n", \ + per_cpu(thermal_throttle_##name, cpu)); \ + else \ + ret = 0; \ + preempt_enable(); \ + \ + return ret; \ +} + +define_therm_throt_sysdev_show_func(count); +define_therm_throt_sysdev_one_ro(count); + +static struct attribute *thermal_throttle_attrs[] = { + &attr_count.attr, + NULL +}; + +static struct attribute_group thermal_throttle_attr_group = { + .attrs = thermal_throttle_attrs, + .name = "thermal_throttle" +}; +#endif /* CONFIG_SYSFS */ /*** - * therm_throt_process - Process thermal throttling event + * therm_throt_process - Process thermal throttling event from interrupt * @curr: Whether the condition is current or not (boolean), since the * thermal interrupt normally gets called both when the thermal * event begins and once the event has ended. * - * This function is normally called by the thermal interrupt after the + * This function is called by the thermal interrupt after the * IRQ has been acknowledged. * * It will take care of rate limiting and printing messages to the syslog. @@ -41,6 +86,9 @@ int therm_throt_process(int curr) unsigned int cpu = smp_processor_id(); __u64 tmp_jiffs = get_jiffies_64(); + if (curr) + __get_cpu_var(thermal_throttle_count)++; + if (time_before64(tmp_jiffs, __get_cpu_var(next_check))) return 0; @@ -49,7 +97,9 @@ int therm_throt_process(int curr) /* if we just entered the thermal event */ if (curr) { printk(KERN_CRIT "CPU%d: Temperature above threshold, " - "cpu clock throttled\n", cpu); + "cpu clock throttled (total events = %lu)\n", cpu, + __get_cpu_var(thermal_throttle_count)); + add_taint(TAINT_MACHINE_CHECK); } else { printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu); @@ -57,3 +107,65 @@ int therm_throt_process(int curr) return 1; } + +#ifdef CONFIG_SYSFS +/* Add/Remove thermal_throttle interface for CPU device */ +static __cpuinit int thermal_throttle_add_dev(struct sys_device * sys_dev) +{ + sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group); + return 0; +} + +#ifdef CONFIG_HOTPLUG_CPU +static __cpuinit int thermal_throttle_remove_dev(struct sys_device * sys_dev) +{ + sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group); + return 0; +} + +/* Get notified when a cpu comes on/off. Be hotplug friendly. */ +static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_ONLINE: + thermal_throttle_add_dev(sys_dev); + break; + case CPU_DEAD: + thermal_throttle_remove_dev(sys_dev); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block thermal_throttle_cpu_notifier = +{ + .notifier_call = thermal_throttle_cpu_callback, +}; +#endif /* CONFIG_HOTPLUG_CPU */ + +static __init int thermal_throttle_init_device(void) +{ + unsigned int cpu = 0; + + if (!atomic_read(&therm_throt_en)) + return 0; + + preempt_disable(); /* CPU hotplug */ + for_each_online_cpu(cpu) { + /* connect live CPUs to sysfs */ + thermal_throttle_add_dev(get_cpu_sysdev(cpu)); + } + preempt_enable(); + + register_hotcpu_notifier(&thermal_throttle_cpu_notifier); + return 0; +} + +device_initcall(thermal_throttle_init_device); +#endif /* CONFIG_SYSFS */ diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c index dec1121..6551505 100644 --- a/arch/x86_64/kernel/mce_intel.c +++ b/arch/x86_64/kernel/mce_intel.c @@ -77,6 +77,9 @@ static void __cpuinit intel_init_thermal apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", cpu, tm2 ? "TM2" : "TM1"); + + /* enable thermal throttle processing */ + atomic_set(&therm_throt_en, 1); return; } diff --git a/include/asm-i386/therm_throt.h b/include/asm-i386/therm_throt.h index 3c9c22c..399bf60 100644 --- a/include/asm-i386/therm_throt.h +++ b/include/asm-i386/therm_throt.h @@ -1,6 +1,9 @@ #ifndef __ASM_I386_THERM_THROT_H__ #define __ASM_I386_THERM_THROT_H__ 1 +#include <asm/atomic.h> + +extern atomic_t therm_throt_en; int therm_throt_process(int curr); #endif /* __ASM_I386_THERM_THROT_H__ */ -- 1.4.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] therm_throt: Add a cumulative thermal throttle event counter. 2006-09-22 0:48 ` [PATCH 4/4] therm_throt: Add a cumulative thermal throttle event counter Dmitriy Zavin @ 2006-09-22 5:51 ` Andi Kleen 0 siblings, 0 replies; 8+ messages in thread From: Andi Kleen @ 2006-09-22 5:51 UTC (permalink / raw) To: Dmitriy Zavin; +Cc: linux-kernel, akpm > + preempt_disable(); /* CPU hotplug */ > + for_each_online_cpu(cpu) { > + /* connect live CPUs to sysfs */ > + thermal_throttle_add_dev(get_cpu_sysdev(cpu)); > + } > + preempt_enable(); There was still one problem in there: sysfs_create_group can sleep and that's not ok with preemption disabled. I changed it to register the notifier first and do the necessary locking in there using a private lock (that the new akpm-recommended(tm) way to do this) -Andi ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing 2006-09-22 0:48 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 2/4] jiffies: Add 64bit jiffies compares (for use with get_jiffies_64) Dmitriy Zavin @ 2006-09-22 5:50 ` Andi Kleen 1 sibling, 0 replies; 8+ messages in thread From: Andi Kleen @ 2006-09-22 5:50 UTC (permalink / raw) To: Dmitriy Zavin; +Cc: linux-kernel, akpm > +#ifdef CONFIG_X86_MCE_INTEL > +void mce_log_therm_throt_event(unsigned int cpu, __u64 status); > +#endif I removed that ifdef. -Andi ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events. 2006-09-22 0:48 [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Dmitriy Zavin @ 2006-09-22 5:49 ` Andi Kleen 1 sibling, 0 replies; 8+ messages in thread From: Andi Kleen @ 2006-09-22 5:49 UTC (permalink / raw) To: Dmitriy Zavin; +Cc: linux-kernel, akpm On Friday 22 September 2006 02:48, Dmitriy Zavin wrote: > Differences from last cut: > - No more #ifdef CONFIG_X86_64.. sorry Andi :). x86_64 specific > code is in arch/x86_64/kernel/mce.c > - Commented the need/use for time_before64/time_after64. > (I addressed Andi Kleen's concern about these macros in a > followup from last attempt, but never got a response.) > - More comments in therm_throt.c and individual patch descriptions Added thanks with minor changes. -Andi ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-09-22 5:51 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-09-22 0:48 [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 2/4] jiffies: Add 64bit jiffies compares (for use with get_jiffies_64) Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 3/4] therm_throt: Make the jiffies compares use the 64bit safe macros Dmitriy Zavin 2006-09-22 0:48 ` [PATCH 4/4] therm_throt: Add a cumulative thermal throttle event counter Dmitriy Zavin 2006-09-22 5:51 ` Andi Kleen 2006-09-22 5:50 ` [PATCH 1/4] x86_64/i386 therm mce: Refactor thermal throttle processing Andi Kleen 2006-09-22 5:49 ` [PATCH 0/4 v2] therm_throt: Refactor thermal throttle processing, and keep a total count of events Andi Kleen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox