From 6c298ecc1fc3c8e65be0f59e3c2095f29f59aa26 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 17 Dec 2010 10:46:43 +0000 Subject: [PATCH] vtd: Reinstate ACPI DMAR on system shutdown or S3/S4/S5. Signed-off-by: Keir Fraser --- xen/arch/x86/acpi/power.c | 4 +++- xen/arch/x86/shutdown.c | 2 ++ xen/arch/x86/tboot.c | 9 ++------- xen/common/kexec.c | 9 +-------- xen/drivers/passthrough/vtd/dmar.c | 31 ++++++++++++++++++++++++++++++ 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 f429d9914e..b4a633d544 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -140,6 +139,8 @@ static int enter_state(u32 state) freeze_domains(); + acpi_dmar_reinstate(); + if ( (error = disable_nonboot_cpus()) ) goto enable_cpu; @@ -208,6 +209,7 @@ static int enter_state(u32 state) mtrr_aps_sync_begin(); enable_nonboot_cpus(); mtrr_aps_sync_end(); + 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 c8821ed0a1..74ef63dfc8 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -309,6 +309,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 ae2d620099..cab39c440e 100644 --- a/xen/arch/x86/tboot.c +++ b/xen/arch/x86/tboot.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -475,13 +476,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 f6ce3b16a2..989907b98d 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -203,20 +203,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 08266ca704..0bc10ba047 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -771,3 +771,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 ade73d5616..42c3b6b87c 100644 --- a/xen/include/xen/acpi.h +++ b/xen/include/xen/acpi.h @@ -444,4 +444,7 @@ extern int pnpacpi_disabled; void acpi_reboot(void); +void acpi_dmar_zap(void); +void acpi_dmar_reinstate(void); + #endif /*_LINUX_ACPI_H*/ -- 2.39.5