• Stephane Eranian's avatar
    perf/x86: Fix shared register mutual exclusion enforcement · 2f7f73a5
    Stephane Eranian authored
    This patch fixes a problem with the shared registers mutual
    exclusion code and incremental event scheduling by the
    generic perf_event code.
    
    There was a bug whereby the mutual exclusion on the shared
    registers was not enforced because of incremental scheduling
    abort due to event constraints. As an example on Intel
    Nehalem, consider the following events:
    
    group1= L1D_CACHE_LD:E_STATE,OFFCORE_RESPONSE_0:PF_RFO,L1D_CACHE_LD:I_STATE
    group2= L1D_CACHE_LD:I_STATE
    
    The L1D_CACHE_LD event can only be measured by 2 counters. Yet, there
    are 3 instances here. The first group can be scheduled and is committed.
    Then, the generic code tries to schedule group2 and this fails (because
    there is no more counter to support the 3rd instance of L1D_CACHE_LD).
    But in x86_schedule_events() error path, put_event_contraints() is invoked
    on ALL the events and not just the ones that just failed. That causes the
    "lock" on the shared offcore_response MSR to be released. Yet the first group
    is actually scheduled and is exposed to reprogramming of that shared msr by
    the sibling HT thread. In other words, there is no guarantee on what is
    measured.
    
    This patch fixes the problem by tagging committed events with the
    PERF_X86_EVENT_COMMITTED tag. In the error path of x86_schedule_events(),
    only the events NOT tagged have their constraint released. The tag
    is eventually removed when the event in descheduled.
    Signed-off-by: default avatarStephane Eranian <eranian@google.com>
    Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
    Link: http://lkml.kernel.org/r/20130620164254.GA3556@quadSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    2f7f73a5
perf_event.c 48.1 KB