* [patch] fix ACPI table discovery from EFI for x86
@ 2005-07-14 0:59 Matt Tolentino
2005-08-04 22:07 ` Bjorn Helgaas
2005-08-04 22:34 ` Tolentino, Matthew E
0 siblings, 2 replies; 3+ messages in thread
From: Matt Tolentino @ 2005-07-14 0:59 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-ia64, tony.luck
This patch addresses a problem on x86 EFI systems with larger memory
configurations. Up until now, we've relied on the fact that the
ACPI RSDT would reside somewhere in low memory that could be permanently
mapped in kernel address space - so __va() has been sufficient. However,
on EFI systems, the RSDT is often anywhere in the lower 4GB of physical
address space. So, we may need to remap it on x86 systems.
Second, this fixes some miscalculations in one of the EFI memmap
callback functions.
Lastly, this also removes all of the va->pa->va contortions and
stores the physical location in the efi struct while preserving the
validity checks. This change is the only reason this impacts
ia64.
Tested on x86 EFI machines and boot tested on one ia64 machine
thanks to Tony. Additional testing on ia64 machines would be
appreciated!
Problem reported and original patch proposed by Ping Wei.
Signed-off-by: Matt Tolentino <matthew.e.tolentino@intel.com>
---
diff -urNp linux-2.6.13-rc3/arch/i386/kernel/acpi/boot.c linux-2.6.13-rc3-efi/arch/i386/kernel/acpi/boot.c
--- linux-2.6.13-rc3/arch/i386/kernel/acpi/boot.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/arch/i386/kernel/acpi/boot.c 2005-07-13 10:32:54.073297792 -0400
@@ -682,10 +682,10 @@ acpi_find_rsdp (void)
unsigned long rsdp_phys = 0;
if (efi_enabled) {
- if (efi.acpi20)
- return __pa(efi.acpi20);
- else if (efi.acpi)
- return __pa(efi.acpi);
+ if (efi.phys_acpi20 != EFI_INVALID_ACPI_TABLE_ADDR)
+ return efi.phys_acpi20;
+ else if (efi.phys_acpi != EFI_INVALID_ACPI_TABLE_ADDR)
+ return efi.phys_acpi;
}
/*
* Scan memory looking for the RSDP signature. First search EBDA (low
diff -urNp linux-2.6.13-rc3/arch/i386/kernel/efi.c linux-2.6.13-rc3-efi/arch/i386/kernel/efi.c
--- linux-2.6.13-rc3/arch/i386/kernel/efi.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/arch/i386/kernel/efi.c 2005-07-13 10:32:04.731798840 -0400
@@ -376,17 +376,20 @@ void __init efi_init(void)
if (config_tables = NULL)
printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
+ efi.phys_acpi20 = EFI_INVALID_ACPI_TABLE_ADDR;
+ efi.phys_acpi = EFI_INVALID_ACPI_TABLE_ADDR;
+
for (i = 0; i < num_config_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) = 0) {
efi.mps = (void *)config_tables[i].table;
printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) = 0) {
- efi.acpi20 = __va(config_tables[i].table);
+ efi.phys_acpi20 = config_tables[i].table;
printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) = 0) {
- efi.acpi = __va(config_tables[i].table);
+ efi.phys_acpi = config_tables[i].table;
printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) = 0) {
diff -urNp linux-2.6.13-rc3/arch/i386/kernel/setup.c linux-2.6.13-rc3-efi/arch/i386/kernel/setup.c
--- linux-2.6.13-rc3/arch/i386/kernel/setup.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/arch/i386/kernel/setup.c 2005-07-13 10:24:25.149665944 -0400
@@ -1034,10 +1034,10 @@ static int __init
free_available_memory(unsigned long start, unsigned long end, void *arg)
{
/* check max_low_pfn */
- if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
+ if (start >= (max_low_pfn << PAGE_SHIFT))
return 0;
- if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
- end = (max_low_pfn + 1) << PAGE_SHIFT;
+ if (end >= (max_low_pfn << PAGE_SHIFT))
+ end = max_low_pfn << PAGE_SHIFT;
if (start < end)
free_bootmem(start, end - start);
diff -urNp linux-2.6.13-rc3/arch/ia64/kernel/acpi.c linux-2.6.13-rc3-efi/arch/ia64/kernel/acpi.c
--- linux-2.6.13-rc3/arch/ia64/kernel/acpi.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/arch/ia64/kernel/acpi.c 2005-07-13 10:33:51.614550192 -0400
@@ -615,9 +615,9 @@ acpi_find_rsdp (void)
{
unsigned long rsdp_phys = 0;
- if (efi.acpi20)
- rsdp_phys = __pa(efi.acpi20);
- else if (efi.acpi)
+ if (efi.phys_acpi20 != EFI_INVALID_ACPI_TABLE_ADDR)
+ rsdp_phys = efi.phys_acpi20;
+ else if (efi.phys_acpi != EFI_INVALID_ACPI_TABLE_ADDR)
printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
diff -urNp linux-2.6.13-rc3/arch/ia64/kernel/efi.c linux-2.6.13-rc3-efi/arch/ia64/kernel/efi.c
--- linux-2.6.13-rc3/arch/ia64/kernel/efi.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/arch/ia64/kernel/efi.c 2005-07-13 10:33:32.002531672 -0400
@@ -596,15 +596,18 @@ efi_init (void)
printk(KERN_INFO "EFI v%u.%.02u by %s:",
efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
+ efi.phys_acpi20 = EFI_INVALID_ACPI_TABLE_ADDR;
+ efi.phys_acpi = EFI_INVALID_ACPI_TABLE_ADDR;
+
for (i = 0; i < (int) efi.systab->nr_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) = 0) {
efi.mps = __va(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) {
- efi.acpi20 = __va(config_tables[i].table);
+ efi.phys_acpi20 = 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) {
- efi.acpi = __va(config_tables[i].table);
+ efi.phys_acpi = config_tables[i].table;
printk(" ACPI=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) = 0) {
efi.smbios = __va(config_tables[i].table);
diff -urNp linux-2.6.13-rc3/drivers/acpi/osl.c linux-2.6.13-rc3-efi/drivers/acpi/osl.c
--- linux-2.6.13-rc3/drivers/acpi/osl.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/drivers/acpi/osl.c 2005-07-13 10:34:25.417411376 -0400
@@ -163,12 +163,12 @@ acpi_os_get_root_pointer(u32 flags, stru
{
if (efi_enabled) {
addr->pointer_type = ACPI_PHYSICAL_POINTER;
- if (efi.acpi20)
+ if (efi.phys_acpi20 != EFI_INVALID_ACPI_TABLE_ADDR)
addr->pointer.physical - (acpi_physical_address) virt_to_phys(efi.acpi20);
- else if (efi.acpi)
+ (acpi_physical_address)efi.phys_acpi20;
+ else if (efi.phys_acpi != EFI_INVALID_ACPI_TABLE_ADDR)
addr->pointer.physical - (acpi_physical_address) virt_to_phys(efi.acpi);
+ (acpi_physical_address)efi.phys_acpi;
else {
printk(KERN_ERR PREFIX "System description tables not found\n");
return AE_NOT_FOUND;
@@ -187,7 +187,9 @@ acpi_status
acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
{
if (efi_enabled) {
- if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
+ /* determine whether or not we need to call ioremap */
+ if ((EFI_MEMORY_WB & efi_mem_attributes(phys)) &&
+ ((unsigned long)phys < (unsigned long)__pa(high_memory))) {
*virt = (void __iomem *) phys_to_virt(phys);
} else {
*virt = ioremap(phys, size);
diff -urNp linux-2.6.13-rc3/drivers/acpi/tables.c linux-2.6.13-rc3-efi/drivers/acpi/tables.c
--- linux-2.6.13-rc3/drivers/acpi/tables.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/drivers/acpi/tables.c 2005-07-13 10:24:25.180661232 -0400
@@ -581,7 +581,8 @@ acpi_table_init (void)
return -ENODEV;
}
- rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys);
+ rsdp = (struct acpi_table_rsdp *) __acpi_map_table(rsdp_phys,
+ sizeof(struct acpi_table_rsdp));
if (!rsdp) {
printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
return -ENODEV;
diff -urNp linux-2.6.13-rc3/drivers/firmware/efivars.c linux-2.6.13-rc3-efi/drivers/firmware/efivars.c
--- linux-2.6.13-rc3/drivers/firmware/efivars.c 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/drivers/firmware/efivars.c 2005-07-13 10:24:25.183660776 -0400
@@ -570,10 +570,10 @@ systab_read(struct subsystem *entry, cha
if (efi.mps)
str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps));
- if (efi.acpi20)
- str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20));
- if (efi.acpi)
- str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi));
+ if (efi.phys_acpi20 != ~0UL)
+ str += sprintf(str, "ACPI20=0x%lx\n", efi.phys_acpi20);
+ if (efi.phys_acpi != ~0UL)
+ str += sprintf(str, "ACPI=0x%lx\n", efi.phys_acpi);
if (efi.smbios)
str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios));
if (efi.hcdp)
diff -urNp linux-2.6.13-rc3/include/linux/efi.h linux-2.6.13-rc3-efi/include/linux/efi.h
--- linux-2.6.13-rc3/include/linux/efi.h 2005-07-13 00:46:46.000000000 -0400
+++ linux-2.6.13-rc3-efi/include/linux/efi.h 2005-07-13 10:36:24.999232176 -0400
@@ -246,14 +246,16 @@ struct efi_memory_map {
unsigned long desc_version;
};
+#define EFI_INVALID_ACPI_TABLE_ADDR (~0UL)
+
/*
* All runtime access to EFI goes through this structure:
*/
extern struct efi {
efi_system_table_t *systab; /* EFI system table */
void *mps; /* MPS table */
- void *acpi; /* ACPI table (IA64 ext 0.71) */
- void *acpi20; /* ACPI table (ACPI 2.0) */
+ unsigned long phys_acpi; /* ACPI table */
+ unsigned long phys_acpi20; /* ACPI table (ACPI 2.0) */
void *smbios; /* SM BIOS table */
void *sal_systab; /* SAL system table */
void *boot_info; /* boot info table */
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch] fix ACPI table discovery from EFI for x86
2005-07-14 0:59 [patch] fix ACPI table discovery from EFI for x86 Matt Tolentino
@ 2005-08-04 22:07 ` Bjorn Helgaas
2005-08-04 22:34 ` Tolentino, Matthew E
1 sibling, 0 replies; 3+ messages in thread
From: Bjorn Helgaas @ 2005-08-04 22:07 UTC (permalink / raw)
To: Matt Tolentino; +Cc: linux-kernel, akpm, linux-ia64, tony.luck
On Wednesday 13 July 2005 7:09 pm, Matt Tolentino wrote:
> This patch addresses a problem on x86 EFI systems with larger memory
> configurations. Up until now, we've relied on the fact that the
> ACPI RSDT would reside somewhere in low memory that could be permanently
> mapped in kernel address space - so __va() has been sufficient. However,
> on EFI systems, the RSDT is often anywhere in the lower 4GB of physical
> address space. So, we may need to remap it on x86 systems.
The hunk below breaks HP rx7620, rx8620, and Superdome (all ia64)
systems. This is from 2.6.13-rc4-mm1, in
acpi-fix-table-discovery-from-efi-for-x86.patch
> @@ -187,7 +187,9 @@ acpi_status
> acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
> {
> if (efi_enabled) {
> - if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
> + /* determine whether or not we need to call ioremap */
> + if ((EFI_MEMORY_WB & efi_mem_attributes(phys)) &&
> + ((unsigned long)phys < (unsigned long)__pa(high_memory))) {
> *virt = (void __iomem *) phys_to_virt(phys);
> } else {
> *virt = ioremap(phys, size);
If "phys >= __pa(high_memory)", we use ioremap(), but there's no
guarantee that phys is in memory that supports UC. On the systems
I mentioned, phys is above high_memory, but in memory that only
supports WB, which leads to an MCA.
Here's a bit of the memmap:
available 0000000100000000-00000007FDFFFFFF 00000000006FE000 0000000000000008
reserved 00000040000A0000-00000040000BFFFF 0000000000000020 0000000000000008
available 0000004080000000-00000040FED9FFFF 000000000007EDA0 0000000000000008
BS_data 00000040FEDA0000-00000040FEDA1FFF 0000000000000002 0000000000000008
available 00000040FEDA2000-00000040FEDA7FFF 0000000000000006 0000000000000008
BS_data 00000040FEDA8000-00000040FF1FFFFF 0000000000000458 0000000000000008
available 00000040FF200000-00000040FF555FFF 0000000000000356 0000000000000008
RT_code 00000040FF556000-00000040FF5BFFFF 000000000000006A 8000000000000008
BS_code 00000040FF5C0000-00000040FF5FFFFF 0000000000000040 0000000000000008
available 00000040FF600000-00000040FF641FFF 0000000000000042 0000000000000008
RT_code 00000040FF642000-00000040FF67FFFF 000000000000003E 8000000000000008
available 00000040FF680000-00000040FF7DFFFF 0000000000000160 0000000000000008
RT_data 00000040FF7E0000-00000040FF7FFFFF 0000000000000020 8000000000000008
RT_code 00000703FF000000-00000703FFFFFFFF 0000000000001000 8000000000000008
PAL_code 00000723FF000000-00000723FF03FFFF 0000000000000040 8000000000000008
RT_code 00000723FF040000-00000723FFBAFFFF 0000000000000B70 8000000000000008
reserved 00000723FFBB0000-00000723FFE8FFFF 00000000000002E0 8000000000000008
RT_code 00000723FFE90000-00000723FFFFFFFF 0000000000000170 8000000000000008
MemMapIO 00000F0000000000-00000F003FFFFFFF 0000000000040000 8000000000000001
The firmware tables are up in the reserved section at 0x723FFBB0000:
EFI v1.10 by HP: SALsystab=0x723ff7e7640 ACPI 2.0=0x723ffbb0000 HCDP=0x723ffbf27f0 SMBIOS=0x7fffe000
But high_memory is only 0x00000040ff000000 because there's no available
memory for the OS to use above that point (there are a few pages marked
"available", but we ignore them to avoid attribute aliasing on ia64).
So we erroneously try to ioremap the ACPI tables, which causes uncached
accesses to them, which blows up because they really live in memory that
doesn't support UC.
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [patch] fix ACPI table discovery from EFI for x86
2005-07-14 0:59 [patch] fix ACPI table discovery from EFI for x86 Matt Tolentino
2005-08-04 22:07 ` Bjorn Helgaas
@ 2005-08-04 22:34 ` Tolentino, Matthew E
1 sibling, 0 replies; 3+ messages in thread
From: Tolentino, Matthew E @ 2005-08-04 22:34 UTC (permalink / raw)
To: Bjorn Helgaas, Brown, Len; +Cc: linux-kernel, akpm, linux-ia64, Luck, Tony
Bjorn Helgaas <> wrote:
> On Wednesday 13 July 2005 7:09 pm, Matt Tolentino wrote:
>> This patch addresses a problem on x86 EFI systems with larger memory
>> configurations. Up until now, we've relied on the fact that the
>> ACPI RSDT would reside somewhere in low memory that could be
>> permanently
>> mapped in kernel address space - so __va() has been sufficient.
>> However,
>> on EFI systems, the RSDT is often anywhere in the lower 4GB of
>> physical
>> address space. So, we may need to remap it on x86 systems.
>
> The hunk below breaks HP rx7620, rx8620, and Superdome (all ia64)
> systems. This is from 2.6.13-rc4-mm1, in
Ugh. Well, that's pretty ugly...
Andrew, Len, please drop this one until I look at this closer.
> acpi-fix-table-discovery-from-efi-for-x86.patch
Thanks for testing Bjorn.
matt
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-08-04 22:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-14 0:59 [patch] fix ACPI table discovery from EFI for x86 Matt Tolentino
2005-08-04 22:07 ` Bjorn Helgaas
2005-08-04 22:34 ` Tolentino, Matthew E
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox