Skip to content

Commit

Permalink
x86, efi: Do not reserve boot services regions within reserved areas
Browse files Browse the repository at this point in the history
Commit 916f676 started reserving boot service code since some systems
require you to keep that code around until SetVirtualAddressMap is called.

However, in some cases those areas will overlap with reserved regions.
The proper medium-term fix is to fix the bootloader to prevent the
conflicts from occurring by moving the kernel to a better position,
but the kernel should check for this possibility, and only reserve regions
which can be reserved.

Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
Link: http://lkml.kernel.org/r/4DF7A005.1050407@gmail.com
Acked-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Maarten Lankhorst authored and Ingo Molnar committed Jun 18, 2011
1 parent c11760c commit 7d68dc3
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/memblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#define ARCH_DISCARD_MEMBLOCK

u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
void memblock_x86_to_bootmem(u64 start, u64 end);

void memblock_x86_reserve_range(u64 start, u64 end, char *name);
void memblock_x86_free_range(u64 start, u64 end);
Expand All @@ -19,5 +18,6 @@ u64 memblock_x86_hole_size(u64 start, u64 end);
u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align);

#endif
4 changes: 2 additions & 2 deletions arch/x86/mm/memblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <linux/range.h>

/* Check for already reserved areas */
static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align)
{
struct memblock_region *r;
u64 addr = *addrp, last;
Expand Down Expand Up @@ -59,7 +59,7 @@ u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
if (addr >= ei_last)
continue;
*sizep = ei_last - addr;
while (check_with_memblock_reserved_size(&addr, sizep, align))
while (memblock_x86_check_reserved_size(&addr, sizep, align))
;

if (*sizep)
Expand Down
29 changes: 25 additions & 4 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,31 @@ void __init efi_reserve_boot_services(void)

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;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
u64 start = md->phys_addr;
u64 size = md->num_pages << EFI_PAGE_SHIFT;

if (md->type != EFI_BOOT_SERVICES_CODE &&
md->type != EFI_BOOT_SERVICES_DATA)
continue;

memblock_x86_reserve_range(start, start + size, "EFI Boot");
/* Only reserve where possible:
* - Not within any already allocated areas
* - Not over any memory area (really needed, if above?)
* - Not within any part of the kernel
* - Not the bios reserved area
*/
if ((start+size >= virt_to_phys(_text)
&& start <= virt_to_phys(_end)) ||
!e820_all_mapped(start, start+size, E820_RAM) ||
memblock_x86_check_reserved_size(&start, &size,
1<<EFI_PAGE_SHIFT)) {
/* Could not reserve, skip it */
md->num_pages = 0;
memblock_dbg(PFX "Could not reserve boot range "
"[0x%010llx-0x%010llx]\n",
start, start+size-1);
} else
memblock_x86_reserve_range(start, start+size,
"EFI Boot");
}
}

Expand All @@ -334,6 +351,10 @@ static void __init efi_free_boot_services(void)
md->type != EFI_BOOT_SERVICES_DATA)
continue;

/* Could not reserve boot area */
if (!size)
continue;

free_bootmem_late(start, size);
}
}
Expand Down

0 comments on commit 7d68dc3

Please sign in to comment.