From: Al Stone ahs3@redhat.com
This series of patches first sets up the efi_map_regions() function, which is in turn used by setup_arch() to initialize ACPI tables loaded from RAM. For this to work properly, there were bugs to be fixed in both the EFI and ACPI code; these fixes get the two to agree on where the ACPI data is in RAM, and how it is to be addressed at early boot.
Al Stone (4): ARM: EFI: make efi_remap_regions() visible for use in setup_arch() ARM: ACPI: insert WARN_ON to make error condition more obvious ARM: clean up the io.h header file ACPI: ARM: use the correct ioremap sequence when loading and using ACPI data
arch/arm/include/asm/efi.h | 1 + arch/arm/include/asm/io.h | 9 ++------- arch/arm/kernel/efi.c | 31 +++++++++++++++++++++++-------- arch/arm/kernel/setup.c | 9 ++++++--- drivers/acpi/acpica/tbxface.c | 1 + drivers/acpi/osl.c | 12 ++++++------ drivers/acpi/plat/arm/boot.c | 19 +++++++------------ include/linux/acpi.h | 2 +- include/linux/acpi_io.h | 4 ++++ 9 files changed, 51 insertions(+), 37 deletions(-)
From: Al Stone ahs3@redhat.com
Make efi_remap_regions() visible. This allows ARM to gain access to objects passed in RAM from EFI very early on -- as needed by ACPI and FDT, for example -- by allowing the use of this function in setup_arch(). Note that in the process of making this visible, some portions of the function had to be corrected in order to operate well with ACPI and/or FDT.
Signed-off-by: Al Stone al.stone@linaro.org --- arch/arm/include/asm/efi.h | 1 + arch/arm/kernel/efi.c | 31 +++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index aead94c..93fa002 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -4,6 +4,7 @@ #include <asm/mach/map.h>
extern int efi_memblock_arm_reserve_range(void); +extern void efi_remap_regions(void);
typedef efi_status_t efi_phys_call_t(u32 memory_map_size, u32 descriptor_size, diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c index 11892b1..36e52f1 100644 --- a/arch/arm/kernel/efi.c +++ b/arch/arm/kernel/efi.c @@ -7,6 +7,7 @@ * */
+#include <linux/bootmem.h> #include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> @@ -362,20 +363,21 @@ static int __init remap_region(efi_memory_desc_t *md, efi_memory_desc_t *entry) return 1; }
-static int __init remap_regions(void) +void __init efi_remap_regions(void) { void *p, *next; efi_memory_desc_t *md;
- memmap.phys_map = get_runtime_mmap(); + memmap.phys_map = efi_remap(virt_to_phys(memmap.phys_map), + efi_boot_mmap_size); if (!memmap.phys_map) - return 0; + return; memmap.map_end = (void *)memmap.phys_map + efi_boot_mmap_size;
/* Allocate space for the physical region map */ - memmap.map = kzalloc(memmap.nr_map * memmap.desc_size, GFP_KERNEL); + memmap.map = alloc_bootmem_align(memmap.nr_map * memmap.desc_size, 8); if (!memmap.map) - return 0; + return;
next = memmap.map; for (p = memmap.phys_map; p < memmap.map_end; p += memmap.desc_size) { @@ -384,7 +386,7 @@ static int __init remap_regions(void) continue;
if (!remap_region(p, next)) - return 0; + return;
next += memmap.desc_size; } @@ -401,7 +403,10 @@ static int __init remap_regions(void) */ runtime = efi_lookup_mapped_addr((u32)efi.systab->runtime);
- return 1; + initial_boot_params = efi_lookup_mapped_addr( + __virt_to_phys((long unsigned int)initial_boot_params)); + + efi_unmap(memmap.phys_map); }
@@ -441,6 +446,7 @@ efi_status_t __init phys_set_virtual_address_map(u32 memory_map_size, void __init efi_enter_virtual_mode(void) { efi_status_t status; + void *mmap;
if (!efi_enabled(EFI_BOOT)) { pr_info("EFI services will not be available.\n"); @@ -451,11 +457,20 @@ void __init efi_enter_virtual_mode(void)
/* Map the regions we memblock_remove:d earlier into kernel address space */ - if (!remap_regions()) { + if (!efi_enabled(EFI_SYSTEM_TABLES)) { pr_info("Failed to remap EFI regions - runtime services will not be available.\n"); return; }
+ mmap = kzalloc(memmap.nr_map * memmap.desc_size, GFP_KERNEL); + if (!mmap) { + pr_info("Failed to allocate EFI memory map.\n"); + return; + } + memcpy(mmap, memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = mmap; + memmap.phys_map = get_runtime_mmap(); + /* Call SetVirtualAddressMap with the physical address of the map */ efi.set_virtual_address_map = (efi_set_virtual_address_map_t *)
From: Al Stone ahs3@redhat.com
This patch just makes it painfully obvious when the RSDP cannot be found.
Signed-off-by: Al Stone al.stone@linaro.org --- drivers/acpi/acpica/tbxface.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ad11162..41aebe6 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -137,6 +137,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, if (!rsdp_address) { return_ACPI_STATUS(AE_NOT_FOUND); } + WARN_ON(rsdp_address == 0);
/* * Get the root table (RSDT or XSDT) and extract all entries to the local
On Tue, 2013-09-24 at 14:45 -0600, al.stone@linaro.org wrote:
From: Al Stone ahs3@redhat.com
This patch just makes it painfully obvious when the RSDP cannot be found.
Signed-off-by: Al Stone al.stone@linaro.org
drivers/acpi/acpica/tbxface.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ad11162..41aebe6 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -137,6 +137,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, if (!rsdp_address) { return_ACPI_STATUS(AE_NOT_FOUND); }
- WARN_ON(rsdp_address == 0);
Isn't the WARN_ON unreachable here? Or maybe you wanted to remove the preceding error return.
--Mark
On 09/24/2013 03:11 PM, Mark Salter wrote:
On Tue, 2013-09-24 at 14:45 -0600, al.stone@linaro.org wrote:
From: Al Stone ahs3@redhat.com
This patch just makes it painfully obvious when the RSDP cannot be found.
Signed-off-by: Al Stone al.stone@linaro.org
drivers/acpi/acpica/tbxface.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ad11162..41aebe6 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -137,6 +137,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, if (!rsdp_address) { return_ACPI_STATUS(AE_NOT_FOUND); }
- WARN_ON(rsdp_address == 0);
Isn't the WARN_ON unreachable here? Or maybe you wanted to remove the preceding error return.
--Mark
Argh. Right you are. This part of the patch should be ignored, then. This is a leftover from some previous debug code that should not have been submitted. Sorry about the noise...
From: Al Stone ahs3@redhat.com
With the use of early_memremap() available, we can now clear up some macro definitions in preparation for upstream submittal.
Signed-off-by: Al Stone al.stone@linaro.org --- arch/arm/include/asm/io.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 426a13a..77c025a 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -328,12 +328,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t); */ #define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) #define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -/* - * BOZO: is this just mis-named as ioremap_cached()? - * renaming it to ioremap_cache() to find out for now. - #define ioremap_cached(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) - */ -#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) +#define ioremap_cached(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) #define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC) #define iounmap __arm_iounmap
@@ -415,7 +410,7 @@ extern void early_ioremap_reset(void); extern void __iomem *early_remap(resource_size_t phys_addr, unsigned long size, u32 prot); #define early_ioremap(x, y) early_remap(x, y, L_PTE_MT_DEV_NONSHARED) -#define early_memremap(x, y) early_remap(x, y, L_PTE_MT_UNCACHED) +#define early_memremap(x, y) early_remap(x, y, L_PTE_MT_WRITEALLOC)
extern void early_iounmap(void __iomem *addr, unsigned long size);
From: Al Stone ahs3@redhat.com
This patch converts the ACPI initialization sequence so that it uses early_memremap() prior to paging_init() having been called. This allows us to provide a more uniform mechanism for passing the ACPI data into the kernel via RAM on boot. Prior mechanisms would collide with DMI or FDT use of RAM so that no data was loaded; this allows for peaceful coexistence.
Signed-off-by: Al Stone al.stone@linaro.org --- arch/arm/kernel/setup.c | 9 ++++++--- drivers/acpi/osl.c | 12 ++++++------ drivers/acpi/plat/arm/boot.c | 19 +++++++------------ include/linux/acpi.h | 2 +- include/linux/acpi_io.h | 4 ++++ 5 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a440211..c3fac4f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -895,9 +895,6 @@ void __init setup_arch(char **cmdline_p) efi_memblock_arm_reserve_range(); #endif
- paging_init(mdesc); - request_standard_resources(mdesc); - #ifdef CONFIG_ACPI /* * Parse the ACPI tables for possible boot-time configuration @@ -906,9 +903,15 @@ void __init setup_arch(char **cmdline_p) early_acpi_boot_init(); #endif
+ paging_init(mdesc); + request_standard_resources(mdesc); + if (mdesc->restart) arm_pm_restart = mdesc->restart;
+#ifdef CONFIG_EFI + efi_remap_regions(); +#endif unflatten_device_tree();
arm_dt_init_cpu_maps(); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ebe34b3..3ed2207 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -290,7 +290,7 @@ void acpi_find_arm_root_pointer(acpi_physical_address *pa) (u64)rp->xsdt_physical_address); pr_debug(" x_checksum: 0x%02x\n", rp->extended_checksum);
- *pa = (acpi_physical_address)(virt_to_phys(rp)); + *pa = (acpi_physical_address)(virt_to_phys(rp)); } else { pr_err("ACPI missing rsdp info\n"); *pa = (acpi_physical_address)NULL; @@ -309,9 +309,9 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) - return efi.acpi20; + return efi.acpi20 + ACPI_BLOB_HEADER_SIZE; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) - return efi.acpi; + return efi.acpi + ACPI_BLOB_HEADER_SIZE; else { printk(KERN_ERR PREFIX "System description tables not found\n"); @@ -386,11 +386,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; }
-#ifndef CONFIG_IA64 -#define should_use_kmap(pfn) page_is_ram(pfn) -#else +#if defined(CONFIG_IA64) || defined(CONFIG_ARM) /* ioremap will take care of cache attributes */ #define should_use_kmap(pfn) 0 +#else +#define should_use_kmap(pfn) page_is_ram(pfn) #endif
static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index 5ca62dc..b22c57e 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -40,7 +40,10 @@
#include <asm/pgtable.h> #include <asm/io.h> +#include <asm/mach/map.h> +#ifdef CONFIG_SMP #include <asm/smp.h> +#endif #include <asm/acpi.h>
/* @@ -82,7 +85,7 @@ int acpi_use_timer_override __initdata; int acpi_fix_pin2_polarity __initdata; static u64 acpi_lapic_addr __initdata;
-struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP from FDT */ +struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP */
/* * Boot-time Configuration @@ -103,17 +106,12 @@ static unsigned int gsi_to_irq(unsigned int gsi) return irq; }
-/* - * BOZO: is it reasonable to just reserve the memory space? Or are there - * other restrictions needed? Or does it need copying to some other place? - */ -char *__init __acpi_map_table(unsigned long phys, unsigned long size) +char *__init __acpi_map_table(phys_addr_t phys, unsigned long size) { if (!phys || !size) return NULL;
- /* we're already in memory so we cannot io_remap the entry */ - return phys_to_virt(phys); + return early_memremap(phys, size); }
void __init __acpi_unmap_table(char *map, unsigned long size) @@ -121,10 +119,7 @@ void __init __acpi_unmap_table(char *map, unsigned long size) if (!map || !size) return;
- /* we're already in memory so we cannot io_remap the entry; - * since we're not io_remap'ing, unmap'ing is especially - * pointless - */ + early_iounmap(map, size); return; }
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f0eb673..53e0fa1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -88,7 +88,7 @@ static inline void acpi_initrd_override(void *data, size_t size) } #endif
-char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +char *__acpi_map_table(phys_addr_t phys_addr, unsigned long size); void __acpi_unmap_table(char *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h index b0ffa21..74a1eed 100644 --- a/include/linux/acpi_io.h +++ b/include/linux/acpi_io.h @@ -7,7 +7,11 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) { +#ifdef CONFIG_ARM + return early_memremap(phys, size); +#else return ioremap_cache(phys, size); +#endif }
void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size);
On Tue, Sep 24, 2013 at 02:46:01PM -0600, al.stone@linaro.org wrote:
From: Al Stone ahs3@redhat.com
This patch converts the ACPI initialization sequence so that it uses early_memremap() prior to paging_init() having been called. This allows us to provide a more uniform mechanism for passing the ACPI data into the kernel via RAM on boot. Prior mechanisms would collide with DMI or FDT use of RAM so that no data was loaded; this allows for peaceful coexistence.
Signed-off-by: Al Stone al.stone@linaro.org
arch/arm/kernel/setup.c | 9 ++++++--- drivers/acpi/osl.c | 12 ++++++------ drivers/acpi/plat/arm/boot.c | 19 +++++++------------ include/linux/acpi.h | 2 +- include/linux/acpi_io.h | 4 ++++ 5 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a440211..c3fac4f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -895,9 +895,6 @@ void __init setup_arch(char **cmdline_p) efi_memblock_arm_reserve_range(); #endif
- paging_init(mdesc);
- request_standard_resources(mdesc);
#ifdef CONFIG_ACPI /* * Parse the ACPI tables for possible boot-time configuration @@ -906,9 +903,15 @@ void __init setup_arch(char **cmdline_p) early_acpi_boot_init(); #endif
- paging_init(mdesc);
- request_standard_resources(mdesc);
- if (mdesc->restart) arm_pm_restart = mdesc->restart;
+#ifdef CONFIG_EFI
- efi_remap_regions();
+#endif unflatten_device_tree(); arm_dt_init_cpu_maps(); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ebe34b3..3ed2207 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -290,7 +290,7 @@ void acpi_find_arm_root_pointer(acpi_physical_address *pa) (u64)rp->xsdt_physical_address); pr_debug(" x_checksum: 0x%02x\n", rp->extended_checksum);
- *pa = (acpi_physical_address)(virt_to_phys(rp));
*pa = (acpi_physical_address)(virt_to_phys(rp));
Random spacing change?
} else { pr_err("ACPI missing rsdp info\n"); *pa = (acpi_physical_address)NULL; @@ -309,9 +309,9 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR)return efi.acpi20 + ACPI_BLOB_HEADER_SIZE;
return efi.acpi;
else {return efi.acpi + ACPI_BLOB_HEADER_SIZE;
Definately wrong, grub should fixup the offset not here. My original grub patch did fix this offset inside grub.
If you do this tables built into UEFI will be broken.
printk(KERN_ERR PREFIX "System description tables not found\n");
@@ -386,11 +386,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; } -#ifndef CONFIG_IA64 -#define should_use_kmap(pfn) page_is_ram(pfn) -#else +#if defined(CONFIG_IA64) || defined(CONFIG_ARM) /* ioremap will take care of cache attributes */ #define should_use_kmap(pfn) 0 +#else +#define should_use_kmap(pfn) page_is_ram(pfn) #endif static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index 5ca62dc..b22c57e 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -40,7 +40,10 @@ #include <asm/pgtable.h> #include <asm/io.h> +#include <asm/mach/map.h> +#ifdef CONFIG_SMP #include <asm/smp.h> +#endif #include <asm/acpi.h> /* @@ -82,7 +85,7 @@ int acpi_use_timer_override __initdata; int acpi_fix_pin2_polarity __initdata; static u64 acpi_lapic_addr __initdata; -struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP from FDT */ +struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP */
Unrelated comment change!
/*
- Boot-time Configuration
@@ -103,17 +106,12 @@ static unsigned int gsi_to_irq(unsigned int gsi) return irq; } -/*
- BOZO: is it reasonable to just reserve the memory space? Or are there
- other restrictions needed? Or does it need copying to some other place?
- */
-char *__init __acpi_map_table(unsigned long phys, unsigned long size) +char *__init __acpi_map_table(phys_addr_t phys, unsigned long size) { if (!phys || !size) return NULL;
- /* we're already in memory so we cannot io_remap the entry */
- return phys_to_virt(phys);
- return early_memremap(phys, size);
} void __init __acpi_unmap_table(char *map, unsigned long size) @@ -121,10 +119,7 @@ void __init __acpi_unmap_table(char *map, unsigned long size) if (!map || !size) return;
- /* we're already in memory so we cannot io_remap the entry;
* since we're not io_remap'ing, unmap'ing is especially
* pointless
*/
- early_iounmap(map, size); return;
} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f0eb673..53e0fa1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -88,7 +88,7 @@ static inline void acpi_initrd_override(void *data, size_t size) } #endif -char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +char *__acpi_map_table(phys_addr_t phys_addr, unsigned long size); void __acpi_unmap_table(char *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h index b0ffa21..74a1eed 100644 --- a/include/linux/acpi_io.h +++ b/include/linux/acpi_io.h @@ -7,7 +7,11 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) { +#ifdef CONFIG_ARM
- return early_memremap(phys, size);
+#else return ioremap_cache(phys, size); +#endif }
How can this even work? It is called after paging_init()?
void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size);
I shall make an attempt to fix the issues I have found in this and re-send this patch.
This I guess will mean there is a fix needed for grub patch as well.
Graeme
On 09/24/2013 02:45 PM, al.stone@linaro.org wrote:
From: Al Stone ahs3@redhat.com
This series of patches first sets up the efi_map_regions() function, which is in turn used by setup_arch() to initialize ACPI tables loaded from RAM. For this to work properly, there were bugs to be fixed in both the EFI and ACPI code; these fixes get the two to agree on where the ACPI data is in RAM, and how it is to be addressed at early boot.
Al Stone (4): ARM: EFI: make efi_remap_regions() visible for use in setup_arch() ARM: ACPI: insert WARN_ON to make error condition more obvious ARM: clean up the io.h header file ACPI: ARM: use the correct ioremap sequence when loading and using ACPI data
arch/arm/include/asm/efi.h | 1 + arch/arm/include/asm/io.h | 9 ++------- arch/arm/kernel/efi.c | 31 +++++++++++++++++++++++-------- arch/arm/kernel/setup.c | 9 ++++++--- drivers/acpi/acpica/tbxface.c | 1 + drivers/acpi/osl.c | 12 ++++++------ drivers/acpi/plat/arm/boot.c | 19 +++++++------------ include/linux/acpi.h | 2 +- include/linux/acpi_io.h | 4 ++++ 9 files changed, 51 insertions(+), 37 deletions(-)
These can probably be made prettier but they do work, regardless.