lkml.org 
[lkml]   [2016]   [Mar]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 35/50] x86/mm: Fix slow_virt_to_phys() for X86_PAE again
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Dexuan Cui <decui@microsoft.com>

    commit bf70e5513dfea29c3682e7eb3dbb45f0723bac09 upstream.

    "d1cd12108346: x86, pageattr: Prevent overflow in slow_virt_to_phys() for
    X86_PAE" was unintentionally removed by the recent "34437e67a672: x86/mm: Fix
    slow_virt_to_phys() to handle large PAT bit".

    And, the variable 'phys_addr' was defined as "unsigned long" by mistake -- it should
    be "phys_addr_t".

    As a result, Hyper-V network driver in 32-PAE Linux guest can't work again.

    Fixes: commit 34437e67a672: "x86/mm: Fix slow_virt_to_phys() to handle large PAT bit"
    Signed-off-by: Dexuan Cui <decui@microsoft.com>
    Reviewed-by: Toshi Kani <toshi.kani@hpe.com>
    Cc: olaf@aepfle.de
    Cc: jasowang@redhat.com
    Cc: driverdev-devel@linuxdriverproject.org
    Cc: linux-mm@kvack.org
    Cc: apw@canonical.com
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: K. Y. Srinivasan <kys@microsoft.com>
    Cc: Haiyang Zhang <haiyangz@microsoft.com>
    Link: http://lkml.kernel.org/r/1456394292-9030-1-git-send-email-decui@microsoft.com
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/mm/pageattr.c | 14 ++++++++++----
    1 file changed, 10 insertions(+), 4 deletions(-)

    --- a/arch/x86/mm/pageattr.c
    +++ b/arch/x86/mm/pageattr.c
    @@ -414,24 +414,30 @@ pmd_t *lookup_pmd_address(unsigned long
    phys_addr_t slow_virt_to_phys(void *__virt_addr)
    {
    unsigned long virt_addr = (unsigned long)__virt_addr;
    - unsigned long phys_addr, offset;
    + phys_addr_t phys_addr;
    + unsigned long offset;
    enum pg_level level;
    pte_t *pte;

    pte = lookup_address(virt_addr, &level);
    BUG_ON(!pte);

    + /*
    + * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t
    + * before being left-shifted PAGE_SHIFT bits -- this trick is to
    + * make 32-PAE kernel work correctly.
    + */
    switch (level) {
    case PG_LEVEL_1G:
    - phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
    + phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
    offset = virt_addr & ~PUD_PAGE_MASK;
    break;
    case PG_LEVEL_2M:
    - phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
    + phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
    offset = virt_addr & ~PMD_PAGE_MASK;
    break;
    default:
    - phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
    + phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
    offset = virt_addr & ~PAGE_MASK;
    }


    \
     
     \ /
      Last update: 2016-03-14 19:41    [W:6.721 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site