WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] x86: sync thermal monitor LVT handling with Linux

To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] x86: sync thermal monitor LVT handling with Linux
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Wed, 15 Jun 2011 16:37:43 +0100
Delivery-date: Wed, 15 Jun 2011 08:38:44 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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>

--- a/xen/arch/x86/cpu/mcheck/mce_intel.c
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c
@@ -72,6 +72,29 @@ fastcall void smp_thermal_interrupt(stru
     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)
 {
@@ -80,12 +103,7 @@ static void intel_init_thermal(struct cp
     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
@@ -93,9 +111,25 @@ static void intel_init_thermal(struct cp
      * 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 */
     }
 
@@ -104,8 +138,9 @@ static void intel_init_thermal(struct cp
 
     /* 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 */
     }
 
@@ -123,7 +158,7 @@ static void intel_init_thermal(struct cp
     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");
@@ -1305,6 +1340,7 @@ enum mcheck_type intel_mcheck_init(struc
         if ( cpu_mcabank_alloc(0) )
             BUG();
         register_cpu_notifier(&cpu_nfb);
+        mcheck_intel_therm_init();
     }
 
     intel_init_mca(c);


Attachment: x86-apic-lvtthmr-bios.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] x86: sync thermal monitor LVT handling with Linux, Jan Beulich <=