lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 761/800] powerpc/64s: fix hash page fault interrupt handler
    Date
    From: Nicholas Piggin <npiggin@gmail.com>

    [ Upstream commit 5567b1ee29b7a83e8c01d99d34b5bbd306ce0bcf ]

    The early bad fault or key fault test in do_hash_fault() ends up calling
    into ___do_page_fault without having gone through an interrupt handler
    wrapper (except the initial _RAW one). This can end up calling local irq
    functions while the interrupt has not been reconciled, which will likely
    cause crashes and it trips up on a later patch that adds more assertions.

    pkey_exec_prot from selftests causes this path to be executed.

    There is no real reason to run the in_nmi() test should be performed
    before the key fault check. In fact if a perf interrupt in the hash
    fault code did a stack walk that was made to take a key fault somehow
    then running ___do_page_fault could possibly cause another hash fault
    causing problems. Move the in_nmi() test first, and then do everything
    else inside the regular interrupt handler function.

    Fixes: 3a96570ffceb ("powerpc: convert interrupt handlers to use wrappers")
    Reported-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
    Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
    Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
    Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
    Link: https://lore.kernel.org/r/20210630074621.2109197-2-npiggin@gmail.com
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    arch/powerpc/mm/book3s64/hash_utils.c | 24 +++++++++++-------------
    1 file changed, 11 insertions(+), 13 deletions(-)

    diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
    index 96d9aa164007..ac5720371c0d 100644
    --- a/arch/powerpc/mm/book3s64/hash_utils.c
    +++ b/arch/powerpc/mm/book3s64/hash_utils.c
    @@ -1522,8 +1522,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
    }
    EXPORT_SYMBOL_GPL(hash_page);

    -DECLARE_INTERRUPT_HANDLER_RET(__do_hash_fault);
    -DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
    +DECLARE_INTERRUPT_HANDLER(__do_hash_fault);
    +DEFINE_INTERRUPT_HANDLER(__do_hash_fault)
    {
    unsigned long ea = regs->dar;
    unsigned long dsisr = regs->dsisr;
    @@ -1533,6 +1533,11 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
    unsigned int region_id;
    long err;

    + if (unlikely(dsisr & (DSISR_BAD_FAULT_64S | DSISR_KEYFAULT))) {
    + hash__do_page_fault(regs);
    + return;
    + }
    +
    region_id = get_region_id(ea);
    if ((region_id == VMALLOC_REGION_ID) || (region_id == IO_REGION_ID))
    mm = &init_mm;
    @@ -1571,9 +1576,10 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
    bad_page_fault(regs, SIGBUS);
    }
    err = 0;
    - }

    - return err;
    + } else if (err) {
    + hash__do_page_fault(regs);
    + }
    }

    /*
    @@ -1582,13 +1588,6 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
    */
    DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault)
    {
    - unsigned long dsisr = regs->dsisr;
    -
    - if (unlikely(dsisr & (DSISR_BAD_FAULT_64S | DSISR_KEYFAULT))) {
    - hash__do_page_fault(regs);
    - return 0;
    - }
    -
    /*
    * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then
    * don't call hash_page, just fail the fault. This is required to
    @@ -1607,8 +1606,7 @@ DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault)
    return 0;
    }

    - if (__do_hash_fault(regs))
    - hash__do_page_fault(regs);
    + __do_hash_fault(regs);

    return 0;
    }
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:09    [W:2.115 / U:1.140 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site