lkml.org 
[lkml]   [2020]   [Apr]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 029/131] perf/core: Disable page faults when getting phys address
    Date
    From: Jiri Olsa <jolsa@kernel.org>

    [ Upstream commit d3296fb372bf7497b0e5d0478c4e7a677ec6f6e9 ]

    We hit following warning when running tests on kernel
    compiled with CONFIG_DEBUG_ATOMIC_SLEEP=y:

    WARNING: CPU: 19 PID: 4472 at mm/gup.c:2381 __get_user_pages_fast+0x1a4/0x200
    CPU: 19 PID: 4472 Comm: dummy Not tainted 5.6.0-rc6+ #3
    RIP: 0010:__get_user_pages_fast+0x1a4/0x200
    ...
    Call Trace:
    perf_prepare_sample+0xff1/0x1d90
    perf_event_output_forward+0xe8/0x210
    __perf_event_overflow+0x11a/0x310
    __intel_pmu_pebs_event+0x657/0x850
    intel_pmu_drain_pebs_nhm+0x7de/0x11d0
    handle_pmi_common+0x1b2/0x650
    intel_pmu_handle_irq+0x17b/0x370
    perf_event_nmi_handler+0x40/0x60
    nmi_handle+0x192/0x590
    default_do_nmi+0x6d/0x150
    do_nmi+0x2f9/0x3c0
    nmi+0x8e/0xd7

    While __get_user_pages_fast() is IRQ-safe, it calls access_ok(),
    which warns on:

    WARN_ON_ONCE(!in_task() && !pagefault_disabled())

    Peter suggested disabling page faults around __get_user_pages_fast(),
    which gets rid of the warning in access_ok() call.

    Suggested-by: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Link: https://lkml.kernel.org/r/20200407141427.3184722-1-jolsa@kernel.org
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    kernel/events/core.c | 9 ++++++---
    1 file changed, 6 insertions(+), 3 deletions(-)

    diff --git a/kernel/events/core.c b/kernel/events/core.c
    index 8c70ee23fbe91..00fb2fe92c4d6 100644
    --- a/kernel/events/core.c
    +++ b/kernel/events/core.c
    @@ -6411,9 +6411,12 @@ static u64 perf_virt_to_phys(u64 virt)
    * Try IRQ-safe __get_user_pages_fast first.
    * If failed, leave phys_addr as 0.
    */
    - if ((current->mm != NULL) &&
    - (__get_user_pages_fast(virt, 1, 0, &p) == 1))
    - phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
    + if (current->mm != NULL) {
    + pagefault_disable();
    + if (__get_user_pages_fast(virt, 1, 0, &p) == 1)
    + phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
    + pagefault_enable();
    + }

    if (p)
    put_page(p);
    --
    2.20.1


    \
     
     \ /
      Last update: 2020-04-28 20:58    [W:5.256 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site