84 lines
2.9 KiB
Diff
84 lines
2.9 KiB
Diff
From: Matt Fleming <matt@codeblueprint.co.uk>
|
|
Date: Thu, 21 Jan 2016 14:11:59 +0000
|
|
Subject: x86/efi: Setup separate EFI page tables in kexec paths
|
|
Origin: https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/commit?id=753b11ef8e92a1c1bbe97f2a5ec14bdd1ef2e6fe
|
|
|
|
The switch to using a new dedicated page table for EFI runtime
|
|
calls in commit commit 67a9108ed431 ("x86/efi: Build our own
|
|
page table structures") failed to take into account changes
|
|
required for the kexec code paths, which are unfortunately
|
|
duplicated in the EFI code.
|
|
|
|
Call the allocation and setup functions in
|
|
kexec_enter_virtual_mode() just like we do for
|
|
__efi_enter_virtual_mode() to avoid hitting NULL-pointer
|
|
dereferences when making EFI runtime calls.
|
|
|
|
At the very least, the call to efi_setup_page_tables() should
|
|
have existed for kexec before the following commit:
|
|
|
|
67a9108ed431 ("x86/efi: Build our own page table structures")
|
|
|
|
Things just magically worked because we were actually using
|
|
the kernel's page tables that contained the required mappings.
|
|
|
|
Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
|
|
Tested-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
|
|
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
|
|
Cc: Andy Lutomirski <luto@amacapital.net>
|
|
Cc: Borislav Petkov <bp@alien8.de>
|
|
Cc: Brian Gerst <brgerst@gmail.com>
|
|
Cc: Dave Young <dyoung@redhat.com>
|
|
Cc: Denys Vlasenko <dvlasenk@redhat.com>
|
|
Cc: H. Peter Anvin <hpa@zytor.com>
|
|
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Cc: Peter Zijlstra <peterz@infradead.org>
|
|
Cc: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
|
|
Cc: Thomas Gleixner <tglx@linutronix.de>
|
|
Link: http://lkml.kernel.org/r/1453385519-11477-1-git-send-email-matt@codeblueprint.co.uk
|
|
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
|
---
|
|
arch/x86/platform/efi/efi.c | 15 +++++++++++++++
|
|
1 file changed, 15 insertions(+)
|
|
|
|
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
|
|
index 3c1f3cd7b2ba..bdd9477f937c 100644
|
|
--- a/arch/x86/platform/efi/efi.c
|
|
+++ b/arch/x86/platform/efi/efi.c
|
|
@@ -815,6 +815,7 @@ static void __init kexec_enter_virtual_mode(void)
|
|
{
|
|
#ifdef CONFIG_KEXEC_CORE
|
|
efi_memory_desc_t *md;
|
|
+ unsigned int num_pages;
|
|
void *p;
|
|
|
|
efi.systab = NULL;
|
|
@@ -829,6 +830,12 @@ static void __init kexec_enter_virtual_mode(void)
|
|
return;
|
|
}
|
|
|
|
+ if (efi_alloc_page_tables()) {
|
|
+ pr_err("Failed to allocate EFI page tables\n");
|
|
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
|
|
+ return;
|
|
+ }
|
|
+
|
|
/*
|
|
* Map efi regions which were passed via setup_data. The virt_addr is a
|
|
* fixed addr which was used in first kernel of a kexec boot.
|
|
@@ -843,6 +850,14 @@ static void __init kexec_enter_virtual_mode(void)
|
|
|
|
BUG_ON(!efi.systab);
|
|
|
|
+ num_pages = ALIGN(memmap.nr_map * memmap.desc_size, PAGE_SIZE);
|
|
+ num_pages >>= PAGE_SHIFT;
|
|
+
|
|
+ if (efi_setup_page_tables(memmap.phys_map, num_pages)) {
|
|
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
|
|
+ return;
|
|
+ }
|
|
+
|
|
efi_sync_low_kernel_mappings();
|
|
|
|
/*
|