lkml.org 
[lkml]   [2020]   [Sep]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 02/10] arm64: pmu: Add function implementation to update event index in userpage
    Date
    From: Raphael Gault <raphael.gault@arm.com>

    In order to be able to access the counter directly for userspace,
    we need to provide the index of the counter using the userpage.
    We thus need to override the event_idx function to retrieve and
    convert the perf_event index to armv8 hardware index.

    Since the arm_pmu driver can be used by any implementation, even
    if not armv8, two components play a role into making sure the
    behaviour is correct and consistent with the PMU capabilities:

    * the ARMPMU_EL0_RD_CNTR flag which denotes the capability to access
    counter from userspace.
    * the event_idx call back, which is implemented and initialized by
    the PMU implementation: if no callback is provided, the default
    behaviour applies, returning 0 as index value.

    Signed-off-by: Raphael Gault <raphael.gault@arm.com>
    Signed-off-by: Rob Herring <robh@kernel.org>
    ---
    arch/arm64/kernel/perf_event.c | 21 +++++++++++++++++++++
    include/linux/perf/arm_pmu.h | 2 ++
    2 files changed, 23 insertions(+)

    diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
    index 70538ae684da..2727d126cecd 100644
    --- a/arch/arm64/kernel/perf_event.c
    +++ b/arch/arm64/kernel/perf_event.c
    @@ -820,6 +820,22 @@ static void armv8pmu_clear_event_idx(struct pmu_hw_events *cpuc,
    clear_bit(idx - 1, cpuc->used_mask);
    }

    +static int armv8pmu_access_event_idx(struct perf_event *event)
    +{
    + if (!(event->hw.flags & ARMPMU_EL0_RD_CNTR))
    + return 0;
    +
    + /*
    + * We remap the cycle counter index to 32 to
    + * match the offset applied to the rest of
    + * the counter indices.
    + */
    + if (event->hw.idx == ARMV8_IDX_CYCLE_COUNTER)
    + return 32;
    +
    + return event->hw.idx;
    +}
    +
    /*
    * Add an event filter to a given event.
    */
    @@ -916,6 +932,9 @@ static int __armv8_pmuv3_map_event(struct perf_event *event,
    if (armv8pmu_event_is_64bit(event))
    event->hw.flags |= ARMPMU_EVT_64BIT;

    + if (!armv8pmu_event_is_chained(event))
    + event->hw.flags |= ARMPMU_EL0_RD_CNTR;
    +
    /* Only expose micro/arch events supported by this PMU */
    if ((hw_event_id > 0) && (hw_event_id < ARMV8_PMUV3_MAX_COMMON_EVENTS)
    && test_bit(hw_event_id, armpmu->pmceid_bitmap)) {
    @@ -1092,6 +1111,8 @@ static int armv8_pmu_init(struct arm_pmu *cpu_pmu, char *name,
    cpu_pmu->set_event_filter = armv8pmu_set_event_filter;
    cpu_pmu->filter_match = armv8pmu_filter_match;

    + cpu_pmu->pmu.event_idx = armv8pmu_access_event_idx;
    +
    cpu_pmu->name = name;
    cpu_pmu->map_event = map_event;
    cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = events ?
    diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
    index 5b616dde9a4c..74fbbbd29dc7 100644
    --- a/include/linux/perf/arm_pmu.h
    +++ b/include/linux/perf/arm_pmu.h
    @@ -26,6 +26,8 @@
    */
    /* Event uses a 64bit counter */
    #define ARMPMU_EVT_64BIT 1
    +/* Allow access to hardware counter from userspace */
    +#define ARMPMU_EL0_RD_CNTR 2

    #define HW_OP_UNSUPPORTED 0xFFFF
    #define C(_x) PERF_COUNT_HW_CACHE_##_x
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-09-11 23:51    [W:3.008 / U:0.108 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site