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] kexec: disable iommu and x2apic before jumping into

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] kexec: disable iommu and x2apic before jumping into the kdump kernel
From: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Date: Fri, 13 May 2011 13:47:57 +0100
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Delivery-date: Fri, 13 May 2011 05:49:52 -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
User-agent: Mercurial-patchbomb/1.4.3
This is a massive hack but is better than the code currently in place.
Some functions have been duped into a crash_* version to separate them
from the regular shutdown path, where disabling these subsystems is
irrelevant.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>

diff -r 0c446850d85e -r efa733ebd00d xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Wed May 11 12:58:04 2011 +0100
+++ b/xen/arch/x86/apic.c       Fri May 13 13:45:05 2011 +0100
@@ -344,6 +344,42 @@
     }
 }
 
+/* Customised version of disable_local_APIC which is only called on the kexec 
crash path.
+ * It is a brutal hack and only here untill the APIC code is overhauled.  We 
NEED to swtich
+ * out of x2apic mode whatever the case as the kdump kernel cant cope due to 
the MMIO <-> MSR
+ * swap invovled with x2apic mode.
+ */
+void crash_disable_local_APIC(void)
+{
+    uint64_t msr_content;
+    clear_local_APIC();
+
+    apic_write_around(APIC_SPIV,
+        apic_read(APIC_SPIV) & ~APIC_SPIV_APIC_ENABLED);
+
+    rdmsrl(MSR_IA32_APICBASE, msr_content);
+
+    /* This is the only way to exit x2apic mode.  Trying to disable x2apic 
mode while staying
+     * xapic mode will result in a protection fault which leads to a general 
protection fault
+     * as this is on the fault handler codepath.
+     */
+    msr_content &= ~(MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD);
+    wrmsrl(MSR_IA32_APICBASE, msr_content);
+
+    /* In most cases, we should leave the lapic in xapic mode as this is the 
default state on
+     * CPU reset.  However, some bioses specifically disable xapic mode for 
hilarity sake so
+     * we should follow suit so the kdump kernel does not get confused about 
mismatching ACPI
+     * tables.
+     */
+    if ( ! enabled_via_apicbase) {
+           /* If we did not manually enable xapic mode, I.E. the bios left it 
enabled,
+            * lets follow suit and leave it enabled for the kdump kernel.
+            */
+        wrmsrl(MSR_IA32_APICBASE, msr_content | MSR_IA32_APICBASE_ENABLE);
+    }
+}
+
+
 /*
  * This is to verify that we're looking at a real local APIC.
  * Check these against your board if the CPUs aren't getting
diff -r 0c446850d85e -r efa733ebd00d xen/arch/x86/crash.c
--- a/xen/arch/x86/crash.c      Wed May 11 12:58:04 2011 +0100
+++ b/xen/arch/x86/crash.c      Fri May 13 13:45:05 2011 +0100
@@ -27,6 +27,8 @@
 #include <asm/hvm/support.h>
 #include <asm/apic.h>
 #include <asm/io_apic.h>
+#include <xen/iommu.h>
+#include <asm/hvm/iommu.h>
 
 static atomic_t waiting_for_crash_ipi;
 static unsigned int crashing_cpu;
@@ -43,7 +45,12 @@
 
     kexec_crash_save_cpu();
 
-    __stop_this_cpu();
+    crash_disable_local_APIC();
+    hvm_cpu_down();
+    /* Clear FPU, zapping any pending exceptions. Needed for warm reset with
+     * some BIOSes.*/
+    clts();
+    asm volatile ( "fninit" );
 
     atomic_dec(&waiting_for_crash_ipi);
 
@@ -77,7 +84,15 @@
         msecs--;
     }
 
-    __stop_this_cpu();
+    crash_disable_local_APIC();
+    hvm_cpu_down();
+    /* Clear FPU, zapping any pending exceptions. Needed for warm reset with
+     * some BIOSes.*/
+    clts();
+    asm volatile ( "fninit" );
+
+    x2apic_enabled = 0;
+
     disable_IO_APIC();
 
     local_irq_enable();
@@ -86,9 +101,24 @@
 void machine_crash_shutdown(void)
 {
     crash_xen_info_t *info;
+    const struct iommu_ops * ops;
 
     nmi_shootdown_cpus();
 
+    local_irq_disable();
+
+    /* Yes i know this is hacky but it is the easiest solution.  I should add 
an iommu_ops
+     * function called crash() or so which just disables the iommu 'fun' 
without saving state
+     */
+    ops = iommu_get_ops();
+    ops->suspend();
+
+    /* Yes i know this is from driver/passthrough/vtd/ but it appears to be 
architecture
+     * independant, and also bears little/no relation to x2apic.  Needs 
cleaning up
+     */
+    iommu_disable_x2apic_IR();
+    local_irq_enable();
+
     info = kexec_crash_save_info();
     info->xen_phys_start = xen_phys_start;
     info->dom0_pfn_to_mfn_frame_list_list =
diff -r 0c446850d85e -r efa733ebd00d xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c       Wed May 11 12:58:04 2011 +0100
+++ b/xen/arch/x86/hpet.c       Fri May 13 13:45:05 2011 +0100
@@ -670,6 +670,34 @@
     smp_send_event_check_mask(&cpu_online_map);
 }
 
+void crash_hpet_disable_legacy_broadcast(void)
+{
+    u32 cfg;
+
+    if ( !hpet_events || !(hpet_events->flags & HPET_EVT_LEGACY) )
+        return;
+
+    /* By this point in the crash handler, we are the only CPU still going,
+     * so the lock is irrelevant
+     */
+    /* spin_lock_irqsave(&hpet_events->lock, flags); */
+
+    hpet_events->flags |= HPET_EVT_DISABLE;
+
+    /* disable HPET T0 */
+    cfg = hpet_read32(HPET_Tn_CFG(0));
+    cfg &= ~HPET_TN_ENABLE;
+    hpet_write32(cfg, HPET_Tn_CFG(0));
+
+    /* Stop HPET legacy interrupts */
+    cfg = hpet_read32(HPET_CFG);
+    cfg &= ~HPET_CFG_LEGACY;
+    hpet_write32(cfg, HPET_CFG);
+
+    /* spin_unlock_irqrestore(&hpet_events->lock, flags); */
+}
+
+
 void hpet_broadcast_enter(void)
 {
     unsigned int cpu = smp_processor_id();
diff -r 0c446850d85e -r efa733ebd00d xen/arch/x86/machine_kexec.c
--- a/xen/arch/x86/machine_kexec.c      Wed May 11 12:58:04 2011 +0100
+++ b/xen/arch/x86/machine_kexec.c      Fri May 13 13:45:05 2011 +0100
@@ -97,7 +97,7 @@
     };
 
     if ( hpet_broadcast_is_available() )
-        hpet_disable_legacy_broadcast();
+        crash_hpet_disable_legacy_broadcast();
 
     /*
      * compat_machine_kexec() returns to idle pagetables, which requires us
diff -r 0c446850d85e -r efa733ebd00d xen/include/asm-x86/apic.h
--- a/xen/include/asm-x86/apic.h        Wed May 11 12:58:04 2011 +0100
+++ b/xen/include/asm-x86/apic.h        Fri May 13 13:45:05 2011 +0100
@@ -182,6 +182,7 @@
 extern void connect_bsp_APIC (void);
 extern void disconnect_bsp_APIC (int virt_wire_setup);
 extern void disable_local_APIC (void);
+extern void crash_disable_local_APIC (void);
 extern int verify_local_APIC (void);
 extern void cache_APIC_registers (void);
 extern void sync_Arb_IDs (void);
diff -r 0c446850d85e -r efa733ebd00d xen/include/asm-x86/hpet.h
--- a/xen/include/asm-x86/hpet.h        Wed May 11 12:58:04 2011 +0100
+++ b/xen/include/asm-x86/hpet.h        Fri May 13 13:45:05 2011 +0100
@@ -73,5 +73,6 @@
 void hpet_broadcast_exit(void);
 int hpet_broadcast_is_available(void);
 void hpet_disable_legacy_broadcast(void);
+void crash_hpet_disable_legacy_broadcast(void);
 
 #endif /* __X86_HPET_H__ */

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