aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-12-17 10:48:30 +0000
committerKeir Fraser <keir@xen.org>2010-12-17 10:48:30 +0000
commitf2133ab9dbfa0486999520e7e765bb34ca4425f5 (patch)
tree178afafa768f94e91d53233828a99ef47e3bb3ea
parent66c7e1a1ff293520302973ebff40e3270124bc0a (diff)
downloadxen-f2133ab9dbfa0486999520e7e765bb34ca4425f5.tar.gz
xen-f2133ab9dbfa0486999520e7e765bb34ca4425f5.tar.bz2
xen-f2133ab9dbfa0486999520e7e765bb34ca4425f5.zip
vtd: Reinstate ACPI DMAR on system shutdown or S3/S4/S5.
Signed-off-by: Keir Fraser <keir@xen.org> xen-unstable changeset: 22570:f2dba7ff0828 xen-unstable date: Fri Dec 17 10:46:43 2010 +0000
-rw-r--r--xen/arch/x86/acpi/power.c4
-rw-r--r--xen/arch/x86/shutdown.c2
-rw-r--r--xen/arch/x86/tboot.c9
-rw-r--r--xen/common/kexec.c9
-rw-r--r--xen/drivers/passthrough/vtd/dmar.c31
-rw-r--r--xen/include/xen/acpi.h3
6 files changed, 42 insertions, 16 deletions
diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c
index e6847b3e4f..f9e2973bd5 100644
--- a/xen/arch/x86/acpi/power.c
+++ b/xen/arch/x86/acpi/power.c
@@ -12,7 +12,6 @@
#include <xen/config.h>
#include <asm/io.h>
-#include <asm/acpi.h>
#include <xen/acpi.h>
#include <xen/errno.h>
#include <xen/iocap.h>
@@ -159,6 +158,8 @@ static int enter_state(u32 state)
freeze_domains();
+ acpi_dmar_reinstate();
+
disable_nonboot_cpus();
if ( num_online_cpus() != 1 )
{
@@ -229,6 +230,7 @@ static int enter_state(u32 state)
cpufreq_add_cpu(0);
microcode_resume_cpu(0);
enable_nonboot_cpus();
+ acpi_dmar_zap();
thaw_domains();
spin_unlock(&pm_lock);
return error;
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 135e6ebc63..371990add6 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -308,6 +308,8 @@ void machine_restart(unsigned int delay_millisecs)
console_start_sync();
spin_debug_disable();
+ acpi_dmar_reinstate();
+
local_irq_enable();
/* Ensure we are the boot CPU. */
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
index 4e86146f7d..5e50bfc4e0 100644
--- a/xen/arch/x86/tboot.c
+++ b/xen/arch/x86/tboot.c
@@ -5,6 +5,7 @@
#include <xen/sched.h>
#include <xen/domain_page.h>
#include <xen/iommu.h>
+#include <xen/acpi.h>
#include <asm/fixmap.h>
#include <asm/page.h>
#include <asm/processor.h>
@@ -479,13 +480,7 @@ int __init tboot_parse_dmar_table(acpi_table_handler dmar_handler)
/* acpi_parse_dmar() zaps APCI DMAR signature in TXT heap table */
/* but dom0 will read real table, so must zap it there too */
- dmar_table = NULL;
- acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table);
- if ( dmar_table != NULL )
- {
- dmar_table->signature[0] = 'X';
- dmar_table->checksum -= 'X'-'D';
- }
+ acpi_dmar_zap();
return rc;
}
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index da50880030..768bfd34d5 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -109,20 +109,13 @@ 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);
+ acpi_dmar_reinstate();
}
void kexec_crash(void)
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c
index d8edf03e53..1c7f9f3027 100644
--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -768,3 +768,34 @@ int __init acpi_dmar_init(void)
{
return parse_dmar_table(acpi_parse_dmar);
}
+
+static struct acpi_table_header *get_dmar(void)
+{
+ struct acpi_table_header *dmar_table = NULL;
+ unsigned long flags;
+
+ /* Disabling IRQs avoids cross-CPU TLB flush in map_pages_to_xen(). */
+ local_irq_save(flags);
+ acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table);
+ local_irq_restore(flags);
+
+ return dmar_table;
+}
+
+void acpi_dmar_reinstate(void)
+{
+ struct acpi_table_header *dmar_table = get_dmar();
+ if ( dmar_table == NULL )
+ return;
+ dmar_table->signature[0] = 'D';
+ dmar_table->checksum += 'X'-'D';
+}
+
+void acpi_dmar_zap(void)
+{
+ struct acpi_table_header *dmar_table = get_dmar();
+ if ( dmar_table == NULL )
+ return;
+ dmar_table->signature[0] = 'X';
+ dmar_table->checksum -= 'X'-'D';
+}
diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h
index 43b81536bf..aa812d34e8 100644
--- a/xen/include/xen/acpi.h
+++ b/xen/include/xen/acpi.h
@@ -421,4 +421,7 @@ extern int pnpacpi_disabled;
void acpi_reboot(void);
+void acpi_dmar_zap(void);
+void acpi_dmar_reinstate(void);
+
#endif /*_LINUX_ACPI_H*/