• Michael Ellerman's avatar
    powerpc/perf: Add per-event excludes on Power8 · 9de5cb0f
    Michael Ellerman authored
    Power8 has a new register (MMCR2), which contains individual freeze bits
    for each counter. This is an improvement on previous chips as it means
    we can have multiple events on the PMU at the same time with different
    exclude_{user,kernel,hv} settings. Previously we had to ensure all
    events on the PMU had the same exclude settings.
    
    The core of the patch is fairly simple. We use the 207S feature flag to
    indicate that the PMU backend supports per-event excludes, if it's set
    we skip the generic logic that enforces the equality of excludes between
    events. We also use that flag to skip setting the freeze bits in MMCR0,
    the PMU backend is expected to have handled setting them in MMCR2.
    
    The complication arises with EBB. The FCxP bits in MMCR2 are accessible
    R/W to a task using EBB. Which means a task using EBB will be able to
    see that we are using MMCR2 for freezing, whereas the old logic which
    used MMCR0 is not user visible.
    
    The task can not see or affect exclude_kernel & exclude_hv, so we only
    need to consider exclude_user.
    
    The table below summarises the behaviour both before and after this
    commit is applied:
    
     exclude_user           true  false
     ------------------------------------
            | User visible |  N    N
     Before | Can freeze   |  Y    Y
            | Can unfreeze |  N    Y
     ------------------------------------
            | User visible |  Y    Y
      After | Can freeze   |  Y    Y
            | Can unfreeze |  Y/N  Y
     ------------------------------------
    
    So firstly I assert that the simple visibility of the exclude_user
    setting in MMCR2 is a non-issue. The event belongs to the task, and
    was most likely created by the task. So the exclude_user setting is not
    privileged information in any way.
    
    Secondly, the behaviour in the exclude_user = false case is unchanged.
    This is important as it is the case that is actually useful, ie. the
    event is created with no exclude setting and the task uses MMCR2 to
    implement exclusion manually.
    
    For exclude_user = true there is no meaningful change to freezing the
    event. Previously the task could use MMCR2 to freeze the event, though
    it was already frozen with MMCR0. With the new code the task can use
    MMCR2 to freeze the event, though it was already frozen with MMCR2.
    
    The only real change is when exclude_user = true and the task tries to
    use MMCR2 to unfreeze the event. Previously this had no effect, because
    the event was already frozen in MMCR0. With the new code the task can
    unfreeze the event in MMCR2, but at some indeterminate time in the
    future the kernel will overwrite its setting and refreeze the event.
    
    Therefore my final assertion is that any task using exclude_user = true
    and also fiddling with MMCR2 was deeply confused before this change, and
    remains so after it.
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
    9de5cb0f
core-book3s.c 53.8 KB