EFI urgent fixes
Subsystems (3)
Hi folks,
Please pull the following fixes. There are patches that resolve a few boot crashes and some minor build and boot log cleanups.
The following changes since commit 08332893e37af6ae779367e78e444f8f9571511d:
Linux 4.12-rc2 (2017-05-21 19:30:23 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-urgent
for you to fetch changes up to 5d36982a80248b2dcce395e7fa4ba342e814ced1:
efi/bgrt: Skip efi_bgrt_init in case of non-efi boot (2017-05-26 11:27:38 +0100)
----------------------------------------------------------------
- Make the boot console quiet when using Xen on EFI by deleting a pointless error message - Juergen Gross
- Silence harmless warnings emitted with GCC 7 - Arnd Bergmann
- Prevent a crash when booting kexec with the efi=old_map kernel command line parameter by disabling EFI runtime services - Sai Praneeth
- Fix boot crash when using kaslr and efi=old_map. The crash is caused because of assumptions about PAGE_OFFSET alignment which are not true with kaslr enabled - Baoquan He
- Fix boot regression when a machine has an ACPI BGRT table and is booted using BIOS, not EFI. - Dave Young
----------------------------------------------------------------
Arnd Bergmann (1):
efi: Remove duplicate 'const' specifiers
Baoquan He (1):
x86/efi: Correct ident mapping of efi old_map when kalsr enabled
Dave Young (1):
efi/bgrt: Skip efi_bgrt_init in case of non-efi boot
Juergen Gross (1):
efi: Don't issue error message when booted under xen
Sai Praneeth (1):
x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
arch/x86/platform/efi/efi.c | 6 ++- arch/x86/platform/efi/efi_64.c | 79 +++++++++++++++++++++++++++---- arch/x86/platform/efi/quirks.c | 3 ++ drivers/firmware/efi/efi-bgrt.c | 3 ++ drivers/firmware/efi/libstub/secureboot.c | 4 +- 5 files changed, 83 insertions(+), 12 deletions(-)
PATCH 1/5 efi: Don't issue error message when booted under xen
From: Juergen Gross <[email protected]>
When booted as Xen dom0 there won't be an EFI memmap allocated. Avoid issuing an error message in this case:
[ 0.144079] efi: Failed to allocate new EFI memmap
--- arch/x86/platform/efi/quirks.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/platform/efi/quirks.c +3 -0
@@ -360,6 +360,9 @@ void __init efi_free_boot_services(void)free_bootmem_late (start, size); } +if (!num_entries) +return ; + new_size = efi.memmap.desc_size * num_entries; new_phys =efi_memmap_alloc (num_entries);if (!new_phys) {
Signature · 1 line
2.12.2
tip-bot for Juergen Gross
merge bot[tip:efi/urgent] efi: Don't issue error message when booted under Xen
efi: Don't issue error message when booted under Xen
Commit-ID: 1ea34adb87c969b89dfd83f1905a79161e9ada26 Gitweb: http://git.kernel.org/tip/1ea34adb87c969b89dfd83f1905a79161e9ada26 Author: Juergen Gross <[email protected]> AuthorDate: Fri, 26 May 2017 12:36:47 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 28 May 2017 11:06:16 +0200
efi: Don't issue error message when booted under Xen
When booted as Xen dom0 there won't be an EFI memmap allocated. Avoid issuing an error message in this case:
[ 0.144079] efi: Failed to allocate new EFI memmap
--- arch/x86/platform/efi/quirks.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/platform/efi/quirks.c +3 -0
@@ -360,6 +360,9 @@ void __init efi_free_boot_services(void)free_bootmem_late (start, size); } +if (!num_entries) +return ; + new_size = efi.memmap.desc_size * num_entries; new_phys =efi_memmap_alloc (num_entries);if (!new_phys) {
PATCH 2/5 efi: Remove duplicate 'const' specifiers
In reply to Matt FlemingFrom: Arnd Bergmann <[email protected]>
gcc-7 shows a harmless warning:
drivers/firmware/efi/libstub/secureboot.c:19:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier]
static const efi_char16_t const efi_SecureBoot_name[] = {drivers/firmware/efi/libstub/secureboot.c:22:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier]
Removing one of the specifiers gives us the expected behavior.
--- drivers/firmware/efi/libstub/secureboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/libstub/secureboot.c +2 -2
@@ -16,10 +16,10 @@/* BIOS variables */ 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 }; -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 };
Signature · 1 line
2.12.2
tip-bot for Arnd Bergmann
merge bot[tip:efi/urgent] efi: Remove duplicate 'const' specifiers
efi: Remove duplicate 'const' specifiers
Commit-ID: 684e3f965d0be8c26fedefe94f637374242aba08 Gitweb: http://git.kernel.org/tip/684e3f965d0be8c26fedefe94f637374242aba08 Author: Arnd Bergmann <[email protected]> AuthorDate: Fri, 26 May 2017 12:36:48 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 28 May 2017 11:06:16 +0200
efi: Remove duplicate 'const' specifiers
gcc-7 shows these harmless warnings:
drivers/firmware/efi/libstub/secureboot.c:19:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier]
static const efi_char16_t const efi_SecureBoot_name[] = {
drivers/firmware/efi/libstub/secureboot.c:22:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier]
Removing one of the specifiers gives us the expected behavior.
--- drivers/firmware/efi/libstub/secureboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/libstub/secureboot.c +2 -2
@@ -16,10 +16,10 @@/* BIOS variables */ 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 }; -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 };
PATCH 3/5 x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
In reply to Matt FlemingFrom: Sai Praneeth <[email protected]>
Booting kexec kernel with "efi=old_map" in kernel command line hits kernel panic as shown below.
BUG: unable to handle kernel paging request at ffff88007fe78070 IP: virt_efi_set_variable.part.7+0x63/0x1b0 PGD 7ea28067 PUD 7ea2b067 PMD 7ea2d067 PTE 0 [...] Call Trace: virt_efi_set_variable+0x5d/0x70 efi_delete_dummy_variable+0x7a/0x80 efi_enter_virtual_mode+0x3f6/0x4a7 start_kernel+0x375/0x400 x86_64_start_reservations+0x2a/0x2c x86_64_start_kernel+0x168/0x176 start_cpu+0x14/0x14
[ efi=old_map was never intended to work with kexec. The problem with
using efi=old_map is that the virtual addresses are assigned from the memory region used by other kernel mappings; vmalloc() space. Potentially there could be collisions when booting kexec if something else is mapped at the virtual address we allocated for runtime service regions in the initial boot - Matt Fleming ]
Since kexec was never intended to work with efi=old_map, disable runtime services in kexec if booted with efi=old_map, so that we don't panic.
--- arch/x86/platform/efi/efi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/platform/efi/efi.c +4 -2
@@ -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 -* 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 ();clear_bit (EFI_RUNTIME_SERVICES , &efi.flags);return ;
Signature · 1 line
2.12.2
tip-bot for Sai Praneeth
merge bot[tip:efi/urgent] x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
Commit-ID: 4e52797d2efefac3271abdc54439a3435abd77b9 Gitweb: http://git.kernel.org/tip/4e52797d2efefac3271abdc54439a3435abd77b9 Author: Sai Praneeth <[email protected]> AuthorDate: Fri, 26 May 2017 12:36:49 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 28 May 2017 11:06:16 +0200
x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map
Booting kexec kernel with "efi=old_map" in kernel command line hits kernel panic as shown below.
BUG: unable to handle kernel paging request at ffff88007fe78070 IP: virt_efi_set_variable.part.7+0x63/0x1b0 PGD 7ea28067 PUD 7ea2b067 PMD 7ea2d067 PTE 0 [...] Call Trace: virt_efi_set_variable() efi_delete_dummy_variable() efi_enter_virtual_mode() start_kernel() x86_64_start_reservations() x86_64_start_kernel() start_cpu()
[ efi=old_map was never intended to work with kexec. The problem with
using efi=old_map is that the virtual addresses are assigned from the memory region used by other kernel mappings; vmalloc() space. Potentially there could be collisions when booting kexec if something else is mapped at the virtual address we allocated for runtime service regions in the initial boot - Matt Fleming ]
Since kexec was never intended to work with efi=old_map, disable runtime services in kexec if booted with efi=old_map, so that we don't panic.
--- arch/x86/platform/efi/efi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/platform/efi/efi.c +4 -2
@@ -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 -* 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 ();clear_bit (EFI_RUNTIME_SERVICES , &efi.flags);return ;
PATCH 4/5 x86/efi: Correct ident mapping of efi old_map when kalsr enabled
In reply to Matt FlemingFrom: Baoquan He <[email protected]>
For EFI with 'efi=old_map' kernel option specified, Kernel will panic when kaslr is enabled.
The back trace is:
BUG: unable to handle kernel paging request at 000000007febd57e
IP: 0x7febd57e
PGD 1025a067
PUD 0
Oops: 0010 [#1] SMP [ ... ] Call Trace: ? efi_call+0x58/0x90 ? printk+0x58/0x6f efi_enter_virtual_mode+0x3c5/0x50d start_kernel+0x40f/0x4b8 ? set_init_arg+0x55/0x55 ? early_idt_handler_array+0x120/0x120 x86_64_start_reservations+0x24/0x26 x86_64_start_kernel+0x14c/0x16f start_cpu+0x14/0x14
The root cause is the ident mapping is not built correctly in old_map case.
For nokaslr kernel, PAGE_OFFSET is 0xffff880000000000 which is PGDIR_SIZE aligned. We can borrow the pud table from direct mapping safely. Given a physical address X, we have pud_index(X) == pud_index(__va(X)). However, for kaslr kernel, PAGE_OFFSET is PUD_SIZE aligned. For a given physical address X, pud_index(X) != pud_index(__va(X)). We can't only copy pgd entry from direct mapping to build ident mapping, instead need copy pud entry one by one from direct mapping.
Fix it.
--- arch/x86/platform/efi/efi_64.c | 79 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-)
arch/x86/platform/efi/efi_64.c +71 -8
@@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable)pgd_t *__init efi_call_phys_prolog (void ) { -unsigned long vaddress; -pgd_t *save_pgd; +unsigned long vaddr, addr_pgd, addr_p4d, addr_pud; +pgd_t *save_pgd, *pgd_k, *pgd_efi; +p4d_t *p4d, *p4d_k, *p4d_efi; +pud_t *pud;int pgd; -int n_pgds; +int n_pgds, i, j;if (!efi_enabled (EFI_OLD_MEMMAP )) { save_pgd = (pgd_t *)read_cr3 ();
@@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void) n_pgds =DIV_ROUND_UP ((max_pfn <<PAGE_SHIFT ),PGDIR_SIZE ); save_pgd =kmalloc_array (n_pgds,sizeof (*save_pgd),GFP_KERNEL ); +/* +* Build 1:1 ident mapping for old_map usage. It needs to be noticed +* that PAGE_OFFSET is PGDIR_SIZE aligned with KASLR disabled, while +* 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 +* . Means here we can only reuse pmd table of direct mapping. +*/ for (pgd =0 ; pgd < n_pgds; pgd++) { - save_pgd[pgd] = *pgd_offset_k (pgd *PGDIR_SIZE ); - vaddress = (unsigned long )__va (pgd *PGDIR_SIZE ); -set_pgd (pgd_offset_k (pgd *PGDIR_SIZE ), *pgd_offset_k (vaddress)); + addr_pgd = (unsigned long )(pgd *PGDIR_SIZE ); + vaddr = (unsigned long )__va (pgd *PGDIR_SIZE ); + 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:__flush_tlb_all ();
@@ -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. */ -int pgd_idx; +int pgd_idx, i;int nr_pgds; +pgd_t *pgd; +p4d_t *p4d; +pud_t *pud;if (!efi_enabled (EFI_OLD_MEMMAP )) {write_cr3 ((unsigned long )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 ); -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]); +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);__flush_tlb_all ();
Signature · 1 line
2.12.2
tip-bot for Baoquan He
merge bot[tip:efi/urgent] x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled
x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled
Commit-ID: 94133e46a0f5ca3f138479806104ab4a8cb0455e Gitweb: http://git.kernel.org/tip/94133e46a0f5ca3f138479806104ab4a8cb0455e Author: Baoquan He <[email protected]> AuthorDate: Fri, 26 May 2017 12:36:50 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 28 May 2017 11:06:16 +0200
x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled
For EFI with the 'efi=old_map' kernel option specified, the kernel will panic when KASLR is enabled:
BUG: unable to handle kernel paging request at 000000007febd57e IP: 0x7febd57e PGD 1025a067 PUD 0 Oops: 0010 [#1] SMP Call Trace: efi_enter_virtual_mode() start_kernel() x86_64_start_reservations() x86_64_start_kernel() start_cpu()
The root cause is that the identity mapping is not built correctly in the 'efi=old_map' case.
On 'nokaslr' kernels, PAGE_OFFSET is 0xffff880000000000 which is PGDIR_SIZE aligned. We can borrow the PUD table from the direct mappings safely. Given a physical address X, we have pud_index(X) == pud_index(__va(X)).
However, on KASLR kernels, PAGE_OFFSET is PUD_SIZE aligned. For a given physical address X, pud_index(X) != pud_index(__va(X)). We can't just copy the PGD entry from direct mapping to build identity mapping, instead we need to copy the PUD entries one by one from the direct mapping.
Fix it.
--- arch/x86/platform/efi/efi_64.c | 79 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-)
arch/x86/platform/efi/efi_64.c +71 -8
@@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable)pgd_t *__init efi_call_phys_prolog (void ) { -unsigned long vaddress; -pgd_t *save_pgd; +unsigned long vaddr, addr_pgd, addr_p4d, addr_pud; +pgd_t *save_pgd, *pgd_k, *pgd_efi; +p4d_t *p4d, *p4d_k, *p4d_efi; +pud_t *pud;int pgd; -int n_pgds; +int n_pgds, i, j;if (!efi_enabled (EFI_OLD_MEMMAP )) { save_pgd = (pgd_t *)read_cr3 ();
@@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void) n_pgds =DIV_ROUND_UP ((max_pfn <<PAGE_SHIFT ),PGDIR_SIZE ); 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++) { - save_pgd[pgd] = *pgd_offset_k (pgd *PGDIR_SIZE ); - vaddress = (unsigned long )__va (pgd *PGDIR_SIZE ); -set_pgd (pgd_offset_k (pgd *PGDIR_SIZE ), *pgd_offset_k (vaddress)); + addr_pgd = (unsigned long )(pgd *PGDIR_SIZE ); + vaddr = (unsigned long )__va (pgd *PGDIR_SIZE ); + 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:__flush_tlb_all ();
@@ -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. */ -int pgd_idx; +int pgd_idx, i;int nr_pgds; +pgd_t *pgd; +p4d_t *p4d; +pud_t *pud;if (!efi_enabled (EFI_OLD_MEMMAP )) {write_cr3 ((unsigned long )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 ); -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]); +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);__flush_tlb_all ();
PATCH 5/5 efi/bgrt: Skip efi_bgrt_init in case of non-efi boot
In reply to Matt FlemingFrom: Dave Young <[email protected]>
Sabrina Dubroca reported an early panic below, it was introduced by commit 7b0a911478c7 ("efi/x86: Move the EFI BGRT init code to early init code"). The cause is on this machine even for legacy boot firmware still provide the ACPI BGRT table which should be EFI only. Thus the garbage bgrt data caused the efi_bgrt_init panic.
Add a checking to skip efi_bgrt_init in case non EFI booting solves this problem.
BUG: unable to handle kernel paging request at ffffffffff240001 IP: efi_bgrt_init+0xdc/0x134
PGD 1ac0c067
PUD 1ac0e067
PMD 1aee9067
PTE 9380701800000163
Oops: 0009 [#1] SMP Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.10.0-rc5-00116-g7b0a911 #19 Hardware name: Hewlett-Packard HP Z220 CMT Workstation/1790, BIOS K51 v01.02 05/03/2012 task: ffffffff9fc10500 task.stack: ffffffff9fc00000 RIP: 0010:efi_bgrt_init+0xdc/0x134 RSP: 0000:ffffffff9fc03d58 EFLAGS: 00010082 RAX: ffffffffff240001 RBX: 0000000000000000 RCX: 1380701800000006 RDX: 8000000000000163 RSI: 9380701800000163 RDI: 00000000000005be RBP: ffffffff9fc03d70 R08: 1380701800001000 R09: 0000000000000002 R10: 000000000002d000 R11: ffff98a3dedd2fc6 R12: ffffffff9f9f22b6 R13: ffffffff9ff49480 R14: 0000000000000010 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffffffff9fd20000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffff240001 CR3: 000000001ac09000 CR4: 00000000000406b0 Call Trace: ? acpi_parse_ioapic+0x98/0x98 acpi_parse_bgrt+0x9/0xd acpi_table_parse+0x7a/0xa9 acpi_boot_init+0x3c7/0x4f9 ? acpi_parse_x2apic+0x74/0x74 ? acpi_parse_x2apic_nmi+0x46/0x46 setup_arch+0xb4b/0xc6f ? printk+0x52/0x6e start_kernel+0xb2/0x47b ? early_idt_handler_array+0x120/0x120 x86_64_start_reservations+0x24/0x26 x86_64_start_kernel+0xf7/0x11a start_cpu+0x14/0x14 Code: 48 c7 c7 10 16 a0 9f e8 4e 94 40 ff eb 62 be 06 00 00 00 e8 f9 ff 00 00 48 85 c0 75 0e 48 c7 c7 40 16 a0 9f e8 31 94 40 ff eb 45 <66> 44 8b 20 be 06 00 00 00 48 89 c7 8b 58 02 e8 87 00 01 00 66 RIP: efi_bgrt_init+0xdc/0x134 RSP: ffffffff9fc03d58 CR2: ffffffffff240001 ---[ end trace f68728a0d3053b52 ]--- Kernel panic - not syncing: Attempted to kill the idle task! ---[ end Kernel panic - not syncing: Attempted to kill the idle task!
--- drivers/firmware/efi/efi-bgrt.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/firmware/efi/efi-bgrt.c +3 -0
@@ -36,6 +36,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)if (acpi_disabled)return ; +if (!efi_enabled (EFI_BOOT )) +return ; +if (table->length <sizeof (bgrt_tab)) {pr_notice ("Ignoring BGRT: invalid length %u (expected %zu)\n" , table->length,sizeof (bgrt_tab));
Signature · 1 line
2.12.2
tip-bot for Dave Young
merge bot[tip:efi/urgent] efi/bgrt: Skip efi_bgrt_init() in case of non-EFI boot
efi/bgrt: Skip efi_bgrt_init() in case of non-EFI boot
Commit-ID: 7425826f4f7ac60f2538b06a7f0a5d1006405159 Gitweb: http://git.kernel.org/tip/7425826f4f7ac60f2538b06a7f0a5d1006405159 Author: Dave Young <[email protected]> AuthorDate: Fri, 26 May 2017 12:36:51 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 28 May 2017 11:06:17 +0200
efi/bgrt: Skip efi_bgrt_init() in case of non-EFI boot
Sabrina Dubroca reported an early panic:
BUG: unable to handle kernel paging request at ffffffffff240001 IP: efi_bgrt_init+0xdc/0x134
[...]
---[ end Kernel panic - not syncing: Attempted to kill the idle task!
... which was introduced by:
7b0a911478c7 ("efi/x86: Move the EFI BGRT init code to early init code")
The cause is that on this machine the firmware provides the EFI ACPI BGRT table even on legacy non-EFI bootups - which table should be EFI only.
The garbage BGRT data causes the efi_bgrt_init() panic.
Add a check to skip efi_bgrt_init() in case non-EFI bootup to work around this firmware bug.
--- drivers/firmware/efi/efi-bgrt.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/firmware/efi/efi-bgrt.c +3 -0
@@ -36,6 +36,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)if (acpi_disabled)return ; +if (!efi_enabled (EFI_BOOT )) +return ; +if (table->length <sizeof (bgrt_tab)) {pr_notice ("Ignoring BGRT: invalid length %u (expected %zu)\n" , table->length,sizeof (bgrt_tab));