Skip to content

Commit

Permalink
acpi/x86: introduce __apci_map_table, v4
Browse files Browse the repository at this point in the history
to prevent wrongly overwriting fixmap that still want to use.

ACPI used to rely on low mappings being all linearly mapped and
grew a habit: it never really unmapped certain kinds of tables
after use.

This can cause problems - for example the hypothetical case
when some spurious access still references it.

v2: remove prev_map and prev_size in __apci_map_table
v3: let acpi_os_unmap_memory() call early_iounmap too, so remove extral calling to
early_acpi_os_unmap_memory
v4: fix typo in one acpi_get_table_with_size calling

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Acked-by: Len Brown <len.brown@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Yinghai Lu authored and Ingo Molnar committed Feb 9, 2009
1 parent 05876f8 commit 7d97277
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 27 deletions.
4 changes: 4 additions & 0 deletions arch/ia64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
return __va(phys_addr);
}

char *__init __acpi_unmap_table(unsigned long virt_addr, unsigned long size)
{
}

/* --------------------------------------------------------------------------
Boot-time Table Parsing
-------------------------------------------------------------------------- */
Expand Down
17 changes: 7 additions & 10 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,18 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
*/
char *__init __acpi_map_table(unsigned long phys, unsigned long size)
{
static char *prev_map;
static unsigned long prev_size;

if (prev_map) {
early_iounmap(prev_map, prev_size);
prev_map = NULL;
}

if (!phys || !size)
return NULL;

prev_size = size;
prev_map = early_ioremap(phys, size);
return early_ioremap(phys, size);
}
void __init __acpi_unmap_table(char *map, unsigned long size)
{
if (!map || !size)
return;

return prev_map;
early_iounmap(map, size);
}

#ifdef CONFIG_PCI_MMCONFIG
Expand Down
17 changes: 14 additions & 3 deletions drivers/acpi/acpica/tbxface.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)

/*******************************************************************************
*
* FUNCTION: acpi_get_table
* FUNCTION: acpi_get_table_with_size
*
* PARAMETERS: Signature - ACPI signature of needed table
* Instance - Which instance (for SSDTs)
Expand All @@ -377,8 +377,9 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
*
*****************************************************************************/
acpi_status
acpi_get_table(char *signature,
u32 instance, struct acpi_table_header **out_table)
acpi_get_table_with_size(char *signature,
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size)
{
u32 i;
u32 j;
Expand Down Expand Up @@ -408,6 +409,7 @@ acpi_get_table(char *signature,
acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
if (ACPI_SUCCESS(status)) {
*out_table = acpi_gbl_root_table_list.tables[i].pointer;
*tbl_size = acpi_gbl_root_table_list.tables[i].length;
}

if (!acpi_gbl_permanent_mmap) {
Expand All @@ -420,6 +422,15 @@ acpi_get_table(char *signature,
return (AE_NOT_FOUND);
}

acpi_status
acpi_get_table(char *signature,
u32 instance, struct acpi_table_header **out_table)
{
acpi_size tbl_size;

return acpi_get_table_with_size(signature,
instance, out_table, &tbl_size);
}
ACPI_EXPORT_SYMBOL(acpi_get_table)

/*******************************************************************************
Expand Down
6 changes: 0 additions & 6 deletions drivers/acpi/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,12 +694,6 @@ void __init acpi_early_init(void)
if (!acpi_strict)
acpi_gbl_enable_interpreter_slack = TRUE;

/*
* Doing a zero-sized mapping will clear out the previous
* __acpi_map_table() mapping, if any.
*/
__acpi_map_table(0, 0);

acpi_gbl_permanent_mmap = 1;

status = acpi_reallocate_root_table();
Expand Down
11 changes: 9 additions & 2 deletions drivers/acpi/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,19 @@ EXPORT_SYMBOL_GPL(acpi_os_map_memory);

void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
if (acpi_gbl_permanent_mmap) {
if (acpi_gbl_permanent_mmap)
iounmap(virt);
}
else
__acpi_unmap_table(virt, size);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);

void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
if (!acpi_gbl_permanent_mmap)
__acpi_unmap_table(virt, size);
}

#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
Expand Down
20 changes: 14 additions & 6 deletions drivers/acpi/tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,15 @@ acpi_table_parse_entries(char *id,
struct acpi_subtable_header *entry;
unsigned int count = 0;
unsigned long table_end;
acpi_size tbl_size;

if (!handler)
return -EINVAL;

if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
acpi_get_table(id, acpi_apic_instance, &table_header);
acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size);
else
acpi_get_table(id, 0, &table_header);
acpi_get_table_with_size(id, 0, &table_header, &tbl_size);

if (!table_header) {
printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
Expand All @@ -206,8 +207,10 @@ acpi_table_parse_entries(char *id,
table_end) {
if (entry->type == entry_id
&& (!max_entries || count++ < max_entries))
if (handler(entry, table_end))
if (handler(entry, table_end)) {
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return -EINVAL;
}

entry = (struct acpi_subtable_header *)
((unsigned long)entry + entry->length);
Expand All @@ -217,6 +220,7 @@ acpi_table_parse_entries(char *id,
"%i found\n", id, entry_id, count - max_entries, count);
}

early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
}

Expand All @@ -241,17 +245,19 @@ acpi_table_parse_madt(enum acpi_madt_type id,
int __init acpi_table_parse(char *id, acpi_table_handler handler)
{
struct acpi_table_header *table = NULL;
acpi_size tbl_size;

if (!handler)
return -EINVAL;

if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
acpi_get_table(id, acpi_apic_instance, &table);
acpi_get_table_with_size(id, acpi_apic_instance, &table, &tbl_size);
else
acpi_get_table(id, 0, &table);
acpi_get_table_with_size(id, 0, &table, &tbl_size);

if (table) {
handler(table);
early_acpi_os_unmap_memory(table, tbl_size);
return 0;
} else
return 1;
Expand All @@ -265,8 +271,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
static void __init check_multiple_madt(void)
{
struct acpi_table_header *table = NULL;
acpi_size tbl_size;

acpi_get_table(ACPI_SIG_MADT, 2, &table);
acpi_get_table_with_size(ACPI_SIG_MADT, 2, &table, &tbl_size);
if (table) {
printk(KERN_WARNING PREFIX
"BIOS bug: multiple APIC/MADT found,"
Expand All @@ -275,6 +282,7 @@ static void __init check_multiple_madt(void)
"If \"acpi_apic_instance=%d\" works better, "
"notify linux-acpi@vger.kernel.org\n",
acpi_apic_instance ? 0 : 2);
early_acpi_os_unmap_memory(table, tbl_size);

} else
acpi_apic_instance = 0;
Expand Down
1 change: 1 addition & 0 deletions include/acpi/acpiosxf.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ void __iomem *acpi_os_map_memory(acpi_physical_address where,
acpi_size length);

void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size);

#ifdef ACPI_FUTURE_USAGE
acpi_status
Expand Down
4 changes: 4 additions & 0 deletions include/acpi/acpixf.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ acpi_get_table_header(acpi_string signature,
struct acpi_table_header *out_table_header);

acpi_status
acpi_get_table_with_size(acpi_string signature,
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size);
acpi_status
acpi_get_table(acpi_string signature,
u32 instance, struct acpi_table_header **out_table);

Expand Down
1 change: 1 addition & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);

char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
void __init __acpi_unmap_table(char *map, unsigned long size);
int early_acpi_boot_init(void);
int acpi_boot_init (void);
int acpi_boot_table_init (void);
Expand Down

0 comments on commit 7d97277

Please sign in to comment.