]> xenbits.xensource.com Git - xen.git/commitdiff
kexec: Clean up shutdown logic. Reinstate ACPI DMAR during kexec.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 2 Aug 2010 16:18:37 +0000 (17:18 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 2 Aug 2010 16:18:37 +0000 (17:18 +0100)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen-unstable changeset:   21886:578ed14c3c67
xen-unstable date:        Thu Jul 29 10:31:21 2010 +0100

xen/arch/x86/crash.c
xen/arch/x86/machine_kexec.c
xen/arch/x86/smp.c
xen/arch/x86/tboot.c
xen/common/kexec.c
xen/drivers/acpi/tables.c
xen/drivers/passthrough/vtd/dmar.c
xen/include/asm-x86/smp.h

index 1c90b6eca2dc22e51c455848062f06997d27ee1e..a76f9aca2075c25093be31a27c28043cd125f47b 100644 (file)
@@ -25,7 +25,6 @@
 #include <public/xen.h>
 #include <asm/shared.h>
 #include <asm/hvm/support.h>
-#include <asm/hpet.h>
 
 static atomic_t waiting_for_crash_ipi;
 static unsigned int crashing_cpu;
@@ -41,9 +40,10 @@ static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
     local_irq_disable();
 
     kexec_crash_save_cpu();
-    disable_local_APIC();
+
+    __stop_this_cpu();
+
     atomic_dec(&waiting_for_crash_ipi);
-    hvm_cpu_down();
 
     for ( ; ; )
         halt();
@@ -55,7 +55,10 @@ static void nmi_shootdown_cpus(void)
 {
     unsigned long msecs;
 
+    local_irq_disable();
+
     crashing_cpu = smp_processor_id();
+    local_irq_count(crashing_cpu) = 0;
 
     atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
     /* Would it be better to replace the trap vector here? */
@@ -72,25 +75,18 @@ static void nmi_shootdown_cpus(void)
         msecs--;
     }
 
-    /* Leave the nmi callback set */
-    disable_local_APIC();
+    __stop_this_cpu();
+    disable_IO_APIC();
+
+    local_irq_enable();
 }
 
 void machine_crash_shutdown(void)
 {
     crash_xen_info_t *info;
 
-    local_irq_disable();
-
     nmi_shootdown_cpus();
 
-    if ( hpet_broadcast_is_available() )
-        hpet_disable_legacy_broadcast();
-
-    disable_IO_APIC();
-
-    hvm_cpu_down();
-
     info = kexec_crash_save_info();
     info->xen_phys_start = xen_phys_start;
     info->dom0_pfn_to_mfn_frame_list_list =
index f44aba2b5b6d8d7707db55c0faa197b8716307ef..d3f146854fab113207473573a850e79708871d16 100644 (file)
@@ -18,6 +18,7 @@
 #include <xen/domain_page.h>
 #include <asm/fixmap.h>
 #include <asm/hvm/hvm.h>
+#include <asm/hpet.h>
 
 typedef void (*relocate_new_kernel_t)(
                 unsigned long indirection_page,
@@ -76,38 +77,11 @@ void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
 {
 }
 
-static void __machine_reboot_kexec(void *data)
+void machine_reboot_kexec(xen_kexec_image_t *image)
 {
-    xen_kexec_image_t *image = (xen_kexec_image_t *)data;
-
-    watchdog_disable();
-    console_start_sync();
-
+    BUG_ON(smp_processor_id() != 0);
     smp_send_stop();
-
     machine_kexec(image);
-}
-
-void machine_reboot_kexec(xen_kexec_image_t *image)
-{
-    int reboot_cpu_id;
-
-    reboot_cpu_id = 0;
-
-    if ( !cpu_isset(reboot_cpu_id, cpu_online_map) )
-        reboot_cpu_id = smp_processor_id();
-
-    if ( reboot_cpu_id != smp_processor_id() )
-    {
-        on_selected_cpus(cpumask_of(reboot_cpu_id), __machine_reboot_kexec,
-                         image, 0);
-        for (;;)
-                ; /* nothing */
-    }
-    else
-    {
-        __machine_reboot_kexec(image);
-    }
     BUG();
 }
 
@@ -118,6 +92,9 @@ void machine_kexec(xen_kexec_image_t *image)
         .limit = LAST_RESERVED_GDT_BYTE
     };
 
+    if ( hpet_broadcast_is_available() )
+        hpet_disable_legacy_broadcast();
+
     /*
      * compat_machine_kexec() returns to idle pagetables, which requires us
      * to be running on a static GDT mapping (idle pagetables have no GDT
index 2a019239005840887031bc1872a329e7b92b73d1..a0f7d8e9475b62edd77aa0b346d99ec4f5c408ef 100644 (file)
@@ -326,7 +326,7 @@ int on_selected_cpus(
     return 0;
 }
 
-static void __stop_this_cpu(void)
+void __stop_this_cpu(void)
 {
     ASSERT(!local_irq_is_enabled());
 
index f5930401a2d5ed65c4832077a2ce4a3187d8d70e..4e86146f7da4eae47f7360d838ba8a91e3332f60 100644 (file)
@@ -482,7 +482,10 @@ int __init tboot_parse_dmar_table(acpi_table_handler dmar_handler)
     dmar_table = NULL;
     acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table);
     if ( dmar_table != NULL )
-        ((struct acpi_table_dmar *)dmar_table)->header.signature[0] = '\0';
+    {
+        dmar_table->signature[0] = 'X';
+        dmar_table->checksum -= 'X'-'D';
+    }
 
     return rc;
 }
index c8cf1ac33db68ecf1677191d168b17cef9f18cd2..da508800304ac054cf4771f35ee7dffa704c39b1 100644 (file)
@@ -6,7 +6,9 @@
  * - Magnus Damm <magnus@valinux.co.jp>
  */
 
+#include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/acpi.h>
 #include <xen/ctype.h>
 #include <xen/errno.h>
 #include <xen/guest_access.h>
@@ -107,6 +109,22 @@ crash_xen_info_t *kexec_crash_save_info(void)
     return out;
 }
 
