Commit b2c99e3c authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Linus Torvalds

[PATCH] EFI: keep physical table addresses in efi structure

Almost all users of the table addresses from the EFI system table want
physical addresses.  So rather than doing the pa->va->pa conversion, just keep
physical addresses in struct efi.

This fixes a DMI bug: the efi structure contained the physical SMBIOS address
on x86 but the virtual address on ia64, so dmi_scan_machine() used ioremap()
on a virtual address on ia64.

This is essentially the same as an earlier patch by Matt Tolentino:
	http://marc.theaimsgroup.com/?l=linux-kernel&m=112130292316281&w=2
except that this changes all table addresses, not just ACPI addresses.

Matt's original patch was backed out because it caused MCAs on HP sx1000
systems.  That problem is resolved by the ioremap() attribute checking added
for ia64.
Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Cc: "Tolentino, Matthew E" <matthew.e.tolentino@intel.com>
Cc: "Brown, Len" <len.brown@intel.com>
Cc: Andi Kleen <ak@muc.de>
Acked-by: default avatar"Luck, Tony" <tony.luck@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 27d8e3d1
...@@ -668,10 +668,10 @@ unsigned long __init acpi_find_rsdp(void) ...@@ -668,10 +668,10 @@ unsigned long __init acpi_find_rsdp(void)
unsigned long rsdp_phys = 0; unsigned long rsdp_phys = 0;
if (efi_enabled) { if (efi_enabled) {
if (efi.acpi20) if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return __pa(efi.acpi20); return efi.acpi20;
else if (efi.acpi) else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
return __pa(efi.acpi); return efi.acpi;
} }
/* /*
* Scan memory looking for the RSDP signature. First search EBDA (low * Scan memory looking for the RSDP signature. First search EBDA (low
......
...@@ -217,14 +217,14 @@ void __init dmi_scan_machine(void) ...@@ -217,14 +217,14 @@ void __init dmi_scan_machine(void)
int rc; int rc;
if (efi_enabled) { if (efi_enabled) {
if (!efi.smbios) if (efi.smbios == EFI_INVALID_TABLE_ADDR)
goto out; goto out;
/* This is called as a core_initcall() because it isn't /* This is called as a core_initcall() because it isn't
* needed during early boot. This also means we can * needed during early boot. This also means we can
* iounmap the space when we're done with it. * iounmap the space when we're done with it.
*/ */
p = dmi_ioremap((unsigned long)efi.smbios, 32); p = dmi_ioremap(efi.smbios, 32);
if (p == NULL) if (p == NULL)
goto out; goto out;
......
...@@ -381,29 +381,38 @@ void __init efi_init(void) ...@@ -381,29 +381,38 @@ void __init efi_init(void)
if (config_tables == NULL) if (config_tables == NULL)
printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n"); printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
efi.mps = EFI_INVALID_TABLE_ADDR;
efi.acpi = EFI_INVALID_TABLE_ADDR;
efi.acpi20 = EFI_INVALID_TABLE_ADDR;
efi.smbios = EFI_INVALID_TABLE_ADDR;
efi.sal_systab = EFI_INVALID_TABLE_ADDR;
efi.boot_info = EFI_INVALID_TABLE_ADDR;
efi.hcdp = EFI_INVALID_TABLE_ADDR;
efi.uga = EFI_INVALID_TABLE_ADDR;
for (i = 0; i < num_config_tables; i++) { for (i = 0; i < num_config_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
efi.mps = (void *)config_tables[i].table; efi.mps = config_tables[i].table;
printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table); printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
} else } else
if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
efi.acpi20 = __va(config_tables[i].table); efi.acpi20 = config_tables[i].table;
printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table); printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
} else } else
if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
efi.acpi = __va(config_tables[i].table); efi.acpi = config_tables[i].table;
printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table); printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
} else } else
if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
efi.smbios = (void *) config_tables[i].table; efi.smbios = config_tables[i].table;
printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table); printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
} else } else
if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
efi.hcdp = (void *)config_tables[i].table; efi.hcdp = config_tables[i].table;
printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table); printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table);
} else } else
if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) {
efi.uga = (void *)config_tables[i].table; efi.uga = config_tables[i].table;
printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table); printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table);
} }
} }
......
...@@ -651,9 +651,9 @@ unsigned long __init acpi_find_rsdp(void) ...@@ -651,9 +651,9 @@ unsigned long __init acpi_find_rsdp(void)
{ {
unsigned long rsdp_phys = 0; unsigned long rsdp_phys = 0;
if (efi.acpi20) if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
rsdp_phys = __pa(efi.acpi20); rsdp_phys = efi.acpi20;
else if (efi.acpi) else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n"); "v1.0/r0.71 tables no longer supported\n");
return rsdp_phys; return rsdp_phys;
......
...@@ -458,24 +458,33 @@ efi_init (void) ...@@ -458,24 +458,33 @@ efi_init (void)
printk(KERN_INFO "EFI v%u.%.02u by %s:", printk(KERN_INFO "EFI v%u.%.02u by %s:",
efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
efi.mps = EFI_INVALID_TABLE_ADDR;
efi.acpi = EFI_INVALID_TABLE_ADDR;
efi.acpi20 = EFI_INVALID_TABLE_ADDR;
efi.smbios = EFI_INVALID_TABLE_ADDR;
efi.sal_systab = EFI_INVALID_TABLE_ADDR;
efi.boot_info = EFI_INVALID_TABLE_ADDR;
efi.hcdp = EFI_INVALID_TABLE_ADDR;
efi.uga = EFI_INVALID_TABLE_ADDR;
for (i = 0; i < (int) efi.systab->nr_tables; i++) { for (i = 0; i < (int) efi.systab->nr_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
efi.mps = __va(config_tables[i].table); efi.mps = config_tables[i].table;
printk(" MPS=0x%lx", config_tables[i].table); printk(" MPS=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
efi.acpi20 = __va(config_tables[i].table); efi.acpi20 = config_tables[i].table;
printk(" ACPI 2.0=0x%lx", config_tables[i].table); printk(" ACPI 2.0=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
efi.acpi = __va(config_tables[i].table); efi.acpi = config_tables[i].table;
printk(" ACPI=0x%lx", config_tables[i].table); printk(" ACPI=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
efi.smbios = __va(config_tables[i].table); efi.smbios = config_tables[i].table;
printk(" SMBIOS=0x%lx", config_tables[i].table); printk(" SMBIOS=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
efi.sal_systab = __va(config_tables[i].table); efi.sal_systab = config_tables[i].table;
printk(" SALsystab=0x%lx", config_tables[i].table); printk(" SALsystab=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
efi.hcdp = __va(config_tables[i].table); efi.hcdp = config_tables[i].table;
printk(" HCDP=0x%lx", config_tables[i].table); printk(" HCDP=0x%lx", config_tables[i].table);
} }
} }
......
...@@ -434,7 +434,7 @@ setup_arch (char **cmdline_p) ...@@ -434,7 +434,7 @@ setup_arch (char **cmdline_p)
find_memory(); find_memory();
/* process SAL system table: */ /* process SAL system table: */
ia64_sal_init(efi.sal_systab); ia64_sal_init(__va(efi.sal_systab));
ia64_setup_printk_clock(); ia64_setup_printk_clock();
......
...@@ -327,10 +327,11 @@ sn_scan_pcdp(void) ...@@ -327,10 +327,11 @@ sn_scan_pcdp(void)
struct pcdp_interface_pci if_pci; struct pcdp_interface_pci if_pci;
extern struct efi efi; extern struct efi efi;
pcdp = efi.hcdp; if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
if (! pcdp)
return; /* no hcdp/pcdp table */ return; /* no hcdp/pcdp table */
pcdp = __va(efi.hcdp);
if (pcdp->rev < 3) if (pcdp->rev < 3)
return; /* only support PCDP (rev >= 3) */ return; /* only support PCDP (rev >= 3) */
......
...@@ -156,12 +156,10 @@ acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) ...@@ -156,12 +156,10 @@ acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
{ {
if (efi_enabled) { if (efi_enabled) {
addr->pointer_type = ACPI_PHYSICAL_POINTER; addr->pointer_type = ACPI_PHYSICAL_POINTER;
if (efi.acpi20) if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
addr->pointer.physical = addr->pointer.physical = efi.acpi20;
(acpi_physical_address) virt_to_phys(efi.acpi20); else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
else if (efi.acpi) addr->pointer.physical = efi.acpi;
addr->pointer.physical =
(acpi_physical_address) virt_to_phys(efi.acpi);
else { else {
printk(KERN_ERR PREFIX printk(KERN_ERR PREFIX
"System description tables not found\n"); "System description tables not found\n");
......
...@@ -568,20 +568,20 @@ systab_read(struct subsystem *entry, char *buf) ...@@ -568,20 +568,20 @@ systab_read(struct subsystem *entry, char *buf)
if (!entry || !buf) if (!entry || !buf)
return -EINVAL; return -EINVAL;
if (efi.mps) if (efi.mps != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps)); str += sprintf(str, "MPS=0x%lx\n", efi.mps);
if (efi.acpi20) if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20)); str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
if (efi.acpi) if (efi.acpi != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi)); str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
if (efi.smbios) if (efi.smbios != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios)); str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
if (efi.hcdp) if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "HCDP=0x%lx\n", __pa(efi.hcdp)); str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
if (efi.boot_info) if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "BOOTINFO=0x%lx\n", __pa(efi.boot_info)); str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
if (efi.uga) if (efi.uga != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "UGA=0x%lx\n", __pa(efi.uga)); str += sprintf(str, "UGA=0x%lx\n", efi.uga);
return str - buf; return str - buf;
} }
......
...@@ -89,19 +89,20 @@ efi_setup_pcdp_console(char *cmdline) ...@@ -89,19 +89,20 @@ efi_setup_pcdp_console(char *cmdline)
struct pcdp_uart *uart; struct pcdp_uart *uart;
struct pcdp_device *dev, *end; struct pcdp_device *dev, *end;
int i, serial = 0; int i, serial = 0;
int rc = -ENODEV;
pcdp = efi.hcdp; if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
if (!pcdp)
return -ENODEV; return -ENODEV;
printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); pcdp = ioremap(efi.hcdp, 4096);
printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
if (strstr(cmdline, "console=hcdp")) { if (strstr(cmdline, "console=hcdp")) {
if (pcdp->rev < 3) if (pcdp->rev < 3)
serial = 1; serial = 1;
} else if (strstr(cmdline, "console=")) { } else if (strstr(cmdline, "console=")) {
printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
return -ENODEV; goto out;
} }
if (pcdp->rev < 3 && efi_uart_console_only()) if (pcdp->rev < 3 && efi_uart_console_only())
...@@ -110,7 +111,8 @@ efi_setup_pcdp_console(char *cmdline) ...@@ -110,7 +111,8 @@ efi_setup_pcdp_console(char *cmdline)
for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) { for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) { if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
if (uart->type == PCDP_CONSOLE_UART) { if (uart->type == PCDP_CONSOLE_UART) {
return setup_serial_console(uart); rc = setup_serial_console(uart);
goto out;
} }
} }
} }
...@@ -121,10 +123,13 @@ efi_setup_pcdp_console(char *cmdline) ...@@ -121,10 +123,13 @@ efi_setup_pcdp_console(char *cmdline)
dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->flags & PCDP_PRIMARY_CONSOLE) {
if (dev->type == PCDP_CONSOLE_VGA) { if (dev->type == PCDP_CONSOLE_VGA) {
return setup_vga_console(dev); rc = setup_vga_console(dev);
goto out;
} }
} }
} }
return -ENODEV; out:
iounmap(pcdp);
return rc;
} }
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
static inline u32 static inline u32
sn_sal_rev(void) sn_sal_rev(void)
{ {
struct ia64_sal_systab *systab = efi.sal_systab; struct ia64_sal_systab *systab = __va(efi.sal_systab);
return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor); return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
} }
......
...@@ -240,19 +240,21 @@ struct efi_memory_map { ...@@ -240,19 +240,21 @@ struct efi_memory_map {
unsigned long desc_size; unsigned long desc_size;
}; };
#define EFI_INVALID_TABLE_ADDR (~0UL)
/* /*
* All runtime access to EFI goes through this structure: * All runtime access to EFI goes through this structure:
*/ */
extern struct efi { extern struct efi {
efi_system_table_t *systab; /* EFI system table */ efi_system_table_t *systab; /* EFI system table */
void *mps; /* MPS table */ unsigned long mps; /* MPS table */
void *acpi; /* ACPI table (IA64 ext 0.71) */ unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
void *acpi20; /* ACPI table (ACPI 2.0) */ unsigned long acpi20; /* ACPI table (ACPI 2.0) */
void *smbios; /* SM BIOS table */ unsigned long smbios; /* SM BIOS table */
void *sal_systab; /* SAL system table */ unsigned long sal_systab; /* SAL system table */
void *boot_info; /* boot info table */ unsigned long boot_info; /* boot info table */
void *hcdp; /* HCDP table */ unsigned long hcdp; /* HCDP table */
void *uga; /* UGA table */ unsigned long uga; /* UGA table */
efi_get_time_t *get_time; efi_get_time_t *get_time;
efi_set_time_t *set_time; efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time; efi_get_wakeup_time_t *get_wakeup_time;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment