Received: by 2002:a05:7412:d8a:b0:e2:908c:2ebd with SMTP id b10csp38130rdg; Tue, 10 Oct 2023 03:42:27 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFvgXrLaIrifrPOEzDtp8THTubfgEKORYtdY/2we5FEPPTMLgDUPdq8Tm+SNkBFHeWxRK37 X-Received: by 2002:a05:6a00:1695:b0:690:1c1b:aefd with SMTP id k21-20020a056a00169500b006901c1baefdmr20675002pfc.5.1696934547355; Tue, 10 Oct 2023 03:42:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696934547; cv=none; d=google.com; s=arc-20160816; b=A0lt5j64GFMEf3sS+9jILEsYYicI/mhfOjuV50HmTG4dp8bqmwnT1vKgWKXSw/2gTk LTTMMnkwSEzkl5MOyOzIiVK55ZGVF2vF3nF2aILvmm5wooALhRMuuT5aAN7BTWrtLcsT s2/XeF35d+wyrtU5HtF767yBWdjTjUlXQIenR/bZL/Xa8NeDqXybmNQqhzfltQVA8jP1 u2xgFVG27ycCITffY4P3nFW9lbRFbcG0LgY3YEWnc8DBYxsMGVBERjeQUBPK8NO3LMm7 q07yYJIYQ/d3H/BaYGofj/Ei9A5V8bfW49HdeecI/Juz3hS/773ls/+Z/bYV776nzHiL tAgQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=HgviywdcJpAoDOb+3371+wFwWwiIxsvSvZ1neMvuRd4=; fh=FiwhyeArbhrGbGqkI7suClk/SuK4po8XwFNjMRUg0hk=; b=cyJVTcLIe8BVEN0uA3j2uAvHs0gkK9p3haHCyRt9Xarhm5msQasszH6uDv6nj5NfWf jov9/ovIjuVvRZU7K/oAXc8JhHFyu7eb9KDEmS9gIm39H3hXytBe70xxvW0sufI+r95s 9zYAmIV3INJdTQIlotHR5h3r8MRvpEHAVxa4I35jw0xHvq1k6EgDjgnfztWMs8CJdIyL VqGeB0IwRoxflhpKC4srr+0xa+1Vs3I248dHeJjXrJPEvp7EBp+i5bAOMz8bRzhNkIMA GEi3iW+CMrODHT6K1Tx4ItKAG+lDO5A0iTtyAT9L3DvmjP9jpbQx+bl+yUtBBQR5s1fj IVjw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from howler.vger.email (howler.vger.email. [23.128.96.34]) by mx.google.com with ESMTPS id cb7-20020a056a00430700b00690c23d353asi9237688pfb.217.2023.10.10.03.42.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Oct 2023 03:42:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) client-ip=23.128.96.34; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id 271978025815; Tue, 10 Oct 2023 03:42:23 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231202AbjJJKmC (ORCPT + 99 others); Tue, 10 Oct 2023 06:42:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229597AbjJJKmB (ORCPT ); Tue, 10 Oct 2023 06:42:01 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 564ADC4; Tue, 10 Oct 2023 03:41:58 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A616A1FB; Tue, 10 Oct 2023 03:42:38 -0700 (PDT) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 751D73F762; Tue, 10 Oct 2023 03:41:55 -0700 (PDT) From: James Clark To: linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org, suzuki.poulose@arm.com Cc: James Clark , Catalin Marinas , Will Deacon , Jonathan Corbet , Russell King , Marc Zyngier , Oliver Upton , James Morse , Zenghui Yu , Mark Rutland , Reiji Watanabe , Geert Uytterhoeven , Zaid Al-Bassam , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev Subject: [PATCH v2 2/3] arm64: perf: Add support for event counting threshold Date: Tue, 10 Oct 2023 11:40:28 +0100 Message-Id: <20231010104048.1923484-3-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231010104048.1923484-1-james.clark@arm.com> References: <20231010104048.1923484-1-james.clark@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=2.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on howler.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Tue, 10 Oct 2023 03:42:23 -0700 (PDT) X-Spam-Level: ** FEAT_PMUv3_TH (Armv8.8) permits a PMU counter to increment only on events whose count meets a specified threshold condition. For example if PMEVTYPERn.TC (Threshold Control) is set to 0b101 (Greater than or equal, count), and the threshold is set to 2, then the PMU counter will now only increment by 1 when an event would have previously incremented the PMU counter by 2 or more on a single processor cycle. Two new Perf event config fields, 'threshold' and 'threshold_control' have been added for controlling the feature: $ perf stat -e stall_slot/threshold=2,threshold_control=5/ A new capability for reading out the maximum supported threshold value has also been added: $ cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max 0x000000ff If a threshold higher than threshold_max is provided, then no error is generated but the threshold is clamped to the max value. If FEAT_PMUv3_TH isn't implemented or a 32 bit kernel is running, then threshold_max reads zero, and neither the 'threshold' nor 'threshold_control' parameters will be used. The threshold is per PMU counter, and there are potentially different threshold_max values per PMU type on heterogeneous systems. Bits higher than 32 now need to be written into PMEVTYPER, so armv8pmu_write_evtype() has to be updated to take an unsigned long value rather than u32 which gives the correct behavior on both aarch32 and 64. Signed-off-by: James Clark --- drivers/perf/arm_pmuv3.c | 67 +++++++++++++++++++++++++++++++++- include/linux/perf/arm_pmuv3.h | 1 + 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c index 8fcaa26f0f8a..6d669b16a2bc 100644 --- a/drivers/perf/arm_pmuv3.c +++ b/drivers/perf/arm_pmuv3.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -294,9 +295,16 @@ static const struct attribute_group armv8_pmuv3_events_attr_group = { .is_visible = armv8pmu_event_attr_is_visible, }; +#define TH_LO 2 +#define TH_HI 13 +#define TH_CNTL_LO 14 +#define TH_CNTL_HI 16 + PMU_FORMAT_ATTR(event, "config:0-15"); PMU_FORMAT_ATTR(long, "config1:0"); PMU_FORMAT_ATTR(rdpmc, "config1:1"); +PMU_FORMAT_ATTR(threshold, "config1:" __stringify(TH_LO) "-" __stringify(TH_HI)); +PMU_FORMAT_ATTR(threshold_control, "config1:" __stringify(TH_CNTL_LO) "-" __stringify(TH_CNTL_HI)); static int sysctl_perf_user_access __read_mostly; @@ -310,10 +318,22 @@ static inline bool armv8pmu_event_want_user_access(struct perf_event *event) return event->attr.config1 & 0x2; } +static inline u32 armv8pmu_event_threshold(struct perf_event_attr *attr) +{ + return FIELD_GET(GENMASK(TH_HI, TH_LO), attr->config1); +} + +static inline u8 armv8pmu_event_threshold_control(struct perf_event_attr *attr) +{ + return FIELD_GET(GENMASK(TH_CNTL_HI, TH_CNTL_LO), attr->config1); +} + static struct attribute *armv8_pmuv3_format_attrs[] = { &format_attr_event.attr, &format_attr_long.attr, &format_attr_rdpmc.attr, + &format_attr_threshold.attr, + &format_attr_threshold_control.attr, NULL, }; @@ -365,10 +385,38 @@ static ssize_t bus_width_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(bus_width); +static u32 threshold_max(struct arm_pmu *cpu_pmu) +{ + /* + * PMMIR.WIDTH is readable and non-zero on aarch32, but it would be + * impossible to write the threshold in the upper 32 bits of PMEVTYPER. + */ + if (IS_ENABLED(CONFIG_ARM)) + return 0; + + /* + * The largest value that can be written to PMEVTYPER_EL0.TH is + * (2 ^ PMMIR.THWIDTH) - 1. + */ + return (1 << FIELD_GET(ARMV8_PMU_THWIDTH, cpu_pmu->reg_pmmir)) - 1; +} + +static ssize_t threshold_max_show(struct device *dev, + struct device_attribute *attr, char *page) +{ + struct pmu *pmu = dev_get_drvdata(dev); + struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu); + + return sysfs_emit(page, "0x%08x\n", threshold_max(cpu_pmu)); +} + +static DEVICE_ATTR_RO(threshold_max); + static struct attribute *armv8_pmuv3_caps_attrs[] = { &dev_attr_slots.attr, &dev_attr_bus_slots.attr, &dev_attr_bus_width.attr, + &dev_attr_threshold_max.attr, NULL, }; @@ -552,7 +600,7 @@ static void armv8pmu_write_counter(struct perf_event *event, u64 value) armv8pmu_write_hw_counter(event, value); } -static inline void armv8pmu_write_evtype(int idx, u32 val) +static inline void armv8pmu_write_evtype(int idx, unsigned long val) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); @@ -914,6 +962,10 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, struct perf_event_attr *attr) { unsigned long config_base = 0; + struct perf_event *perf_event = container_of(attr, struct perf_event, + attr); + struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu); + u32 th, th_max; if (attr->exclude_idle) return -EPERM; @@ -945,6 +997,19 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, if (attr->exclude_user) config_base |= ARMV8_PMU_EXCLUDE_EL0; + /* + * Insert event counting threshold (FEAT_PMUv3_TH) values. If + * FEAT_PMUv3_TH isn't implemented, then THWIDTH (threshold_max) will be + * 0 and no values will be written. + */ + th_max = threshold_max(cpu_pmu); + if (IS_ENABLED(CONFIG_ARM64) && th_max) { + th = min(armv8pmu_event_threshold(attr), th_max); + config_base |= FIELD_PREP(ARMV8_PMU_EVTYPE_TH, th); + config_base |= FIELD_PREP(ARMV8_PMU_EVTYPE_TC, + armv8pmu_event_threshold_control(attr)); + } + /* * Install the filter into config_base as this is used to * construct the event type. diff --git a/include/linux/perf/arm_pmuv3.h b/include/linux/perf/arm_pmuv3.h index ec3a01502e7c..753f8dbd9d10 100644 --- a/include/linux/perf/arm_pmuv3.h +++ b/include/linux/perf/arm_pmuv3.h @@ -255,6 +255,7 @@ #define ARMV8_PMU_BUS_SLOTS_MASK 0xff #define ARMV8_PMU_BUS_WIDTH_SHIFT 16 #define ARMV8_PMU_BUS_WIDTH_MASK 0xf +#define ARMV8_PMU_THWIDTH GENMASK(23, 20) /* * This code is really good -- 2.34.1