diff -r 4b476378fc35 xen/drivers/acpi/tables/tbutils.c --- a/xen/drivers/acpi/tables/tbutils.c Mon Jan 21 17:03:10 2013 +0000 +++ b/xen/drivers/acpi/tables/tbutils.c Tue Jan 22 15:13:43 2013 +0000 @@ -525,3 +525,23 @@ return_ACPI_STATUS(AE_OK); } + +acpi_status acpi_tb_get_table_physical_location(char *signature, acpi_physical_address *out_addr, u32 *out_size) +{ + acpi_native_uint i; + + if (!signature || !out_addr || !out_size) { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < acpi_gbl_root_table_list.count; i++) { + if (!ACPI_COMPARE_NAME(&(acpi_gbl_root_table_list.tables[i].signature), signature)) { + continue; + } + *out_addr = acpi_gbl_root_table_list.tables[i].address; + *out_size = acpi_gbl_root_table_list.tables[i].length; + return AE_OK; + } + return AE_NOT_FOUND; +} + diff -r 4b476378fc35 xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Mon Jan 21 17:03:10 2013 +0000 +++ b/xen/drivers/passthrough/vtd/dmar.c Tue Jan 22 15:13:43 2013 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #include "dmar.h" #include "iommu.h" #include "extern.h" @@ -46,7 +47,6 @@ static LIST_HEAD_READ_MOSTLY(acpi_atsr_units); static LIST_HEAD_READ_MOSTLY(acpi_rhsa_units); -static struct acpi_table_header *__read_mostly dmar_table; static int __read_mostly dmar_flags; static u64 __read_mostly igd_drhd_address; @@ -821,26 +821,56 @@ /* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */ #define parse_dmar_table(h) tboot_parse_dmar_table(h) +static struct acpi_table_header *map_dmar(void) +{ + acpi_physical_address addr; + u32 sz; + + if (acpi_tb_get_table_physical_location(ACPI_SIG_DMAR, &addr, &sz)) { + return NULL; + } + return (struct acpi_table_header*) ioremap(addr, sz); +} + +static void unmap_dmar(struct acpi_table_header *dmar_table) +{ + iounmap(dmar_table); +} + int __init acpi_dmar_init(void) { - acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table); return parse_dmar_table(acpi_parse_dmar); } void acpi_dmar_reinstate(void) { - if ( dmar_table == NULL ) - return; - dmar_table->signature[0] = 'D'; - dmar_table->checksum += 'X'-'D'; + unsigned long flags; + struct acpi_table_header *dmar_table; + /* Disabling IRQs avoids cross-CPU TLB flush in map_pages_to_xen(). */ + local_irq_save(flags); + dmar_table = map_dmar(); /* needs to be dynamically fetched here as acpi_get_table reuses the returned virtual address */ + if (dmar_table) { + dmar_table->signature[0] = 'D'; + dmar_table->checksum += 'X'-'D'; + unmap_dmar(dmar_table); + } + local_irq_restore(flags); } void acpi_dmar_zap(void) { - if ( dmar_table == NULL ) - return; - dmar_table->signature[0] = 'X'; - dmar_table->checksum -= 'X'-'D'; + unsigned long flags; + struct acpi_table_header *dmar_table; + /* Disabling IRQs avoids cross-CPU TLB flush in map_pages_to_xen(). */ + local_irq_save(flags); + dmar_table = map_dmar(); + if (dmar_table) { + dmar_table->signature[0] = 'X'; + dmar_table->checksum -= 'X'-'D'; + unmap_dmar(dmar_table); + } + local_irq_restore(flags); + } int platform_supports_intremap(void) diff -r 4b476378fc35 xen/include/acpi/actables.h --- a/xen/include/acpi/actables.h Mon Jan 21 17:03:10 2013 +0000 +++ b/xen/include/acpi/actables.h Tue Jan 22 15:13:43 2013 +0000 @@ -61,6 +61,8 @@ char *oem_id, char *oem_table_id, acpi_native_uint * table_index); +acpi_status acpi_tb_get_table_physical_location(char *signature, acpi_physical_address *out_addr, u32 *out_size); + /* * tbinstal - Table removal and deletion */