[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: sync thermal monitor LVT handling with Linux



# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxxxx>
# Date 1308165913 -3600
# Node ID e462d2e76734c997a988bf7b888755133919ea60
# Parent  644838dc1322163a49701ddc79e251260d3b39e8
x86: sync thermal monitor LVT handling with Linux

As of 2.6.33, Linux checks that the thermal monitor LVT isn't set to
SMI delivery mode on just the value read on the boot CPU. As of 2.6.39
it additionally avoids writing back the saved value when its delivery
mode is FIXED (as this can cause APIC errors).

Changes done here that aren't in Linux are
- write back the boot CPU value also if delivery mode is FIXED, but
  there is also a valid vector
- print the messages when bailing out only once (on the boot CPU)
- when doing the final (enabling) write to the LVT, don't re-read the
  old value from the APIC, as we have it in a local variable already

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---


diff -r 644838dc1322 -r e462d2e76734 xen/arch/x86/cpu/mcheck/mce_intel.c
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c       Wed Jun 15 20:24:41 2011 +0100
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c       Wed Jun 15 20:25:13 2011 +0100
@@ -83,6 +83,29 @@
     set_irq_regs(old_regs);
 }
 
+/* Thermal monitoring depends on APIC, ACPI and clock modulation */
+static int intel_thermal_supported(struct cpuinfo_x86 *c)
+{
+    if (!cpu_has_apic)
+        return 0;
+    if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
+        return 0;
+    return 1;
+}
+
+static u32 __read_mostly lvtthmr_init;
+
+static void __init mcheck_intel_therm_init(void)
+{
+    /*
+     * This function is only called on boot CPU. Save the init thermal
+     * LVT value on BSP and use that value to restore APs' thermal LVT
+     * entry BIOS programmed later
+     */
+    if (intel_thermal_supported(&boot_cpu_data))
+        lvtthmr_init = apic_read(APIC_LVTTHMR);
+}
+
 /* P4/Xeon Thermal regulation detect and init */
 static void intel_init_thermal(struct cpuinfo_x86 *c)
 {
@@ -91,12 +114,7 @@
     int tm2 = 0;
     unsigned int cpu = smp_processor_id();
 
-    /* Thermal monitoring */
-    if (!cpu_has(c, X86_FEATURE_ACPI))
-        return; /* -ENODEV */
-
-    /* Clock modulation */
-    if (!cpu_has(c, X86_FEATURE_ACC))
+    if (!intel_thermal_supported(c))
         return; /* -ENODEV */
 
     /* first check if its enabled already, in which case there might
@@ -104,9 +122,25 @@
      * since it might be delivered via SMI already -zwanem.
      */
     rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
-    val = apic_read(APIC_LVTTHMR);
-    if ((msr_content & (1ULL<<3)) && (val & APIC_DM_SMI)) {
-        printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n",cpu);
+    val = lvtthmr_init;
+    /*
+     * The initial value of thermal LVT entries on all APs always reads
+     * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
+     * sequence to them and LVT registers are reset to 0s except for
+     * the mask bits which are set to 1s when APs receive INIT IPI.
+     * If BIOS takes over the thermal interrupt and sets its interrupt
+     * delivery mode to SMI (not fixed), it restores the value that the
+     * BIOS has programmed on AP based on BSP's info we saved (since BIOS
+     * is required to set the same value for all threads/cores).
+     */
+    if ((val & APIC_MODE_MASK) != APIC_DM_FIXED
+        || (val & APIC_VECTOR_MASK) > 0xf)
+        apic_write(APIC_LVTTHMR, val);
+
+    if ((msr_content & (1ULL<<3))
+        && (val & APIC_MODE_MASK) == APIC_DM_SMI) {
+        if (c == &boot_cpu_data)
+            printk(KERN_DEBUG "Thermal monitoring handled by SMI\n");
         return; /* -EBUSY */
     }
 
@@ -115,8 +149,9 @@
 
     /* check whether a vector already exists, temporarily masked? */
     if (val & APIC_VECTOR_MASK) {
-        printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already 
installed\n",
-                 cpu, (val & APIC_VECTOR_MASK));
+        if (c == &boot_cpu_data)
+            printk(KERN_DEBUG "Thermal LVT vector (%#x) already installed\n",
+                   val & APIC_VECTOR_MASK);
         return; /* -EBUSY */
     }
 
@@ -134,7 +169,7 @@
     rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
     wrmsrl(MSR_IA32_MISC_ENABLE, msr_content | (1ULL<<3));
 
-    apic_write_around(APIC_LVTTHMR, apic_read(APIC_LVTTHMR) & 
~APIC_LVT_MASKED);
+    apic_write_around(APIC_LVTTHMR, val & ~APIC_LVT_MASKED);
     if (opt_cpu_info)
         printk(KERN_INFO "CPU%u: Thermal monitoring enabled (%s)\n",
                 cpu, tm2 ? "TM2" : "TM1");
@@ -1318,6 +1353,7 @@
         if ( cpu_mcabank_alloc(0) )
             BUG();
         register_cpu_notifier(&cpu_nfb);
+        mcheck_intel_therm_init();
     }
 
     intel_init_mca(c);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.