* [PATCHv4 0/3] Fix ACPI BGRT support for images located in EFI boot services memory @ 2012-09-29 0:55 Josh Triplett 2012-09-29 0:55 ` [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init Josh Triplett ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Josh Triplett @ 2012-09-29 0:55 UTC (permalink / raw) To: linux-kernel Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Matt Fleming, Olof Johansson, Matthew Garrett, David Howells, Rusty Russell, Peter Zijlstra, Pawel Moll, linux-acpi The ACPI BGRT lets the OS access the BIOS logo image and its position on the screen at boot time, allowing it to maintain that image on the screen until ready to display something else, making boot more seamless. This series fixes support for accessing the boot logo image via the BGRT when the BIOS stores it in EFI boot services memory, as recommended by the ACPI 5.0 spec. Linux needs to copy the image out of boot services memory before reclaiming boot services memory. The first patch refactors EFI initialization to defer freeing boot services memory until much later in the boot process, and in particular until after we have ACPI available. The second patch adds a helper function to look up existing EFI boot services mappings, to avoid re-mapping them. The third patch moves BGRT initialization to before the reclamation of boot services memory, copies the logo at that point, and reworks the existing BGRT driver to use that existing copy. v2: Made the new internal function efi_unmap_memmap static. Incorporated feedback from H. Peter Anvin and Matt Fleming: added stubs for x86-specific EFI functions called from init/main.c to eliminate the corresponding ifdefs in start_kernel; deferred efi_free_boot_services even later, to just before free_initmem. v3: Moved efi_free_boot_services back to right after EFI initialization, to avoid a WARN from check_early_ioremap_leak about not calling early_iounmap soon enough. v4: Cast the integral phys_addr through unsigned long before casting it to a pointer, to avoid a warning "cast to pointer from integer of different size" on 32-bit x86. Don't define efi_enter_virtual_mode as a stub on non-x86, because a different function exists on ia64 with that name, and ia64 calls that function in a different point in its initialiation; instead, go back to calling efi_enter_virtual_mode in init/main.c under an #ifdef CONFIG_X86. Define the stubs for efi_late_init and efi_free_boot_services using "static inline" to avoid unused function warnings. v4 should replace the version currently in tip x86/efi. Josh Triplett (3): efi: Defer freeing boot services memory until after ACPI init efi: Add a function to look up existing IO memory mappings efi: Fix the ACPI BGRT driver for images located in EFI boot services memory arch/x86/platform/efi/Makefile | 1 + arch/x86/platform/efi/efi-bgrt.c | 76 ++++++++++++++++++++++++++++++++++++++ arch/x86/platform/efi/efi.c | 65 +++++++++++++++++++++++++------- drivers/acpi/Kconfig | 4 +- drivers/acpi/bgrt.c | 76 +++++--------------------------------- include/linux/efi-bgrt.h | 21 +++++++++++ include/linux/efi.h | 8 ++++ init/main.c | 5 +++ 8 files changed, 174 insertions(+), 82 deletions(-) create mode 100644 arch/x86/platform/efi/efi-bgrt.c create mode 100644 include/linux/efi-bgrt.h -- 1.7.10.4 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init 2012-09-29 0:55 [PATCHv4 0/3] Fix ACPI BGRT support for images located in EFI boot services memory Josh Triplett @ 2012-09-29 0:55 ` Josh Triplett 2012-09-29 23:13 ` [tip:x86/efi] " tip-bot for Josh Triplett 2012-09-29 0:56 ` [PATCHv4 2/3] efi: Add a function to look up existing IO memory mappings Josh Triplett 2012-09-29 0:57 ` [PATCHv4 3/3] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory Josh Triplett 2 siblings, 1 reply; 8+ messages in thread From: Josh Triplett @ 2012-09-29 0:55 UTC (permalink / raw) To: linux-kernel Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Matt Fleming, Olof Johansson, Matthew Garrett, David Howells, Rusty Russell, Peter Zijlstra, Pawel Moll, linux-acpi Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett <josh@joshtriplett.org> --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 5 +++++ init/main.c | 3 +++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f55a4ce..b3dbbdb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void) } /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd..5782114 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +#ifdef CONFIG_X86 +extern void efi_free_boot_services(void); +#else +static inline void efi_free_boot_services(void) {} +#endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index b286730..d61ec54 100644 --- a/init/main.c +++ b/init/main.c @@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [tip:x86/efi] efi: Defer freeing boot services memory until after ACPI init 2012-09-29 0:55 ` [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init Josh Triplett @ 2012-09-29 23:13 ` tip-bot for Josh Triplett 0 siblings, 0 replies; 8+ messages in thread From: tip-bot for Josh Triplett @ 2012-09-29 23:13 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, josh, tglx, hpa Commit-ID: 785107923a83d8456bbd8564e288a24d84109a46 Gitweb: http://git.kernel.org/tip/785107923a83d8456bbd8564e288a24d84109a46 Author: Josh Triplett <josh@joshtriplett.org> AuthorDate: Fri, 28 Sep 2012 17:55:44 -0700 Committer: H. Peter Anvin <hpa@linux.intel.com> CommitDate: Sat, 29 Sep 2012 12:21:01 -0700 efi: Defer freeing boot services memory until after ACPI init Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 5 +++++ init/main.c | 3 +++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f55a4ce..b3dbbdb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void) } /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd..5782114 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +#ifdef CONFIG_X86 +extern void efi_free_boot_services(void); +#else +static inline void efi_free_boot_services(void) {} +#endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index b286730..d61ec54 100644 --- a/init/main.c +++ b/init/main.c @@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHv4 2/3] efi: Add a function to look up existing IO memory mappings 2012-09-29 0:55 [PATCHv4 0/3] Fix ACPI BGRT support for images located in EFI boot services memory Josh Triplett 2012-09-29 0:55 ` [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init Josh Triplett @ 2012-09-29 0:56 ` Josh Triplett 2012-09-29 23:14 ` [tip:x86/efi] " tip-bot for Josh Triplett 2012-09-29 0:57 ` [PATCHv4 3/3] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory Josh Triplett 2 siblings, 1 reply; 8+ messages in thread From: Josh Triplett @ 2012-09-29 0:56 UTC (permalink / raw) To: linux-kernel Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Matt Fleming, Olof Johansson, Matthew Garrett, David Howells, Rusty Russell, Peter Zijlstra, Pawel Moll, linux-acpi The EFI initialization creates virtual mappings for EFI boot services memory, so if a driver wants to access EFI boot services memory, it cannot call ioremap itself; doing so will trip the WARN about mapping RAM twice. Thus, a driver accessing EFI boot services memory must do so via the existing mapping already created during EFI intiialization. Since the EFI code already maintains a memory map for that memory, add a function efi_lookup_mapped_addr to look up mappings in that memory map. Signed-off-by: Josh Triplett <josh@joshtriplett.org> --- arch/x86/platform/efi/efi.c | 28 ++++++++++++++++++++++++++++ include/linux/efi.h | 1 + 2 files changed, 29 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b3dbbdb..f7f928c 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -777,6 +777,34 @@ static void __init runtime_code_page_mkexec(void) } /* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + void *p; + if (WARN_ON(!memmap.map)) + return NULL; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + u64 size = md->num_pages << EFI_PAGE_SHIFT; + u64 end = md->phys_addr + size; + if (!(md->attribute & EFI_MEMORY_RUNTIME) && + md->type != EFI_BOOT_SERVICES_CODE && + md->type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md->virt_addr) + continue; + if (phys_addr >= md->phys_addr && phys_addr < end) { + phys_addr += md->virt_addr - md->phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + +/* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that * has the runtime attribute bit set in its memory descriptor and update diff --git a/include/linux/efi.h b/include/linux/efi.h index 5782114..fff135d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -501,6 +501,7 @@ extern void efi_free_boot_services(void); #else static inline void efi_free_boot_services(void) {} #endif +extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [tip:x86/efi] efi: Add a function to look up existing IO memory mappings 2012-09-29 0:56 ` [PATCHv4 2/3] efi: Add a function to look up existing IO memory mappings Josh Triplett @ 2012-09-29 23:14 ` tip-bot for Josh Triplett 0 siblings, 0 replies; 8+ messages in thread From: tip-bot for Josh Triplett @ 2012-09-29 23:14 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, josh, tglx, hpa Commit-ID: 7bc90e01c3f66c137e7e761f574bbf883087d590 Gitweb: http://git.kernel.org/tip/7bc90e01c3f66c137e7e761f574bbf883087d590 Author: Josh Triplett <josh@joshtriplett.org> AuthorDate: Fri, 28 Sep 2012 17:56:08 -0700 Committer: H. Peter Anvin <hpa@linux.intel.com> CommitDate: Sat, 29 Sep 2012 12:21:02 -0700 efi: Add a function to look up existing IO memory mappings The EFI initialization creates virtual mappings for EFI boot services memory, so if a driver wants to access EFI boot services memory, it cannot call ioremap itself; doing so will trip the WARN about mapping RAM twice. Thus, a driver accessing EFI boot services memory must do so via the existing mapping already created during EFI intiialization. Since the EFI code already maintains a memory map for that memory, add a function efi_lookup_mapped_addr to look up mappings in that memory map. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/0eb48ae012797912874919110660ad420b90268b.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> --- arch/x86/platform/efi/efi.c | 28 ++++++++++++++++++++++++++++ include/linux/efi.h | 1 + 2 files changed, 29 insertions(+), 0 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b3dbbdb..f7f928c 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -777,6 +777,34 @@ static void __init runtime_code_page_mkexec(void) } /* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + void *p; + if (WARN_ON(!memmap.map)) + return NULL; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + u64 size = md->num_pages << EFI_PAGE_SHIFT; + u64 end = md->phys_addr + size; + if (!(md->attribute & EFI_MEMORY_RUNTIME) && + md->type != EFI_BOOT_SERVICES_CODE && + md->type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md->virt_addr) + continue; + if (phys_addr >= md->phys_addr && phys_addr < end) { + phys_addr += md->virt_addr - md->phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + +/* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that * has the runtime attribute bit set in its memory descriptor and update diff --git a/include/linux/efi.h b/include/linux/efi.h index 5782114..fff135d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -501,6 +501,7 @@ extern void efi_free_boot_services(void); #else static inline void efi_free_boot_services(void) {} #endif +extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHv4 3/3] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory 2012-09-29 0:55 [PATCHv4 0/3] Fix ACPI BGRT support for images located in EFI boot services memory Josh Triplett 2012-09-29 0:55 ` [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init Josh Triplett 2012-09-29 0:56 ` [PATCHv4 2/3] efi: Add a function to look up existing IO memory mappings Josh Triplett @ 2012-09-29 0:57 ` Josh Triplett 2012-09-29 23:15 ` [tip:x86/efi] " tip-bot for Josh Triplett 2 siblings, 1 reply; 8+ messages in thread From: Josh Triplett @ 2012-09-29 0:57 UTC (permalink / raw) To: linux-kernel Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Matt Fleming, Olof Johansson, Matthew Garrett, David Howells, Rusty Russell, Peter Zijlstra, Pawel Moll, linux-acpi The ACPI BGRT driver accesses the BIOS logo image when it initializes. However, ACPI 5.0 (which introduces the BGRT) recommends putting the logo image in EFI boot services memory, so that the OS can reclaim that memory. Production systems follow this recommendation, breaking the ACPI BGRT driver. Move the bulk of the BGRT code to run during a new EFI late initialization phase, which occurs after switching EFI to virtual mode, and after initializing ACPI, but before freeing boot services memory. Copy the BIOS logo image to kernel memory at that point, and make it accessible to the BGRT driver. Rework the existing ACPI BGRT driver to act as a simple wrapper exposing that image (and the properties from the BGRT) via sysfs. Signed-off-by: Josh Triplett <josh@joshtriplett.org> --- arch/x86/platform/efi/Makefile | 1 + arch/x86/platform/efi/efi-bgrt.c | 76 ++++++++++++++++++++++++++++++++++++++ arch/x86/platform/efi/efi.c | 6 +++ drivers/acpi/Kconfig | 4 +- drivers/acpi/bgrt.c | 76 +++++--------------------------------- include/linux/efi-bgrt.h | 21 +++++++++++ include/linux/efi.h | 2 + init/main.c | 4 +- 8 files changed, 120 insertions(+), 70 deletions(-) create mode 100644 arch/x86/platform/efi/efi-bgrt.c create mode 100644 include/linux/efi-bgrt.h diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index 73b8be0..6db1cc4 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o +obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c new file mode 100644 index 0000000..f6a0c1b --- /dev/null +++ b/arch/x86/platform/efi/efi-bgrt.c @@ -0,0 +1,76 @@ +/* + * Copyright 2012 Intel Corporation + * Author: Josh Triplett <josh@joshtriplett.org> + * + * Based on the bgrt driver: + * Copyright 2012 Red Hat, Inc <mjg@redhat.com> + * Author: Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/efi.h> +#include <linux/efi-bgrt.h> + +struct acpi_table_bgrt *bgrt_tab; +void *bgrt_image; +size_t bgrt_image_size; + +struct bmp_header { + u16 id; + u32 size; +} __packed; + +void efi_bgrt_init(void) +{ + acpi_status status; + void __iomem *image; + bool ioremapped = false; + struct bmp_header bmp_header; + + if (acpi_disabled) + return; + + status = acpi_get_table("BGRT", 0, + (struct acpi_table_header **)&bgrt_tab); + if (ACPI_FAILURE(status)) + return; + + if (bgrt_tab->version != 1) + return; + if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address) + return; + + image = efi_lookup_mapped_addr(bgrt_tab->image_address); + if (!image) { + image = ioremap(bgrt_tab->image_address, sizeof(bmp_header)); + ioremapped = true; + if (!image) + return; + } + + memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); + if (ioremapped) + iounmap(image); + bgrt_image_size = bmp_header.size; + + bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL); + if (!bgrt_image) + return; + + if (ioremapped) { + image = ioremap(bgrt_tab->image_address, bmp_header.size); + if (!image) { + kfree(bgrt_image); + bgrt_image = NULL; + return; + } + } + + memcpy_fromio(bgrt_image, image, bgrt_image_size); + if (ioremapped) + iounmap(image); +} diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f7f928c..aded2a9 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/efi.h> +#include <linux/efi-bgrt.h> #include <linux/export.h> #include <linux/bootmem.h> #include <linux/memblock.h> @@ -745,6 +746,11 @@ void __init efi_init(void) #endif } +void __init efi_late_init(void) +{ + efi_bgrt_init(); +} + void __init efi_set_executable(efi_memory_desc_t *md, bool executable) { u64 addr, npages; diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8099895..119d58d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD to override that restriction). config ACPI_BGRT - tristate "Boottime Graphics Resource Table support" - default n + bool "Boottime Graphics Resource Table support" + depends on EFI help This driver adds support for exposing the ACPI Boottime Graphics Resource Table, which allows the operating system to obtain diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 6680df3..be60399 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Red Hat, Inc <mjg@redhat.com> + * Copyright 2012 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,20 +12,10 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/sysfs.h> -#include <linux/io.h> -#include <acpi/acpi.h> -#include <acpi/acpi_bus.h> +#include <linux/efi-bgrt.h> -static struct acpi_table_bgrt *bgrt_tab; static struct kobject *bgrt_kobj; -struct bmp_header { - u16 id; - u32 size; -} __attribute ((packed)); - -static struct bmp_header bmp_header; - static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -63,18 +54,7 @@ static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); static ssize_t show_image(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - int size = attr->size; - void __iomem *image = attr->private; - - if (off >= size) { - count = 0; - } else { - if (off + count > size) - count = size - off; - - memcpy_fromio(buf, image+off, count); - } - + memcpy(buf, attr->private + off, count); return count; } @@ -101,45 +81,18 @@ static struct attribute_group bgrt_attribute_group = { static int __init bgrt_init(void) { - acpi_status status; int ret; - void __iomem *bgrt; - if (acpi_disabled) - return -ENODEV; - - status = acpi_get_table("BGRT", 0, - (struct acpi_table_header **)&bgrt_tab); - - if (ACPI_FAILURE(status)) + if (!bgrt_image) return -ENODEV; sysfs_bin_attr_init(&image_attr); - - bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); - - if (!bgrt) { - ret = -EINVAL; - goto out_err; - } - - memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header)); - image_attr.size = bmp_header.size; - iounmap(bgrt); - - image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size); - - if (!image_attr.private) { - ret = -EINVAL; - goto out_err; - } - + image_attr.private = bgrt_image; + image_attr.size = bgrt_image_size; bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); - if (!bgrt_kobj) { - ret = -EINVAL; - goto out_iounmap; - } + if (!bgrt_kobj) + return -EINVAL; ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); if (ret) @@ -155,22 +108,11 @@ out_group: sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); out_kobject: kobject_put(bgrt_kobj); -out_iounmap: - iounmap(image_attr.private); -out_err: return ret; } -static void __exit bgrt_exit(void) -{ - iounmap(image_attr.private); - sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); - sysfs_remove_bin_file(bgrt_kobj, &image_attr); -} - module_init(bgrt_init); -module_exit(bgrt_exit); -MODULE_AUTHOR("Matthew Garrett"); +MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>"); MODULE_DESCRIPTION("BGRT boot graphic support"); MODULE_LICENSE("GPL"); diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h new file mode 100644 index 0000000..051b21f --- /dev/null +++ b/include/linux/efi-bgrt.h @@ -0,0 +1,21 @@ +#ifndef _LINUX_EFI_BGRT_H +#define _LINUX_EFI_BGRT_H + +#ifdef CONFIG_ACPI_BGRT + +#include <linux/acpi.h> + +void efi_bgrt_init(void); + +/* The BGRT data itself; only valid if bgrt_image != NULL. */ +extern void *bgrt_image; +extern size_t bgrt_image_size; +extern struct acpi_table_bgrt *bgrt_tab; + +#else /* !CONFIG_ACPI_BGRT */ + +static inline void efi_bgrt_init(void) {} + +#endif /* !CONFIG_ACPI_BGRT */ + +#endif /* _LINUX_EFI_BGRT_H */ diff --git a/include/linux/efi.h b/include/linux/efi.h index fff135d..8670eb1 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ #ifdef CONFIG_X86 +extern void efi_late_init(void); extern void efi_free_boot_services(void); #else +static inline void efi_late_init(void) {} static inline void efi_free_boot_services(void) {} #endif extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); diff --git a/init/main.c b/init/main.c index d61ec54..db34c0e 100644 --- a/init/main.c +++ b/init/main.c @@ -631,8 +631,10 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) + if (efi_enabled) { + efi_late_init(); efi_free_boot_services(); + } ftrace_init(); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [tip:x86/efi] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory 2012-09-29 0:57 ` [PATCHv4 3/3] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory Josh Triplett @ 2012-09-29 23:15 ` tip-bot for Josh Triplett 0 siblings, 0 replies; 8+ messages in thread From: tip-bot for Josh Triplett @ 2012-09-29 23:15 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, josh, tglx, hpa Commit-ID: 2223af389032425e3d1a70f9cb3a63feaa654ced Gitweb: http://git.kernel.org/tip/2223af389032425e3d1a70f9cb3a63feaa654ced Author: Josh Triplett <josh@joshtriplett.org> AuthorDate: Fri, 28 Sep 2012 17:57:05 -0700 Committer: H. Peter Anvin <hpa@linux.intel.com> CommitDate: Sat, 29 Sep 2012 12:21:03 -0700 efi: Fix the ACPI BGRT driver for images located in EFI boot services memory The ACPI BGRT driver accesses the BIOS logo image when it initializes. However, ACPI 5.0 (which introduces the BGRT) recommends putting the logo image in EFI boot services memory, so that the OS can reclaim that memory. Production systems follow this recommendation, breaking the ACPI BGRT driver. Move the bulk of the BGRT code to run during a new EFI late initialization phase, which occurs after switching EFI to virtual mode, and after initializing ACPI, but before freeing boot services memory. Copy the BIOS logo image to kernel memory at that point, and make it accessible to the BGRT driver. Rework the existing ACPI BGRT driver to act as a simple wrapper exposing that image (and the properties from the BGRT) via sysfs. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/93ce9f823f1c1f3bb88bdd662cce08eee7a17f5d.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> --- arch/x86/platform/efi/Makefile | 1 + arch/x86/platform/efi/efi-bgrt.c | 76 ++++++++++++++++++++++++++++++++++++++ arch/x86/platform/efi/efi.c | 6 +++ drivers/acpi/Kconfig | 4 +- drivers/acpi/bgrt.c | 76 ++++--------------------------------- include/linux/efi-bgrt.h | 21 ++++++++++ include/linux/efi.h | 2 + init/main.c | 4 +- 8 files changed, 120 insertions(+), 70 deletions(-) diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index 73b8be0..6db1cc4 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o +obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c new file mode 100644 index 0000000..f6a0c1b --- /dev/null +++ b/arch/x86/platform/efi/efi-bgrt.c @@ -0,0 +1,76 @@ +/* + * Copyright 2012 Intel Corporation + * Author: Josh Triplett <josh@joshtriplett.org> + * + * Based on the bgrt driver: + * Copyright 2012 Red Hat, Inc <mjg@redhat.com> + * Author: Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/efi.h> +#include <linux/efi-bgrt.h> + +struct acpi_table_bgrt *bgrt_tab; +void *bgrt_image; +size_t bgrt_image_size; + +struct bmp_header { + u16 id; + u32 size; +} __packed; + +void efi_bgrt_init(void) +{ + acpi_status status; + void __iomem *image; + bool ioremapped = false; + struct bmp_header bmp_header; + + if (acpi_disabled) + return; + + status = acpi_get_table("BGRT", 0, + (struct acpi_table_header **)&bgrt_tab); + if (ACPI_FAILURE(status)) + return; + + if (bgrt_tab->version != 1) + return; + if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address) + return; + + image = efi_lookup_mapped_addr(bgrt_tab->image_address); + if (!image) { + image = ioremap(bgrt_tab->image_address, sizeof(bmp_header)); + ioremapped = true; + if (!image) + return; + } + + memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); + if (ioremapped) + iounmap(image); + bgrt_image_size = bmp_header.size; + + bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL); + if (!bgrt_image) + return; + + if (ioremapped) { + image = ioremap(bgrt_tab->image_address, bmp_header.size); + if (!image) { + kfree(bgrt_image); + bgrt_image = NULL; + return; + } + } + + memcpy_fromio(bgrt_image, image, bgrt_image_size); + if (ioremapped) + iounmap(image); +} diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f7f928c..aded2a9 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/efi.h> +#include <linux/efi-bgrt.h> #include <linux/export.h> #include <linux/bootmem.h> #include <linux/memblock.h> @@ -745,6 +746,11 @@ void __init efi_init(void) #endif } +void __init efi_late_init(void) +{ + efi_bgrt_init(); +} + void __init efi_set_executable(efi_memory_desc_t *md, bool executable) { u64 addr, npages; diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8099895..119d58d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD to override that restriction). config ACPI_BGRT - tristate "Boottime Graphics Resource Table support" - default n + bool "Boottime Graphics Resource Table support" + depends on EFI help This driver adds support for exposing the ACPI Boottime Graphics Resource Table, which allows the operating system to obtain diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 6680df3..be60399 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Red Hat, Inc <mjg@redhat.com> + * Copyright 2012 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,20 +12,10 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/sysfs.h> -#include <linux/io.h> -#include <acpi/acpi.h> -#include <acpi/acpi_bus.h> +#include <linux/efi-bgrt.h> -static struct acpi_table_bgrt *bgrt_tab; static struct kobject *bgrt_kobj; -struct bmp_header { - u16 id; - u32 size; -} __attribute ((packed)); - -static struct bmp_header bmp_header; - static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -63,18 +54,7 @@ static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); static ssize_t show_image(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - int size = attr->size; - void __iomem *image = attr->private; - - if (off >= size) { - count = 0; - } else { - if (off + count > size) - count = size - off; - - memcpy_fromio(buf, image+off, count); - } - + memcpy(buf, attr->private + off, count); return count; } @@ -101,45 +81,18 @@ static struct attribute_group bgrt_attribute_group = { static int __init bgrt_init(void) { - acpi_status status; int ret; - void __iomem *bgrt; - if (acpi_disabled) - return -ENODEV; - - status = acpi_get_table("BGRT", 0, - (struct acpi_table_header **)&bgrt_tab); - - if (ACPI_FAILURE(status)) + if (!bgrt_image) return -ENODEV; sysfs_bin_attr_init(&image_attr); - - bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); - - if (!bgrt) { - ret = -EINVAL; - goto out_err; - } - - memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header)); - image_attr.size = bmp_header.size; - iounmap(bgrt); - - image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size); - - if (!image_attr.private) { - ret = -EINVAL; - goto out_err; - } - + image_attr.private = bgrt_image; + image_attr.size = bgrt_image_size; bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); - if (!bgrt_kobj) { - ret = -EINVAL; - goto out_iounmap; - } + if (!bgrt_kobj) + return -EINVAL; ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); if (ret) @@ -155,22 +108,11 @@ out_group: sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); out_kobject: kobject_put(bgrt_kobj); -out_iounmap: - iounmap(image_attr.private); -out_err: return ret; } -static void __exit bgrt_exit(void) -{ - iounmap(image_attr.private); - sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); - sysfs_remove_bin_file(bgrt_kobj, &image_attr); -} - module_init(bgrt_init); -module_exit(bgrt_exit); -MODULE_AUTHOR("Matthew Garrett"); +MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>"); MODULE_DESCRIPTION("BGRT boot graphic support"); MODULE_LICENSE("GPL"); diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h new file mode 100644 index 0000000..051b21f --- /dev/null +++ b/include/linux/efi-bgrt.h @@ -0,0 +1,21 @@ +#ifndef _LINUX_EFI_BGRT_H +#define _LINUX_EFI_BGRT_H + +#ifdef CONFIG_ACPI_BGRT + +#include <linux/acpi.h> + +void efi_bgrt_init(void); + +/* The BGRT data itself; only valid if bgrt_image != NULL. */ +extern void *bgrt_image; +extern size_t bgrt_image_size; +extern struct acpi_table_bgrt *bgrt_tab; + +#else /* !CONFIG_ACPI_BGRT */ + +static inline void efi_bgrt_init(void) {} + +#endif /* !CONFIG_ACPI_BGRT */ + +#endif /* _LINUX_EFI_BGRT_H */ diff --git a/include/linux/efi.h b/include/linux/efi.h index fff135d..8670eb1 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ #ifdef CONFIG_X86 +extern void efi_late_init(void); extern void efi_free_boot_services(void); #else +static inline void efi_late_init(void) {} static inline void efi_free_boot_services(void) {} #endif extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); diff --git a/init/main.c b/init/main.c index d61ec54..db34c0e 100644 --- a/init/main.c +++ b/init/main.c @@ -631,8 +631,10 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) + if (efi_enabled) { + efi_late_init(); efi_free_boot_services(); + } ftrace_init(); ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHv3 2/4] efi: Defer freeing boot services memory until after ACPI init @ 2012-09-08 22:06 Josh Triplett 2012-09-27 21:56 ` [tip:x86/efi] " tip-bot for Josh Triplett 0 siblings, 1 reply; 8+ messages in thread From: Josh Triplett @ 2012-09-08 22:06 UTC (permalink / raw) To: linux-kernel Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Matt Fleming, Olof Johansson, Matthew Garrett, David Howells, Rusty Russell, Jim Cromie, Peter Zijlstra, linux-acpi Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett <josh@joshtriplett.org> --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 2 ++ init/main.c | 3 +++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660eda..ab2cfe8 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void) } /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * @@ -906,9 +914,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index 52fbedf..3c72c27 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); #ifdef CONFIG_X86 extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +extern void efi_free_boot_services(void); #else static void efi_enter_virtual_mode(void) {} +static void efi_free_boot_services(void) {} #endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index ebb1ba5..78e5491 100644 --- a/init/main.c +++ b/init/main.c @@ -629,6 +629,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [tip:x86/efi] efi: Defer freeing boot services memory until after ACPI init 2012-09-08 22:06 [PATCHv3 2/4] efi: Defer freeing boot services memory until after ACPI init Josh Triplett @ 2012-09-27 21:56 ` tip-bot for Josh Triplett 0 siblings, 0 replies; 8+ messages in thread From: tip-bot for Josh Triplett @ 2012-09-27 21:56 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, josh, tglx, hpa, matt.fleming Commit-ID: 668b132e837a2d1b346699bad4ae2e85bce52f55 Gitweb: http://git.kernel.org/tip/668b132e837a2d1b346699bad4ae2e85bce52f55 Author: Josh Triplett <josh@joshtriplett.org> AuthorDate: Sat, 8 Sep 2012 15:06:56 -0700 Committer: H. Peter Anvin <hpa@linux.intel.com> CommitDate: Thu, 27 Sep 2012 14:43:32 -0700 efi: Defer freeing boot services memory until after ACPI init Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/575b74a90571493561bf7bcf6fc0bdc12779fe35.1347141698.git.josh@joshtriplett.org Acked-by: Matt Fleming <matt.fleming@intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 2 ++ init/main.c | 3 +++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f55a4ce..b3dbbdb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void) } /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index 52fbedf..3c72c27 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -497,8 +497,10 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); #ifdef CONFIG_X86 extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +extern void efi_free_boot_services(void); #else static void efi_enter_virtual_mode(void) {} +static void efi_free_boot_services(void) {} #endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index ebb1ba5..78e5491 100644 --- a/init/main.c +++ b/init/main.c @@ -629,6 +629,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-09-29 23:16 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-09-29 0:55 [PATCHv4 0/3] Fix ACPI BGRT support for images located in EFI boot services memory Josh Triplett 2012-09-29 0:55 ` [PATCHv4 1/3] efi: Defer freeing boot services memory until after ACPI init Josh Triplett 2012-09-29 23:13 ` [tip:x86/efi] " tip-bot for Josh Triplett 2012-09-29 0:56 ` [PATCHv4 2/3] efi: Add a function to look up existing IO memory mappings Josh Triplett 2012-09-29 23:14 ` [tip:x86/efi] " tip-bot for Josh Triplett 2012-09-29 0:57 ` [PATCHv4 3/3] efi: Fix the ACPI BGRT driver for images located in EFI boot services memory Josh Triplett 2012-09-29 23:15 ` [tip:x86/efi] " tip-bot for Josh Triplett -- strict thread matches above, loose matches on Subject: below -- 2012-09-08 22:06 [PATCHv3 2/4] efi: Defer freeing boot services memory until after ACPI init Josh Triplett 2012-09-27 21:56 ` [tip:x86/efi] " tip-bot for Josh Triplett
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.