aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-02 16:20:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-02 16:20:23 -0500
commitc67b42f3a3f03e68bf915f32c8f7be0b726fec1a (patch)
tree9abf8c8a276cd5e8119e5c50f53afc220648008e
parent027eb72cbcf81561867a764074964e2ce9828398 (diff)
parentc8f325a59cfc718d13a50fbc746ed9b415c25e92 (diff)
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: "Two EFI boot fixes, one for arm64 and one for x86 systems with certain firmware versions" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi/fdt: Avoid FDT manipulation after ExitBootServices() x86/efi: Always map the first physical page into the EFI pagetables
-rw-r--r--arch/x86/platform/efi/efi_64.c16
-rw-r--r--drivers/firmware/efi/libstub/fdt.c14
2 files changed, 19 insertions, 11 deletions
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 319148bd4b05..2f25a363068c 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -269,6 +269,22 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
269 efi_scratch.use_pgd = true; 269 efi_scratch.use_pgd = true;
270 270
271 /* 271 /*
272 * Certain firmware versions are way too sentimential and still believe
273 * they are exclusive and unquestionable owners of the first physical page,
274 * even though they explicitly mark it as EFI_CONVENTIONAL_MEMORY
275 * (but then write-access it later during SetVirtualAddressMap()).
276 *
277 * Create a 1:1 mapping for this page, to avoid triple faults during early
278 * boot with such firmware. We are free to hand this page to the BIOS,
279 * as trim_bios_range() will reserve the first page and isolate it away
280 * from memory allocators anyway.
281 */
282 if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, _PAGE_RW)) {
283 pr_err("Failed to create 1:1 mapping for the first page!\n");
284 return 1;
285 }
286
287 /*
272 * When making calls to the firmware everything needs to be 1:1 288 * When making calls to the firmware everything needs to be 1:1
273 * mapped and addressable with 32-bit pointers. Map the kernel 289 * mapped and addressable with 32-bit pointers. Map the kernel
274 * text and allocate a new stack because we can't rely on the 290 * text and allocate a new stack because we can't rely on the
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 921dfa047202..260c4b4b492e 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -187,6 +187,7 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
187struct exit_boot_struct { 187struct exit_boot_struct {
188 efi_memory_desc_t *runtime_map; 188 efi_memory_desc_t *runtime_map;
189 int *runtime_entry_count; 189 int *runtime_entry_count;
190 void *new_fdt_addr;
190}; 191};
191 192
192static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, 193static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -202,7 +203,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
202 efi_get_virtmap(*map->map, *map->map_size, *map->desc_size, 203 efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
203 p->runtime_map, p->runtime_entry_count); 204 p->runtime_map, p->runtime_entry_count);
204 205
205 return EFI_SUCCESS; 206 return update_fdt_memmap(p->new_fdt_addr, map);
206} 207}
207 208
208/* 209/*
@@ -300,22 +301,13 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
300 301
301 priv.runtime_map = runtime_map; 302 priv.runtime_map = runtime_map;
302 priv.runtime_entry_count = &runtime_entry_count; 303 priv.runtime_entry_count = &runtime_entry_count;
304 priv.new_fdt_addr = (void *)*new_fdt_addr;
303 status = efi_exit_boot_services(sys_table, handle, &map, &priv, 305 status = efi_exit_boot_services(sys_table, handle, &map, &priv,
304 exit_boot_func); 306 exit_boot_func);
305 307
306 if (status == EFI_SUCCESS) { 308 if (status == EFI_SUCCESS) {
307 efi_set_virtual_address_map_t *svam; 309 efi_set_virtual_address_map_t *svam;
308 310
309 status = update_fdt_memmap((void *)*new_fdt_addr, &map);
310 if (status != EFI_SUCCESS) {
311 /*
312 * The kernel won't get far without the memory map, but
313 * may still be able to print something meaningful so
314 * return success here.
315 */
316 return EFI_SUCCESS;
317 }
318
319 /* Install the new virtual address map */ 311 /* Install the new virtual address map */
320 svam = sys_table->runtime->set_virtual_address_map; 312 svam = sys_table->runtime->set_virtual_address_map;
321 status = svam(runtime_entry_count * desc_size, desc_size, 313 status = svam(runtime_entry_count * desc_size, desc_size,