aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-08-02 17:18:37 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-08-02 17:18:37 +0100
commit0772f7b860224c19b1a59d471e9e88256e9ec92b (patch)
treee71cc0cef388ddee15e398e1de67aaecc108380e
parentffc1e7f1549a5715018579ef3c02b0c1a8da363f (diff)
downloadxen-0772f7b860224c19b1a59d471e9e88256e9ec92b.tar.gz
xen-0772f7b860224c19b1a59d471e9e88256e9ec92b.tar.bz2
xen-0772f7b860224c19b1a59d471e9e88256e9ec92b.zip
kexec: Clean up shutdown logic. Reinstate ACPI DMAR during kexec.
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
-rw-r--r--xen/arch/x86/crash.c24
-rw-r--r--xen/arch/x86/machine_kexec.c35
-rw-r--r--xen/arch/x86/smp.c2
-rw-r--r--xen/arch/x86/tboot.c5
-rw-r--r--xen/common/kexec.c39
-rw-r--r--xen/drivers/acpi/tables.c4
-rw-r--r--xen/drivers/passthrough/vtd/dmar.c3
-rw-r--r--xen/include/asm-x86/smp.h3
8 files changed, 60 insertions, 55 deletions
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index 1c90b6eca2..a76f9aca20 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -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 =
diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c
index f44aba2b5b..d3f146854f 100644
--- a/xen/arch/x86/machine_kexec.c
+++ b/xen/arch/x86/machine_kexec.c
@@ -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
diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
index 2a01923900..a0f7d8e947 100644
--- a/xen/arch/x86/smp.c
+++ b/xen/arch/x86/smp.c
@@ -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());
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
index f5930401a2..4e86146f7d 100644
--- a/xen/arch/x86/tboot.c
+++ b/xen/arch/x86/tboot.c
@@ -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;
}
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index c8cf1ac33d..da50880030 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -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 */
diff --git a/xen/drivers/acpi/tables.c b/xen/drivers/acpi/tables.c
index 252bf98873..a25d9b2be1 100644
--- a/xen/drivers/acpi/tables.c
+++ b/xen/drivers/acpi/tables.c
@@ -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;
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c
index 55c911cfe0..f4078ff44b 100644
--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -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;
}
diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h
index 6f5200dbed..a3c440daeb 100644
--- a/xen/include/asm-x86/smp.h
+++ b/xen/include/asm-x86/smp.h
@@ -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 */