diff options
author | Keir Fraser <keir@xen.org> | 2010-12-17 10:48:30 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-12-17 10:48:30 +0000 |
commit | f2133ab9dbfa0486999520e7e765bb34ca4425f5 (patch) | |
tree | 178afafa768f94e91d53233828a99ef47e3bb3ea | |
parent | 66c7e1a1ff293520302973ebff40e3270124bc0a (diff) | |
download | xen-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.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/shutdown.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/tboot.c | 9 | ||||
-rw-r--r-- | xen/common/kexec.c | 9 | ||||
-rw-r--r-- | xen/drivers/passthrough/vtd/dmar.c | 31 | ||||
-rw-r--r-- | xen/include/xen/acpi.h | 3 |
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*/ |