Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4159

kernel-2.6.18-194.11.1.el5.src.rpm

From: Aristeu Rozanski <aris@redhat.com>
Date: Wed, 20 Aug 2008 13:16:56 -0400
Subject: [x86_64] nmi: use perfctr functions for probing
Message-id: 20080820171648.895079000@redhat.com
O-Subject: [RHEL5.3 PATCH 10/25] nmi: use perfctr functions for probing
Bugzilla: 447618

https://bugzilla.redhat.com/show_bug.cgi?id=447618

This patch changes lapic_watchdog_init() and creates lapic_watchdog_probe()
to allow enabling nmi watchdog as default.

upstream: not upstream, only interesting for RHEL-5 which ships NMI enabled by
          default

diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 5c13e7f..05db057 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -51,67 +51,14 @@ static DEFINE_PER_CPU(short, wd_enabled);
 
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
-
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
-
-#define K7_EVNTSEL_ENABLE	(1 << 22)
-#define K7_EVNTSEL_INT		(1 << 20)
-#define K7_EVNTSEL_OS		(1 << 17)
-#define K7_EVNTSEL_USR		(1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING	0x76
-#define K7_NMI_EVENT		K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-
-#define ARCH_PERFMON_NMI_EVENT_SEL	ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK	ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
-
-#define MSR_P4_MISC_ENABLE	0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL	(1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL	(1<<12)
-#define MSR_P4_PERFCTR0		0x300
-#define MSR_P4_CCCR0		0x360
-#define P4_ESCR_EVENT_SELECT(N)	((N)<<25)
-#define P4_ESCR_OS		(1<<3)
-#define P4_ESCR_USR		(1<<2)
-#define P4_CCCR_OVF_PMI0	(1<<26)
-#define P4_CCCR_OVF_PMI1	(1<<27)
-#define P4_CCCR_THRESHOLD(N)	((N)<<20)
-#define P4_CCCR_COMPLEMENT	(1<<19)
-#define P4_CCCR_COMPARE		(1<<18)
-#define P4_CCCR_REQUIRED	(3<<16)
-#define P4_CCCR_ESCR_SELECT(N)	((N)<<13)
-#define P4_CCCR_ENABLE		(1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
-   CRU_ESCR0 (with any non-null event selector) through a complemented
-   max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0	0x30C
-#define P4_NMI_CRU_ESCR0	(P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0	\
-	(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
-	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
-
-static __cpuinit inline int nmi_known_cpu(void)
-{
-	switch (boot_cpu_data.x86_vendor) {
-	case X86_VENDOR_AMD:
-		return boot_cpu_data.x86 == 15 || boot_cpu_data.x86 == 16;
-	case X86_VENDOR_INTEL:
-		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
-			return 1;
-		else
-			return (boot_cpu_data.x86 == 15);
-	}
-	return 0;
-}
 
 /* Run after command line and cpu_init init, but before all other checks */
 void __cpuinit nmi_watchdog_default(void)
 {
 	if (nmi_watchdog != NMI_DEFAULT)
 		return;
-	if (nmi_known_cpu())
+	/* if not specified, probe it */
+	if (!lapic_watchdog_probe())
 		nmi_watchdog = NMI_LOCAL_APIC;
 	else
 		nmi_watchdog = NMI_IO_APIC;
@@ -192,7 +139,6 @@ int __init check_nmi_watchdog (void)
 			       cpu_pda(cpu)->__nmi_count);
 			if (atomic_dec_and_test(&nmi_watchdog_active))
 				nmi_active = 0;
-			nmi_perfctr_msr = 0;
 			per_cpu(wd_enabled, cpu) = 0;
 			kfree(counts);
 			return -1;
@@ -209,13 +155,8 @@ int __init check_nmi_watchdog (void)
 
 	/* now that we know it works we can reduce NMI frequency to
 	   something more reasonable; makes a difference in some configs */
-	if (nmi_watchdog == NMI_LOCAL_APIC) {
-
-		nmi_hz = 1;
-		if (nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-			nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-		}
-	}
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		nmi_hz = lapic_adjust_nmi_hz(1);
 
 	kfree(counts);
 	return 0;
diff --git a/arch/x86_64/kernel/perfctr-watchdog.c b/arch/x86_64/kernel/perfctr-watchdog.c
index 984f2fb..f68e71c 100644
--- a/arch/x86_64/kernel/perfctr-watchdog.c
+++ b/arch/x86_64/kernel/perfctr-watchdog.c
@@ -668,7 +668,7 @@ static void probe_nmi_watchdog(void)
 
 /* Interface to nmi.c */
 
-int lapic_watchdog_init(unsigned nmi_hz)
+int lapic_watchdog_probe(void)
 {
 	if (!wd_ops) {
 		probe_nmi_watchdog();
@@ -681,6 +681,13 @@ int lapic_watchdog_init(unsigned nmi_hz)
 			return -1;
 		}
 	}
+	return 0;
+}
+
+int lapic_watchdog_init(unsigned nmi_hz)
+{
+	if (lapic_watchdog_probe())
+		return -1;
 
 	if (!(wd_ops->setup(nmi_hz))) {
 		printk(KERN_ERR "Cannot setup NMI watchdog on CPU %d\n",
diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h
index 86b8bcf..7d82b1a 100644
--- a/include/asm-x86_64/nmi.h
+++ b/include/asm-x86_64/nmi.h
@@ -71,6 +71,7 @@ extern int reserve_evntsel_nmi(unsigned int);
 extern void release_evntsel_nmi(unsigned int);
 
 void lapic_watchdog_stop(void);
+int lapic_watchdog_probe(void);
 int lapic_watchdog_init(unsigned nmi_hz);
 int lapic_wd_event(unsigned nmi_hz);
 unsigned lapic_adjust_nmi_hz(unsigned hz);