115 lines
4.1 KiB
Diff
115 lines
4.1 KiB
Diff
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
|
|
Date: Fri, 30 Nov 2018 23:23:27 +0300
|
|
Subject: x86/mm: Fix guard hole handling
|
|
Origin: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?id=16877a5570e0c5f4270d5b17f9bab427bcae9514
|
|
|
|
There is a guard hole at the beginning of the kernel address space, also
|
|
used by hypervisors. It occupies 16 PGD entries.
|
|
|
|
This reserved range is not defined explicitely, it is calculated relative
|
|
to other entities: direct mapping and user space ranges.
|
|
|
|
The calculation got broken by recent changes of the kernel memory layout:
|
|
LDT remap range is now mapped before direct mapping and makes the
|
|
calculation invalid.
|
|
|
|
The breakage leads to crash on Xen dom0 boot[1].
|
|
|
|
Define the reserved range explicitely. It's part of kernel ABI (hypervisors
|
|
expect it to be stable) and must not depend on changes in the rest of
|
|
kernel memory layout.
|
|
|
|
[1] https://lists.xenproject.org/archives/html/xen-devel/2018-11/msg03313.html
|
|
|
|
Fixes: d52888aa2753 ("x86/mm: Move LDT remap out of KASLR region on 5-level paging")
|
|
Reported-by: Hans van Kranenburg <hans.van.kranenburg@mendix.com>
|
|
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Tested-by: Hans van Kranenburg <hans.van.kranenburg@mendix.com>
|
|
Reviewed-by: Juergen Gross <jgross@suse.com>
|
|
Cc: bp@alien8.de
|
|
Cc: hpa@zytor.com
|
|
Cc: dave.hansen@linux.intel.com
|
|
Cc: luto@kernel.org
|
|
Cc: peterz@infradead.org
|
|
Cc: boris.ostrovsky@oracle.com
|
|
Cc: bhe@redhat.com
|
|
Cc: linux-mm@kvack.org
|
|
Cc: xen-devel@lists.xenproject.org
|
|
Link: https://lkml.kernel.org/r/20181130202328.65359-2-kirill.shutemov@linux.intel.com
|
|
---
|
|
arch/x86/include/asm/pgtable_64_types.h | 5 +++++
|
|
arch/x86/mm/dump_pagetables.c | 8 ++++----
|
|
arch/x86/xen/mmu_pv.c | 11 ++++++-----
|
|
3 files changed, 15 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
|
|
index 84bd9bdc1987..88bca456da99 100644
|
|
--- a/arch/x86/include/asm/pgtable_64_types.h
|
|
+++ b/arch/x86/include/asm/pgtable_64_types.h
|
|
@@ -111,6 +111,11 @@ extern unsigned int ptrs_per_p4d;
|
|
*/
|
|
#define MAXMEM (1UL << MAX_PHYSMEM_BITS)
|
|
|
|
+#define GUARD_HOLE_PGD_ENTRY -256UL
|
|
+#define GUARD_HOLE_SIZE (16UL << PGDIR_SHIFT)
|
|
+#define GUARD_HOLE_BASE_ADDR (GUARD_HOLE_PGD_ENTRY << PGDIR_SHIFT)
|
|
+#define GUARD_HOLE_END_ADDR (GUARD_HOLE_BASE_ADDR + GUARD_HOLE_SIZE)
|
|
+
|
|
#define LDT_PGD_ENTRY -240UL
|
|
#define LDT_BASE_ADDR (LDT_PGD_ENTRY << PGDIR_SHIFT)
|
|
#define LDT_END_ADDR (LDT_BASE_ADDR + PGDIR_SIZE)
|
|
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
|
|
index fc37bbd23eb8..dad153e5a427 100644
|
|
--- a/arch/x86/mm/dump_pagetables.c
|
|
+++ b/arch/x86/mm/dump_pagetables.c
|
|
@@ -512,11 +512,11 @@ static inline bool is_hypervisor_range(int idx)
|
|
{
|
|
#ifdef CONFIG_X86_64
|
|
/*
|
|
- * ffff800000000000 - ffff87ffffffffff is reserved for
|
|
- * the hypervisor.
|
|
+ * A hole in the beginning of kernel address space reserved
|
|
+ * for a hypervisor.
|
|
*/
|
|
- return (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
|
|
- (idx < pgd_index(__PAGE_OFFSET));
|
|
+ return (idx >= pgd_index(GUARD_HOLE_BASE_ADDR)) &&
|
|
+ (idx < pgd_index(GUARD_HOLE_END_ADDR));
|
|
#else
|
|
return false;
|
|
#endif
|
|
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
|
|
index a5d7ed125337..0f4fe206dcc2 100644
|
|
--- a/arch/x86/xen/mmu_pv.c
|
|
+++ b/arch/x86/xen/mmu_pv.c
|
|
@@ -648,19 +648,20 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
|
|
unsigned long limit)
|
|
{
|
|
int i, nr, flush = 0;
|
|
- unsigned hole_low, hole_high;
|
|
+ unsigned hole_low = 0, hole_high = 0;
|
|
|
|
/* The limit is the last byte to be touched */
|
|
limit--;
|
|
BUG_ON(limit >= FIXADDR_TOP);
|
|
|
|
+#ifdef CONFIG_X86_64
|
|
/*
|
|
* 64-bit has a great big hole in the middle of the address
|
|
- * space, which contains the Xen mappings. On 32-bit these
|
|
- * will end up making a zero-sized hole and so is a no-op.
|
|
+ * space, which contains the Xen mappings.
|
|
*/
|
|
- hole_low = pgd_index(USER_LIMIT);
|
|
- hole_high = pgd_index(PAGE_OFFSET);
|
|
+ hole_low = pgd_index(GUARD_HOLE_BASE_ADDR);
|
|
+ hole_high = pgd_index(GUARD_HOLE_END_ADDR);
|
|
+#endif
|
|
|
|
nr = pgd_index(limit) + 1;
|
|
for (i = 0; i < nr; i++) {
|
|
--
|
|
2.19.2
|
|
|