Skip to content

Commit 70f1528

Browse files
kirylingomolnar
authored andcommitted
x86/mm: Fix regression with huge pages on PAE
Recent PAT patchset has caused issue on 32-bit PAE machines: page:eea45000 count:0 mapcount:-128 mapping: (null) index:0x0 flags: 0x40000000() page dumped because: VM_BUG_ON_PAGE(page_mapcount(page) < 0) ------------[ cut here ]------------ kernel BUG at /home/build/linux-boris/mm/huge_memory.c:1485! invalid opcode: 0000 [#1] SMP [...] Call Trace: unmap_single_vma ? __wake_up unmap_vmas unmap_region do_munmap vm_munmap SyS_munmap do_fast_syscall_32 ? __do_page_fault sysenter_past_esp Code: ... EIP: [<c11bde80>] zap_huge_pmd+0x240/0x260 SS:ESP 0068:f6459d98 The problem is in pmd_pfn_mask() and pmd_flags_mask(). These helpers use PMD_PAGE_MASK to calculate resulting mask. PMD_PAGE_MASK is 'unsigned long', not 'unsigned long long' as phys_addr_t is on 32-bit PAE (ARCH_PHYS_ADDR_T_64BIT). As a result, the upper bits of resulting mask get truncated. pud_pfn_mask() and pud_flags_mask() aren't problematic since we don't have PUD page table level on 32-bit systems, but it's reasonable to keep them consistent with PMD counterpart. Introduce PHYSICAL_PMD_PAGE_MASK and PHYSICAL_PUD_PAGE_MASK in addition to existing PHYSICAL_PAGE_MASK and reworks helpers to use them. Reported-and-Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> [ Fix -Woverflow warnings from the realmode code. ] Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Toshi Kani <toshi.kani@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jürgen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: linux-mm <linux-mm@kvack.org> Fixes: f70abb0 ("x86/asm: Fix pud/pmd interfaces to handle large PAT bit") Link: http://lkml.kernel.org/r/1448878233-11390-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 656279a commit 70f1528

6 files changed

Lines changed: 17 additions & 19 deletions

File tree

arch/x86/boot/boot.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <stdarg.h>
2424
#include <linux/types.h>
2525
#include <linux/edd.h>
26-
#include <asm/boot.h>
2726
#include <asm/setup.h>
2827
#include "bitops.h"
2928
#include "ctype.h"

arch/x86/boot/video-mode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "video.h"
2020
#include "vesa.h"
2121

22+
#include <uapi/asm/boot.h>
23+
2224
/*
2325
* Common variables
2426
*/

arch/x86/boot/video.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* Select video mode
1414
*/
1515

16+
#include <uapi/asm/boot.h>
17+
1618
#include "boot.h"
1719
#include "video.h"
1820
#include "vesa.h"

arch/x86/include/asm/page_types.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@
99
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
1010
#define PAGE_MASK (~(PAGE_SIZE-1))
1111

12+
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
13+
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
14+
15+
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
16+
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
17+
1218
#define __PHYSICAL_MASK ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
1319
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
1420

15-
/* Cast PAGE_MASK to a signed type so that it is sign-extended if
21+
/* Cast *PAGE_MASK to a signed type so that it is sign-extended if
1622
virtual addresses are 32-bits but physical addresses are larger
1723
(ie, 32-bit PAE). */
1824
#define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
19-
20-
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
21-
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
22-
23-
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
24-
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
25+
#define PHYSICAL_PMD_PAGE_MASK (((signed long)PMD_PAGE_MASK) & __PHYSICAL_MASK)
26+
#define PHYSICAL_PUD_PAGE_MASK (((signed long)PUD_PAGE_MASK) & __PHYSICAL_MASK)
2527

2628
#define HPAGE_SHIFT PMD_SHIFT
2729
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)

arch/x86/include/asm/pgtable_types.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,17 +279,14 @@ static inline pmdval_t native_pmd_val(pmd_t pmd)
279279
static inline pudval_t pud_pfn_mask(pud_t pud)
280280
{
281281
if (native_pud_val(pud) & _PAGE_PSE)
282-
return PUD_PAGE_MASK & PHYSICAL_PAGE_MASK;
282+
return PHYSICAL_PUD_PAGE_MASK;
283283
else
284284
return PTE_PFN_MASK;
285285
}
286286

287287
static inline pudval_t pud_flags_mask(pud_t pud)
288288
{
289-
if (native_pud_val(pud) & _PAGE_PSE)
290-
return ~(PUD_PAGE_MASK & (pudval_t)PHYSICAL_PAGE_MASK);
291-
else
292-
return ~PTE_PFN_MASK;
289+
return ~pud_pfn_mask(pud);
293290
}
294291

295292
static inline pudval_t pud_flags(pud_t pud)
@@ -300,17 +297,14 @@ static inline pudval_t pud_flags(pud_t pud)
300297
static inline pmdval_t pmd_pfn_mask(pmd_t pmd)
301298
{
302299
if (native_pmd_val(pmd) & _PAGE_PSE)
303-
return PMD_PAGE_MASK & PHYSICAL_PAGE_MASK;
300+
return PHYSICAL_PMD_PAGE_MASK;
304301
else
305302
return PTE_PFN_MASK;
306303
}
307304

308305
static inline pmdval_t pmd_flags_mask(pmd_t pmd)
309306
{
310-
if (native_pmd_val(pmd) & _PAGE_PSE)
311-
return ~(PMD_PAGE_MASK & (pmdval_t)PHYSICAL_PAGE_MASK);
312-
else
313-
return ~PTE_PFN_MASK;
307+
return ~pmd_pfn_mask(pmd);
314308
}
315309

316310
static inline pmdval_t pmd_flags(pmd_t pmd)

arch/x86/include/asm/x86_init.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifndef _ASM_X86_PLATFORM_H
22
#define _ASM_X86_PLATFORM_H
33

4-
#include <asm/pgtable_types.h>
54
#include <asm/bootparam.h>
65

76
struct mpc_bus;

0 commit comments

Comments
 (0)