diff options
author | Arvind Sankar <nivedita@alum.mit.edu> | 2020-10-10 15:11:10 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2020-10-19 12:47:21 +0200 |
commit | e5ceb9a02402b984feecb95a82239be151c9f4e2 (patch) | |
tree | c0ea17ca8e1d466a48abb1c37f4c67a3bf3fc7da | |
parent | da9803dfd3955bd2f9909d55e23f188ad76dbe58 (diff) |
x86/boot/64: Initialize 5-level paging variables earlier
Commit
ca0e22d4f011 ("x86/boot/compressed/64: Always switch to own page table")
started using a new set of pagetables even without KASLR.
After that commit, initialize_identity_maps() is called before the
5-level paging variables are setup in choose_random_location(), which
will not work if 5-level paging is actually enabled.
Fix this by moving the initialization of __pgtable_l5_enabled,
pgdir_shift and ptrs_per_p4d into cleanup_trampoline(), which is called
immediately after the finalization of whether the kernel is executing
with 4- or 5-level paging. This will be earlier than anything that might
require those variables, and keeps the 4- vs 5-level paging code all in
one place.
Fixes: ca0e22d4f011 ("x86/boot/compressed/64: Always switch to own page table")
Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Joerg Roedel <jroedel@suse.de>
Tested-by: Joerg Roedel <jroedel@suse.de>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Link: https://lkml.kernel.org/r/20201010191110.4060905-1-nivedita@alum.mit.edu
-rw-r--r-- | arch/x86/boot/compressed/ident_map_64.c | 6 | ||||
-rw-r--r-- | arch/x86/boot/compressed/kaslr.c | 8 | ||||
-rw-r--r-- | arch/x86/boot/compressed/pgtable_64.c | 16 |
3 files changed, 16 insertions, 14 deletions
diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c index 063a60edcf99..c6f7aef7e85a 100644 --- a/arch/x86/boot/compressed/ident_map_64.c +++ b/arch/x86/boot/compressed/ident_map_64.c @@ -33,12 +33,6 @@ #define __PAGE_OFFSET __PAGE_OFFSET_BASE #include "../../mm/ident_map.c" -#ifdef CONFIG_X86_5LEVEL -unsigned int __pgtable_l5_enabled; -unsigned int pgdir_shift = 39; -unsigned int ptrs_per_p4d = 1; -#endif - /* Used by PAGE_KERN* macros: */ pteval_t __default_kernel_pte_mask __read_mostly = ~0; diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index b59547ce5b19..b92fffbe761f 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -840,14 +840,6 @@ void choose_random_location(unsigned long input, return; } -#ifdef CONFIG_X86_5LEVEL - if (__read_cr4() & X86_CR4_LA57) { - __pgtable_l5_enabled = 1; - pgdir_shift = 48; - ptrs_per_p4d = 512; - } -#endif - boot_params->hdr.loadflags |= KASLR_FLAG; if (IS_ENABLED(CONFIG_X86_32)) diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c index 7d0394f4ebf9..5def1674d6f1 100644 --- a/arch/x86/boot/compressed/pgtable_64.c +++ b/arch/x86/boot/compressed/pgtable_64.c @@ -8,6 +8,13 @@ #define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */ +#ifdef CONFIG_X86_5LEVEL +/* __pgtable_l5_enabled needs to be in .data to avoid being cleared along with .bss */ +unsigned int __section(.data) __pgtable_l5_enabled; +unsigned int __section(.data) pgdir_shift = 39; +unsigned int __section(.data) ptrs_per_p4d = 1; +#endif + struct paging_config { unsigned long trampoline_start; unsigned long l5_required; @@ -198,4 +205,13 @@ void cleanup_trampoline(void *pgtable) /* Restore trampoline memory */ memcpy(trampoline_32bit, trampoline_save, TRAMPOLINE_32BIT_SIZE); + + /* Initialize variables for 5-level paging */ +#ifdef CONFIG_X86_5LEVEL + if (__read_cr4() & X86_CR4_LA57) { + __pgtable_l5_enabled = 1; + pgdir_shift = 48; + ptrs_per_p4d = 512; + } +#endif } |