+static int acpi_dmar_reinstate(struct acpi_table_header *table)
+{
+    table->signature[0] = 'D';
+    table->checksum += 'X'-'D';
+    return 0;
+}
+
+static void kexec_common_shutdown(void)
+{
+    watchdog_disable();
+    console_start_sync();
+    spin_debug_disable();
+    one_cpu_only();
+    acpi_table_parse(ACPI_SIG_DMAR, acpi_dmar_reinstate);
+}
+
 void kexec_crash(void)
 {
     int pos;
@@ -115,17 +133,25 @@ void kexec_crash(void)
     if ( !test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags) )
         return;
 
-    console_start_sync();
-
-    one_cpu_only();
+    kexec_common_shutdown();
     kexec_crash_save_cpu();
     machine_crash_shutdown();
-
     machine_kexec(&kexec_image[KEXEC_IMAGE_CRASH_BASE + pos]);
 
     BUG();
 }
 
+static long kexec_reboot(void *_image)
+{
+    xen_kexec_image_t *image = _image;
+
+    kexec_common_shutdown();
+    machine_reboot_kexec(image);
+
+    BUG();
+    return 0;
+}
+
 static void do_crashdump_trigger(unsigned char key)
 {
     printk("'%c' pressed -> triggering crashdump\n", key);
@@ -446,7 +472,7 @@ static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
 {
     xen_kexec_exec_t exec;
     xen_kexec_image_t *image;
-    int base, bit, pos;
+    int base, bit, pos, ret = -EINVAL;
 
     if ( unlikely(copy_from_guest(&exec, uarg, 1)) )
         return -EFAULT;
@@ -464,8 +490,7 @@ static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
     {
     case KEXEC_TYPE_DEFAULT:
         image = &kexec_image[base + pos];
-        one_cpu_only();
-        machine_reboot_kexec(image); /* Does not return */
+        ret = continue_hypercall_on_cpu(0, kexec_reboot, image);
         break;
     case KEXEC_TYPE_CRASH:
         kexec_crash(); /* Does not return */
index 252bf9887397b32f13879c90c72b180b50b8c61e..a25d9b2be18732131721e8f9ac12bbb38b391315 100644 (file)
@@ -41,7 +41,7 @@ mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
 static const char *__initdata
 mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
 
-static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
+static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES];
 
 static int acpi_apic_instance __initdata;
 
@@ -239,7 +239,7 @@ acpi_table_parse_madt(enum acpi_madt_type id,
  * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
  * run @handler on it.  Return 0 if table found, return on if not.
  */
-int __init acpi_table_parse(char *id, acpi_table_handler handler)
+int acpi_table_parse(char *id, acpi_table_handler handler)
 {
        struct acpi_table_header *table = NULL;
 
index 55c911cfe06226955f8d3e9a264b80bcb23e7ecb..f4078ff44b2647420562ea74d4d5f82162305922 100644 (file)
@@ -738,7 +738,8 @@ static int __init acpi_parse_dmar(struct acpi_table_header *table)
 
 out:
     /* Zap ACPI DMAR signature to prevent dom0 using vt-d HW. */
-    dmar->header.signature[0] = '\0';
+    dmar->header.signature[0] = 'X';
+    dmar->header.checksum -= 'X'-'D';
     return ret;
 }
 
index 6f5200dbedcee0e54e287d71cec5ffa5df8e85c9..a3c440daeb83b23c7d8407f2043c32709d235e60 100644 (file)
@@ -102,6 +102,9 @@ static __inline int logical_smp_processor_id(void)
 
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
+
+void __stop_this_cpu(void);
+
 #endif /* !__ASSEMBLY__ */
 
 #else /* CONFIG_SMP */