diff options
| -rw-r--r-- | arch/x86/include/asm/fixmap.h | 10 | ||||
| -rw-r--r-- | arch/x86/include/asm/pgtable_64.h | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/head64.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/head_64.S | 16 | ||||
| -rw-r--r-- | arch/x86/mm/pgtable.c | 9 | ||||
| -rw-r--r-- | arch/x86/xen/mmu_pv.c | 8 |
6 files changed, 42 insertions, 8 deletions
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index e203169931c7..6390bd8c141b 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
| @@ -14,6 +14,16 @@ | |||
| 14 | #ifndef _ASM_X86_FIXMAP_H | 14 | #ifndef _ASM_X86_FIXMAP_H |
| 15 | #define _ASM_X86_FIXMAP_H | 15 | #define _ASM_X86_FIXMAP_H |
| 16 | 16 | ||
| 17 | /* | ||
| 18 | * Exposed to assembly code for setting up initial page tables. Cannot be | ||
| 19 | * calculated in assembly code (fixmap entries are an enum), but is sanity | ||
| 20 | * checked in the actual fixmap C code to make sure that the fixmap is | ||
| 21 | * covered fully. | ||
| 22 | */ | ||
| 23 | #define FIXMAP_PMD_NUM 2 | ||
| 24 | /* fixmap starts downwards from the 507th entry in level2_fixmap_pgt */ | ||
| 25 | #define FIXMAP_PMD_TOP 507 | ||
| 26 | |||
| 17 | #ifndef __ASSEMBLY__ | 27 | #ifndef __ASSEMBLY__ |
| 18 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 19 | #include <asm/acpi.h> | 29 | #include <asm/acpi.h> |
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index ce2b59047cb8..9c85b54bf03c 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
| 15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
| 16 | #include <linux/threads.h> | 16 | #include <linux/threads.h> |
| 17 | #include <asm/fixmap.h> | ||
| 17 | 18 | ||
| 18 | extern p4d_t level4_kernel_pgt[512]; | 19 | extern p4d_t level4_kernel_pgt[512]; |
| 19 | extern p4d_t level4_ident_pgt[512]; | 20 | extern p4d_t level4_ident_pgt[512]; |
| @@ -22,7 +23,7 @@ extern pud_t level3_ident_pgt[512]; | |||
| 22 | extern pmd_t level2_kernel_pgt[512]; | 23 | extern pmd_t level2_kernel_pgt[512]; |
| 23 | extern pmd_t level2_fixmap_pgt[512]; | 24 | extern pmd_t level2_fixmap_pgt[512]; |
| 24 | extern pmd_t level2_ident_pgt[512]; | 25 | extern pmd_t level2_ident_pgt[512]; |
| 25 | extern pte_t level1_fixmap_pgt[512]; | 26 | extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; |
| 26 | extern pgd_t init_top_pgt[]; | 27 | extern pgd_t init_top_pgt[]; |
| 27 | 28 | ||
| 28 | #define swapper_pg_dir init_top_pgt | 29 | #define swapper_pg_dir init_top_pgt |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index c16af27eb23f..ddee1f0870c4 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <asm/bootparam_utils.h> | 35 | #include <asm/bootparam_utils.h> |
| 36 | #include <asm/microcode.h> | 36 | #include <asm/microcode.h> |
| 37 | #include <asm/kasan.h> | 37 | #include <asm/kasan.h> |
| 38 | #include <asm/fixmap.h> | ||
| 38 | 39 | ||
| 39 | /* | 40 | /* |
| 40 | * Manage page tables very early on. | 41 | * Manage page tables very early on. |
| @@ -166,7 +167,8 @@ unsigned long __head __startup_64(unsigned long physaddr, | |||
| 166 | pud[511] += load_delta; | 167 | pud[511] += load_delta; |
| 167 | 168 | ||
| 168 | pmd = fixup_pointer(level2_fixmap_pgt, physaddr); | 169 | pmd = fixup_pointer(level2_fixmap_pgt, physaddr); |
| 169 | pmd[506] += load_delta; | 170 | for (i = FIXMAP_PMD_TOP; i > FIXMAP_PMD_TOP - FIXMAP_PMD_NUM; i--) |
| 171 | pmd[i] += load_delta; | ||
| 170 | 172 | ||
| 171 | /* | 173 | /* |
| 172 | * Set up the identity mapping for the switchover. These | 174 | * Set up the identity mapping for the switchover. These |
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 15ebc2fc166e..a3618cf04cf6 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "../entry/calling.h" | 24 | #include "../entry/calling.h" |
| 25 | #include <asm/export.h> | 25 | #include <asm/export.h> |
| 26 | #include <asm/nospec-branch.h> | 26 | #include <asm/nospec-branch.h> |
| 27 | #include <asm/fixmap.h> | ||
| 27 | 28 | ||
| 28 | #ifdef CONFIG_PARAVIRT | 29 | #ifdef CONFIG_PARAVIRT |
| 29 | #include <asm/asm-offsets.h> | 30 | #include <asm/asm-offsets.h> |
| @@ -445,13 +446,20 @@ NEXT_PAGE(level2_kernel_pgt) | |||
| 445 | KERNEL_IMAGE_SIZE/PMD_SIZE) | 446 | KERNEL_IMAGE_SIZE/PMD_SIZE) |
| 446 | 447 | ||
| 447 | NEXT_PAGE(level2_fixmap_pgt) | 448 | NEXT_PAGE(level2_fixmap_pgt) |
| 448 | .fill 506,8,0 | 449 | .fill (512 - 4 - FIXMAP_PMD_NUM),8,0 |
| 449 | .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC | 450 | pgtno = 0 |
| 450 | /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ | 451 | .rept (FIXMAP_PMD_NUM) |
| 451 | .fill 5,8,0 | 452 | .quad level1_fixmap_pgt + (pgtno << PAGE_SHIFT) - __START_KERNEL_map \ |
| 453 | + _PAGE_TABLE_NOENC; | ||
| 454 | pgtno = pgtno + 1 | ||
| 455 | .endr | ||
| 456 | /* 6 MB reserved space + a 2MB hole */ | ||
| 457 | .fill 4,8,0 | ||
| 452 | 458 | ||
| 453 | NEXT_PAGE(level1_fixmap_pgt) | 459 | NEXT_PAGE(level1_fixmap_pgt) |
| 460 | .rept (FIXMAP_PMD_NUM) | ||
| 454 | .fill 512,8,0 | 461 | .fill 512,8,0 |
| 462 | .endr | ||
| 455 | 463 | ||
| 456 | #undef PMDS | 464 | #undef PMDS |
| 457 | 465 | ||
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index ae394552fb94..089e78c4effd 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
| @@ -637,6 +637,15 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte) | |||
| 637 | { | 637 | { |
| 638 | unsigned long address = __fix_to_virt(idx); | 638 | unsigned long address = __fix_to_virt(idx); |
| 639 | 639 | ||
| 640 | #ifdef CONFIG_X86_64 | ||
| 641 | /* | ||
| 642 | * Ensure that the static initial page tables are covering the | ||
| 643 | * fixmap completely. | ||
| 644 | */ | ||
| 645 | BUILD_BUG_ON(__end_of_permanent_fixed_addresses > | ||
| 646 | (FIXMAP_PMD_NUM * PTRS_PER_PTE)); | ||
| 647 | #endif | ||
| 648 | |||
| 640 | if (idx >= __end_of_fixed_addresses) { | 649 | if (idx >= __end_of_fixed_addresses) { |
| 641 | BUG(); | 650 | BUG(); |
| 642 | return; | 651 | return; |
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 2fe5c9b1816b..dd461c0167ef 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c | |||
| @@ -1907,7 +1907,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) | |||
| 1907 | /* L3_k[511] -> level2_fixmap_pgt */ | 1907 | /* L3_k[511] -> level2_fixmap_pgt */ |
| 1908 | convert_pfn_mfn(level3_kernel_pgt); | 1908 | convert_pfn_mfn(level3_kernel_pgt); |
| 1909 | 1909 | ||
| 1910 | /* L3_k[511][506] -> level1_fixmap_pgt */ | 1910 | /* L3_k[511][508-FIXMAP_PMD_NUM ... 507] -> level1_fixmap_pgt */ |
| 1911 | convert_pfn_mfn(level2_fixmap_pgt); | 1911 | convert_pfn_mfn(level2_fixmap_pgt); |
| 1912 | 1912 | ||
| 1913 | /* We get [511][511] and have Xen's version of level2_kernel_pgt */ | 1913 | /* We get [511][511] and have Xen's version of level2_kernel_pgt */ |
| @@ -1952,7 +1952,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) | |||
| 1952 | set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); | 1952 | set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); |
| 1953 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); | 1953 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); |
| 1954 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); | 1954 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); |
| 1955 | set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO); | 1955 | |
| 1956 | for (i = 0; i < FIXMAP_PMD_NUM; i++) { | ||
| 1957 | set_page_prot(level1_fixmap_pgt + i * PTRS_PER_PTE, | ||
| 1958 | PAGE_KERNEL_RO); | ||
| 1959 | } | ||
| 1956 | 1960 | ||
| 1957 | /* Pin down new L4 */ | 1961 | /* Pin down new L4 */ |
| 1958 | pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, | 1962 | pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, |
