[tip:x86/mm] x86, ACPI: Split acpi_initrd_override() into find/copy two steps

From: tip-bot for Yinghai Lu
Date: Fri Jun 14 2013 - 17:36:30 EST

Commit-ID: 29206daa5831dc5b435a06387fd702875401c6bd
Gitweb: http://git.kernel.org/tip/29206daa5831dc5b435a06387fd702875401c6bd
Author: Yinghai Lu <yinghai@xxxxxxxxxx>
AuthorDate: Thu, 13 Jun 2013 21:02:53 +0800
Committer: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
CommitDate: Fri, 14 Jun 2013 14:04:01 -0700

x86, ACPI: Split acpi_initrd_override() into find/copy two steps

To parse SRAT before memblock starts to work, we need to move acpi table
probing procedure earlier. But acpi_initrd_table_override procedure must
be executed before acpi table probing. So we need to move it earlier too,
which means to move acpi_initrd_table_override procedure before memblock
starts to work.

But acpi_initrd_table_override procedure needs memblock to allocate buffer
for ACPI tables. To solve this problem, we need to split acpi_initrd_override()
procedure into two steps: finding and copying.
Find should be as early as possible. Copy should be after memblock is ready.

Currently, acpi_initrd_table_override procedure is executed after
init_mem_mapping() and relocate_initrd(), so it can scan initrd and copy
acpi tables with kernel virtual addresses of initrd.

Once we split it into finding and copying steps, it could be done like the

Finding could be done in head_32.S and head64.c, just like microcode early
scanning. In head_32.S, it is 32bit flat mode, we don't need to setup page
table to access it. In head64.c, #PF set page table could help us to access
initrd with kernel low mapping addresses.

Copying need to be done just after memblock is ready, because it needs to
allocate buffer for new acpi tables with memblock.
Also it should be done before probing acpi tables, and we need early_ioremap
to access source and target ranges, as init_mem_mapping is not called yet.

While a dummy version of acpi_initrd_override() was defined when
!CONFIG_ACPI_INITRD_TABLE_OVERRIDE, the prototype and dummy version were
conditionalized inside CONFIG_ACPI. This forced setup_arch() to have its own
#ifdefs around acpi_initrd_override() as otherwise build would fail when
!CONFIG_ACPI. Move the prototypes and dummy implementations of the newly
split functions out of CONFIG_ACPI block in acpi.h so that we can throw away
the #ifdefs from its users.

-v2: Split one patch out according to tj.
also don't pass table_nr around.
-v3: Add Tj's changelog about moving down to #idef in acpi.h to
avoid #idef in setup.c

Signed-off-by: Yinghai <yinghai@xxxxxxxxxx>
Link: http://lkml.kernel.org/r/1371128589-8953-7-git-send-email-tangchen@xxxxxxxxxxxxxx
Cc: Pekka Enberg <penberg@xxxxxxxxxx>
Cc: Jacob Shin <jacob.shin@xxxxxxx>
Cc: Rafael J. Wysocki <rjw@xxxxxxx>
Cc: linux-acpi@xxxxxxxxxxxxxxx
Acked-by: Tejun Heo <tj@xxxxxxxxxx>
Tested-by: Thomas Renninger <trenn@xxxxxxx>
Reviewed-by: Tang Chen <tangchen@xxxxxxxxxxxxxx>
Tested-by: Tang Chen <tangchen@xxxxxxxxxxxxxx>
Signed-off-by: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
arch/x86/kernel/setup.c | 6 +++---
drivers/acpi/osl.c | 18 +++++++++++++-----
include/linux/acpi.h | 16 ++++++++--------
3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 6ca5f2c..42f584c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1119,9 +1119,9 @@ void __init setup_arch(char **cmdline_p)


-#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
- acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
+ acpi_initrd_override_find((void *)initrd_start,
+ initrd_end - initrd_start);
+ acpi_initrd_override_copy();


diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 53dd490..6ab6c54 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -572,14 +572,13 @@ static const char * const table_sigs[] = {
static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];

-void __init acpi_initrd_override(void *data, size_t size)
+void __init acpi_initrd_override_find(void *data, size_t size)
- int sig, no, table_nr = 0, total_offset = 0;
+ int sig, no, table_nr = 0;
long offset = 0;
struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file;
- char *p;

if (data == NULL || size == 0)
@@ -620,7 +619,14 @@ void __init acpi_initrd_override(void *data, size_t size)
acpi_initrd_files[table_nr].size = file.size;
- if (table_nr == 0)
+void __init acpi_initrd_override_copy(void)
+ int no, total_offset = 0;
+ char *p;
+ if (!all_tables_size)

/* under 4G at first, then above 4G */
@@ -652,9 +658,11 @@ void __init acpi_initrd_override(void *data, size_t size)
* tables at one time, we will hit the limit. So we need to map tables
* one by one during copying.
- for (no = 0; no < table_nr; no++) {
+ for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
phys_addr_t size = acpi_initrd_files[no].size;

+ if (!size)
+ break;
p = early_ioremap(acpi_tables_addr + total_offset, size);
memcpy(p, acpi_initrd_files[no].data, size);
early_iounmap(p, size);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 17b5b59..8dd917b 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -79,14 +79,6 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
const unsigned long end);

-void acpi_initrd_override(void *data, size_t size);
-static inline void acpi_initrd_override(void *data, size_t size)
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
void __acpi_unmap_table(char *map, unsigned long size);
int early_acpi_boot_init(void);
@@ -476,6 +468,14 @@ static inline bool acpi_driver_match_device(struct device *dev,

#endif /* !CONFIG_ACPI */

+void acpi_initrd_override_find(void *data, size_t size);
+void acpi_initrd_override_copy(void);
+static inline void acpi_initrd_override_find(void *data, size_t size) { }
+static inline void acpi_initrd_override_copy(void) { }
void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
u32 pm1a_ctrl, u32 pm1b_ctrl));
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/