Commit f56f88ee authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Ingo Molnar:
 "Misc fixes:

   - three boot crash fixes for uncommon configurations

   - silence a boot warning under virtualization

   - plus a GCC 7 related (harmless) build warning fix"

* 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi/bgrt: Skip efi_bgrt_init() in case of non-EFI boot
  x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled
  x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
  efi: Remove duplicate 'const' specifiers
  efi: Don't issue error message when booted under Xen
parents 3b1e342b 7425826f
...@@ -828,9 +828,11 @@ static void __init kexec_enter_virtual_mode(void) ...@@ -828,9 +828,11 @@ static void __init kexec_enter_virtual_mode(void)
/* /*
* We don't do virtual mode, since we don't do runtime services, on * We don't do virtual mode, since we don't do runtime services, on
* non-native EFI * non-native EFI. With efi=old_map, we don't do runtime services in
* kexec kernel because in the initial boot something else might
* have been mapped at these virtual addresses.
*/ */
if (!efi_is_native()) { if (!efi_is_native() || efi_enabled(EFI_OLD_MEMMAP)) {
efi_memmap_unmap(); efi_memmap_unmap();
clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return; return;
......
...@@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable) ...@@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable)
pgd_t * __init efi_call_phys_prolog(void) pgd_t * __init efi_call_phys_prolog(void)
{ {
unsigned long vaddress; unsigned long vaddr, addr_pgd, addr_p4d, addr_pud;
pgd_t *save_pgd; pgd_t *save_pgd, *pgd_k, *pgd_efi;
p4d_t *p4d, *p4d_k, *p4d_efi;
pud_t *pud;
int pgd; int pgd;
int n_pgds; int n_pgds, i, j;
if (!efi_enabled(EFI_OLD_MEMMAP)) { if (!efi_enabled(EFI_OLD_MEMMAP)) {
save_pgd = (pgd_t *)read_cr3(); save_pgd = (pgd_t *)read_cr3();
...@@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void) ...@@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void)
n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL); save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL);
/*
* Build 1:1 identity mapping for efi=old_map usage. Note that
* PAGE_OFFSET is PGDIR_SIZE aligned when KASLR is disabled, while
* it is PUD_SIZE ALIGNED with KASLR enabled. So for a given physical
* address X, the pud_index(X) != pud_index(__va(X)), we can only copy
* PUD entry of __va(X) to fill in pud entry of X to build 1:1 mapping.
* This means here we can only reuse the PMD tables of the direct mapping.
*/
for (pgd = 0; pgd < n_pgds; pgd++) { for (pgd = 0; pgd < n_pgds; pgd++) {
save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); addr_pgd = (unsigned long)(pgd * PGDIR_SIZE);
vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); vaddr = (unsigned long)__va(pgd * PGDIR_SIZE);
set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); pgd_efi = pgd_offset_k(addr_pgd);
save_pgd[pgd] = *pgd_efi;
p4d = p4d_alloc(&init_mm, pgd_efi, addr_pgd);
if (!p4d) {
pr_err("Failed to allocate p4d table!\n");
goto out;
}
for (i = 0; i < PTRS_PER_P4D; i++) {
addr_p4d = addr_pgd + i * P4D_SIZE;
p4d_efi = p4d + p4d_index(addr_p4d);
pud = pud_alloc(&init_mm, p4d_efi, addr_p4d);
if (!pud) {
pr_err("Failed to allocate pud table!\n");
goto out;
}
for (j = 0; j < PTRS_PER_PUD; j++) {
addr_pud = addr_p4d + j * PUD_SIZE;
if (addr_pud > (max_pfn << PAGE_SHIFT))
break;
vaddr = (unsigned long)__va(addr_pud);
pgd_k = pgd_offset_k(vaddr);
p4d_k = p4d_offset(pgd_k, vaddr);
pud[j] = *pud_offset(p4d_k, vaddr);
}
}
} }
out: out:
__flush_tlb_all(); __flush_tlb_all();
...@@ -104,8 +145,11 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) ...@@ -104,8 +145,11 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
/* /*
* After the lock is released, the original page table is restored. * After the lock is released, the original page table is restored.
*/ */
int pgd_idx; int pgd_idx, i;
int nr_pgds; int nr_pgds;
pgd_t *pgd;
p4d_t *p4d;
pud_t *pud;
if (!efi_enabled(EFI_OLD_MEMMAP)) { if (!efi_enabled(EFI_OLD_MEMMAP)) {
write_cr3((unsigned long)save_pgd); write_cr3((unsigned long)save_pgd);
...@@ -115,9 +159,28 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) ...@@ -115,9 +159,28 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) {
pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE);
set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]);
if (!(pgd_val(*pgd) & _PAGE_PRESENT))
continue;
for (i = 0; i < PTRS_PER_P4D; i++) {
p4d = p4d_offset(pgd,
pgd_idx * PGDIR_SIZE + i * P4D_SIZE);
if (!(p4d_val(*p4d) & _PAGE_PRESENT))
continue;
pud = (pud_t *)p4d_page_vaddr(*p4d);
pud_free(&init_mm, pud);
}
p4d = (p4d_t *)pgd_page_vaddr(*pgd);
p4d_free(&init_mm, p4d);
}
kfree(save_pgd); kfree(save_pgd);
__flush_tlb_all(); __flush_tlb_all();
......
...@@ -360,6 +360,9 @@ void __init efi_free_boot_services(void) ...@@ -360,6 +360,9 @@ void __init efi_free_boot_services(void)
free_bootmem_late(start, size); free_bootmem_late(start, size);
} }
if (!num_entries)
return;
new_size = efi.memmap.desc_size * num_entries; new_size = efi.memmap.desc_size * num_entries;
new_phys = efi_memmap_alloc(num_entries); new_phys = efi_memmap_alloc(num_entries);
if (!new_phys) { if (!new_phys) {
......
...@@ -36,6 +36,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table) ...@@ -36,6 +36,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
if (acpi_disabled) if (acpi_disabled)
return; return;
if (!efi_enabled(EFI_BOOT))
return;
if (table->length < sizeof(bgrt_tab)) { if (table->length < sizeof(bgrt_tab)) {
pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n",
table->length, sizeof(bgrt_tab)); table->length, sizeof(bgrt_tab));
......
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
/* BIOS variables */ /* BIOS variables */
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID; static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
static const efi_char16_t const efi_SecureBoot_name[] = { static const efi_char16_t efi_SecureBoot_name[] = {
'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
}; };
static const efi_char16_t const efi_SetupMode_name[] = { static const efi_char16_t efi_SetupMode_name[] = {
'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment