From: Jan Beulich Date: Wed, 4 Jun 2014 15:20:38 +0000 (+0200) Subject: ACPI/ERST: fix table mapping X-Git-Tag: 4.2.5-rc1~1 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=68dc110d63d24df71a0278812c2a4d99d3206faf;p=xen.git ACPI/ERST: fix table mapping acpi_get_table(), when executed before reaching SYS_STATE_active, will return a mapping valid only until the next invocation of that funciton. Consequently storing the returned pointer for later use is incorrect. Copy the logic used in VT-d's DMAR handling. Signed-off-by: Jan Beulich master commit: fca69b1fc606ece62430076ca4a157e4bed749a8 master date: 2014-05-26 12:25:01 +0200 --- diff --git a/xen/drivers/acpi/apei/erst.c b/xen/drivers/acpi/apei/erst.c index 71db9fa5a4..8af12639fa 100644 --- a/xen/drivers/acpi/apei/erst.c +++ b/xen/drivers/acpi/apei/erst.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -791,21 +792,42 @@ int __init erst_init(void) { int rc = 0; acpi_status status; + acpi_physical_address erst_addr; + acpi_native_uint erst_len; struct apei_exec_context ctx; if (acpi_disabled) return -ENODEV; - status = acpi_get_table(ACPI_SIG_ERST, 0, - (struct acpi_table_header **)&erst_tab); + status = acpi_get_table_phys(ACPI_SIG_ERST, 0, &erst_addr, &erst_len); if (status == AE_NOT_FOUND) { printk(KERN_INFO "ERST table was not found\n"); return -ENODEV; - } else if (ACPI_FAILURE(status)) { + } + if (ACPI_FAILURE(status)) { const char *msg = acpi_format_exception(status); printk(KERN_WARNING "Failed to get ERST table: %s\n", msg); return -EINVAL; } +#ifdef CONFIG_X86_32 + if (erst_addr + erst_len > (DIRECTMAP_MBYTES << 20)) { + unsigned long offset = erst_addr & (PAGE_SIZE - 1); + unsigned long mapped_size = PAGE_SIZE - offset; + + set_fixmap(FIX_ERST_LO, erst_addr); + if (mapped_size < erst_len) + set_fixmap(FIX_ERST_HI, erst_addr + PAGE_SIZE); + erst_tab = (void *)fix_to_virt(FIX_ERST_LO) + offset; + } else +#endif + { + map_pages_to_xen((unsigned long)__va(erst_addr), + PFN_DOWN(erst_addr), + PFN_UP(erst_addr + erst_len) + - PFN_DOWN(erst_addr), + PAGE_HYPERVISOR); + erst_tab = __va(erst_addr); + } rc = erst_check_table(erst_tab); if (rc) { diff --git a/xen/include/asm-x86/fixmap.h b/xen/include/asm-x86/fixmap.h index 0a7aafa830..30c334f1ad 100644 --- a/xen/include/asm-x86/fixmap.h +++ b/xen/include/asm-x86/fixmap.h @@ -39,6 +39,8 @@ enum fixed_addresses { #define FIX_VGC_BEGIN FIX_PAE_HIGHMEM_END FIX_DMAR_ZAP_HI, FIX_DMAR_ZAP_LO, + FIX_ERST_HI, + FIX_ERST_LO, #else FIX_VGC_END, FIX_VGC_BEGIN = FIX_VGC_END