Skip to content

Commit 7d68dc3

Browse files
mlankhorstIngo Molnar
authored andcommitted
x86, efi: Do not reserve boot services regions within reserved areas
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>
1 parent c11760c commit 7d68dc3

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

arch/x86/include/asm/memblock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#define ARCH_DISCARD_MEMBLOCK
55

66
u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
7-
void memblock_x86_to_bootmem(u64 start, u64 end);
87

98
void memblock_x86_reserve_range(u64 start, u64 end, char *name);
109
void memblock_x86_free_range(u64 start, u64 end);
@@ -19,5 +18,6 @@ u64 memblock_x86_hole_size(u64 start, u64 end);
1918
u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
2019
u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
2120
u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
21+
bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align);
2222

2323
#endif

arch/x86/mm/memblock.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <linux/range.h>
99

1010
/* Check for already reserved areas */
11-
static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
11+
bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align)
1212
{
1313
struct memblock_region *r;
1414
u64 addr = *addrp, last;
@@ -59,7 +59,7 @@ u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
5959
if (addr >= ei_last)
6060
continue;
6161
*sizep = ei_last - addr;
62-
while (check_with_memblock_reserved_size(&addr, sizep, align))
62+
while (memblock_x86_check_reserved_size(&addr, sizep, align))
6363
;
6464

6565
if (*sizep)

arch/x86/platform/efi/efi.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,31 @@ void __init efi_reserve_boot_services(void)
310310

311311
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
312312
efi_memory_desc_t *md = p;
313-
unsigned long long start = md->phys_addr;
314-
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
313+
u64 start = md->phys_addr;
314+
u64 size = md->num_pages << EFI_PAGE_SHIFT;
315315

316316
if (md->type != EFI_BOOT_SERVICES_CODE &&
317317
md->type != EFI_BOOT_SERVICES_DATA)
318318
continue;
319-
320-
memblock_x86_reserve_range(start, start + size, "EFI Boot");
319+
/* Only reserve where possible:
320+
* - Not within any already allocated areas
321+
* - Not over any memory area (really needed, if above?)
322+
* - Not within any part of the kernel
323+
* - Not the bios reserved area
324+
*/
325+
if ((start+size >= virt_to_phys(_text)
326+
&& start <= virt_to_phys(_end)) ||
327+
!e820_all_mapped(start, start+size, E820_RAM) ||
328+
memblock_x86_check_reserved_size(&start, &size,
329+
1<<EFI_PAGE_SHIFT)) {
330+
/* Could not reserve, skip it */
331+
md->num_pages = 0;
332+
memblock_dbg(PFX "Could not reserve boot range "
333+
"[0x%010llx-0x%010llx]\n",
334+
start, start+size-1);
335+
} else
336+
memblock_x86_reserve_range(start, start+size,
337+
"EFI Boot");
321338
}
322339
}
323340

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

354+
/* Could not reserve boot area */
355+
if (!size)
356+
continue;
357+
337358
free_bootmem_late(start, size);
338359
}
339360
}

0 commit comments

Comments
 (0)