Skip to content

Commit 05ab1d8

Browse files
ftang1KAGA-KOKO
authored andcommitted
x86/mm: Expand static page table for fixmap space
We met a kernel panic when enabling earlycon, which is due to the fixmap address of earlycon is not statically setup. Currently the static fixmap setup in head_64.S only covers 2M virtual address space, while it actually could be in 4M space with different kernel configurations, e.g. when VSYSCALL emulation is disabled. So increase the static space to 4M for now by defining FIXMAP_PMD_NUM to 2, and add a build time check to ensure that the fixmap is covered by the initial static page tables. Fixes: 1ad83c8 ("x86_64,vsyscall: Make vsyscall emulation configurable") Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Feng Tang <feng.tang@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: kernel test robot <rong.a.chen@intel.com> Reviewed-by: Juergen Gross <jgross@suse.com> (Xen parts) Cc: H Peter Anvin <hpa@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Andy Lutomirsky <luto@kernel.org> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180920025828.23699-1-feng.tang@intel.com
1 parent 9068a42 commit 05ab1d8

File tree

6 files changed

+42
-8
lines changed

6 files changed

+42
-8
lines changed

arch/x86/include/asm/fixmap.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
#ifndef _ASM_X86_FIXMAP_H
1515
#define _ASM_X86_FIXMAP_H
1616

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+
1727
#ifndef __ASSEMBLY__
1828
#include <linux/kernel.h>
1929
#include <asm/acpi.h>

arch/x86/include/asm/pgtable_64.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/processor.h>
1515
#include <linux/bitops.h>
1616
#include <linux/threads.h>
17+
#include <asm/fixmap.h>
1718

1819
extern p4d_t level4_kernel_pgt[512];
1920
extern p4d_t level4_ident_pgt[512];
@@ -22,7 +23,7 @@ extern pud_t level3_ident_pgt[512];
2223
extern pmd_t level2_kernel_pgt[512];
2324
extern pmd_t level2_fixmap_pgt[512];
2425
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];
2627
extern pgd_t init_top_pgt[];
2728

2829
#define swapper_pg_dir init_top_pgt

arch/x86/kernel/head64.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <asm/bootparam_utils.h>
3636
#include <asm/microcode.h>
3737
#include <asm/kasan.h>
38+
#include <asm/fixmap.h>
3839

3940
/*
4041
* Manage page tables very early on.
@@ -166,7 +167,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
166167
pud[511] += load_delta;
167168

168169
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;
170172

171173
/*
172174
* Set up the identity mapping for the switchover. These

arch/x86/kernel/head_64.S

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "../entry/calling.h"
2525
#include <asm/export.h>
2626
#include <asm/nospec-branch.h>
27+
#include <asm/fixmap.h>
2728

2829
#ifdef CONFIG_PARAVIRT
2930
#include <asm/asm-offsets.h>
@@ -445,13 +446,20 @@ NEXT_PAGE(level2_kernel_pgt)
445446
KERNEL_IMAGE_SIZE/PMD_SIZE)
446447

447448
NEXT_PAGE(level2_fixmap_pgt)
448-
.fill 506,8,0
449-
.quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
450-
/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
451-
.fill 5,8,0
449+
.fill (512 - 4 - FIXMAP_PMD_NUM),8,0
450+
pgtno = 0
451+
.rept (FIXMAP_PMD_NUM)
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
452458

453459
NEXT_PAGE(level1_fixmap_pgt)
460+
.rept (FIXMAP_PMD_NUM)
454461
.fill 512,8,0
462+
.endr
455463

456464
#undef PMDS
457465

arch/x86/mm/pgtable.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,15 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
637637
{
638638
unsigned long address = __fix_to_virt(idx);
639639

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+
640649
if (idx >= __end_of_fixed_addresses) {
641650
BUG();
642651
return;

arch/x86/xen/mmu_pv.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
19071907
/* L3_k[511] -> level2_fixmap_pgt */
19081908
convert_pfn_mfn(level3_kernel_pgt);
19091909

1910-
/* L3_k[511][506] -> level1_fixmap_pgt */
1910+
/* L3_k[511][508-FIXMAP_PMD_NUM ... 507] -> level1_fixmap_pgt */
19111911
convert_pfn_mfn(level2_fixmap_pgt);
19121912

19131913
/* 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)
19521952
set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
19531953
set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
19541954
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+
}
19561960

19571961
/* Pin down new L4 */
19581962
pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,

0 commit comments

Comments
 (0)