Skip to content

Commit e3e2881

Browse files
joergroedelIngo Molnar
authored andcommitted
x86/pgtable: Don't set huge PUD/PMD on non-leaf entries
The pmd_set_huge() and pud_set_huge() functions are used from the generic ioremap() code to establish large mappings where this is possible. But the generic ioremap() code does not check whether the PMD/PUD entries are already populated with a non-leaf entry, so that any page-table pages these entries point to will be lost. Further, on x86-32 with SHARED_KERNEL_PMD=0, this causes a BUG_ON() in vmalloc_sync_one() when PMD entries are synced from swapper_pg_dir to the current page-table. This happens because the PMD entry from swapper_pg_dir was promoted to a huge-page entry while the current PGD still contains the non-leaf entry. Because both entries are present and point to a different page, the BUG_ON() triggers. This was actually triggered with pti-x32 enabled in a KVM virtual machine by the graphics driver. A real and better fix for that would be to improve the page-table handling in the generic ioremap() code. But that is out-of-scope for this patch-set and left for later work. Reported-by: David H. Gutteridge <[email protected]> Signed-off-by: Joerg Roedel <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Laight <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: Eduardo Valentin <[email protected]> Cc: Greg KH <[email protected]> Cc: Jiri Kosina <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Juergen Gross <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Pavel Machek <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Waiman Long <[email protected]> Cc: Will Deacon <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 8c06c77 commit e3e2881

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

arch/x86/mm/pgtable.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/mm.h>
33
#include <linux/gfp.h>
4+
#include <linux/hugetlb.h>
45
#include <asm/pgalloc.h>
56
#include <asm/pgtable.h>
67
#include <asm/tlb.h>
@@ -639,6 +640,10 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
639640
(mtrr != MTRR_TYPE_WRBACK))
640641
return 0;
641642

643+
/* Bail out if we are we on a populated non-leaf entry: */
644+
if (pud_present(*pud) && !pud_huge(*pud))
645+
return 0;
646+
642647
prot = pgprot_4k_2_large(prot);
643648

644649
set_pte((pte_t *)pud, pfn_pte(
@@ -667,6 +672,10 @@ int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
667672
return 0;
668673
}
669674

675+
/* Bail out if we are we on a populated non-leaf entry: */
676+
if (pmd_present(*pmd) && !pmd_huge(*pmd))
677+
return 0;
678+
670679
prot = pgprot_4k_2_large(prot);
671680

672681
set_pte((pte_t *)pmd, pfn_pte(

0 commit comments

Comments
 (0)