lkml.org 
[lkml]   [2019]   [Feb]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 005/305] x86/mm: Fix regression with huge pages on PAE
    3.16.63-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>

    commit 70f1528747651b20c7769d3516ade369f9963237 upstream.

    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: f70abb0fc3da ("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>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    arch/x86/boot/boot.h | 1 -
    arch/x86/boot/video-mode.c | 2 ++
    arch/x86/boot/video.c | 2 ++
    arch/x86/include/asm/page_types.h | 16 +++++++++-------
    arch/x86/include/asm/pgtable_types.h | 14 ++++----------
    arch/x86/include/asm/x86_init.h | 1 -
    6 files changed, 17 insertions(+), 19 deletions(-)

    --- a/arch/x86/boot/boot.h
    +++ b/arch/x86/boot/boot.h
    @@ -23,7 +23,6 @@
    #include <stdarg.h>
    #include <linux/types.h>
    #include <linux/edd.h>
    -#include <asm/boot.h>
    #include <asm/setup.h>
    #include "bitops.h"
    #include "ctype.h"
    --- a/arch/x86/boot/video-mode.c
    +++ b/arch/x86/boot/video-mode.c
    @@ -19,6 +19,8 @@
    #include "video.h"
    #include "vesa.h"

    +#include <uapi/asm/boot.h>
    +
    /*
    * Common variables
    */
    --- a/arch/x86/boot/video.c
    +++ b/arch/x86/boot/video.c
    @@ -13,6 +13,8 @@
    * Select video mode
    */

    +#include <uapi/asm/boot.h>
    +
    #include "boot.h"
    #include "video.h"
    #include "vesa.h"
    --- a/arch/x86/include/asm/page_types.h
    +++ b/arch/x86/include/asm/page_types.h
    @@ -9,19 +9,21 @@
    #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
    #define PAGE_MASK (~(PAGE_SIZE-1))

    +#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
    +#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
    +
    +#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
    +#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
    +
    #define __PHYSICAL_MASK ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
    #define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)

    -/* Cast PAGE_MASK to a signed type so that it is sign-extended if
    +/* Cast *PAGE_MASK to a signed type so that it is sign-extended if
    virtual addresses are 32-bits but physical addresses are larger
    (ie, 32-bit PAE). */
    #define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
    -
    -#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
    -#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
    -
    -#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
    -#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
    +#define PHYSICAL_PMD_PAGE_MASK (((signed long)PMD_PAGE_MASK) & __PHYSICAL_MASK)
    +#define PHYSICAL_PUD_PAGE_MASK (((signed long)PUD_PAGE_MASK) & __PHYSICAL_MASK)

    #define HPAGE_SHIFT PMD_SHIFT
    #define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
    --- a/arch/x86/include/asm/pgtable_types.h
    +++ b/arch/x86/include/asm/pgtable_types.h
    @@ -332,17 +332,14 @@ static inline pmdval_t native_pmd_val(pm
    static inline pudval_t pud_pfn_mask(pud_t pud)
    {
    if (native_pud_val(pud) & _PAGE_PSE)
    - return PUD_PAGE_MASK & PHYSICAL_PAGE_MASK;
    + return PHYSICAL_PUD_PAGE_MASK;
    else
    return PTE_PFN_MASK;
    }

    static inline pudval_t pud_flags_mask(pud_t pud)
    {
    - if (native_pud_val(pud) & _PAGE_PSE)
    - return ~(PUD_PAGE_MASK & (pudval_t)PHYSICAL_PAGE_MASK);
    - else
    - return ~PTE_PFN_MASK;
    + return ~pud_pfn_mask(pud);
    }

    static inline pudval_t pud_flags(pud_t pud)
    @@ -353,17 +350,14 @@ static inline pudval_t pud_flags(pud_t p
    static inline pmdval_t pmd_pfn_mask(pmd_t pmd)
    {
    if (native_pmd_val(pmd) & _PAGE_PSE)
    - return PMD_PAGE_MASK & PHYSICAL_PAGE_MASK;
    + return PHYSICAL_PMD_PAGE_MASK;
    else
    return PTE_PFN_MASK;
    }

    static inline pmdval_t pmd_flags_mask(pmd_t pmd)
    {
    - if (native_pmd_val(pmd) & _PAGE_PSE)
    - return ~(PMD_PAGE_MASK & (pmdval_t)PHYSICAL_PAGE_MASK);
    - else
    - return ~PTE_PFN_MASK;
    + return ~pmd_pfn_mask(pmd);
    }

    static inline pmdval_t pmd_flags(pmd_t pmd)
    --- a/arch/x86/include/asm/x86_init.h
    +++ b/arch/x86/include/asm/x86_init.h
    @@ -1,7 +1,6 @@
    #ifndef _ASM_X86_PLATFORM_H
    #define _ASM_X86_PLATFORM_H

    -#include <asm/pgtable_types.h>
    #include <asm/bootparam.h>

    struct mpc_bus;
    \
     
     \ /
      Last update: 2019-02-03 15:03    [W:4.021 / U:0.248 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site