From nobody Fri May  9 11:48:33 2025
Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com
 [209.85.214.201])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D9A1F507
	for <linux-kernel@vger.kernel.org>; Mon, 24 Mar 2025 16:46:02 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=209.85.214.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1742834764; cv=none;
 b=JEn8Yi6DmLu5+diB8m+2jmlI9fReb+XHTAuPQK7AldZV24wl1W2kU1QZegNH+jxLfBh3uTCOGWdz4ZvuQ3Yay7Sd78NaC/EUmHO6Og9gPqpOH2+TAK6p1TV5KubmuO4XWn/kSDXIAFY9u29nDBIEvoyHPcwGAzjGrGMbIF//V/g=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1742834764; c=relaxed/simple;
	bh=kxWIhqI5kQgSrfWnFj1SXB+Qsrz3NdTDGFIs7hJn0dk=;
	h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From:
	 To:Cc:Content-Type;
 b=gQTL2xU4iXczAFt/evsY5qrv57savF6DvRdzRk2pB8eLCivKo+/HmL9ixfVZIwCmktZQNPLNfT2VamVCQasst3Yb7c+ODcmFPNgRJwmOy4nn4z1Ws2ZRwW7ojh43O0MNJs1FF5koUqqBiofxyJV1Jt4/p/d7k/096dPRFKLwfvI=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dmarc=pass (p=reject dis=none) header.from=google.com;
 spf=pass smtp.mailfrom=flex--irogers.bounces.google.com;
 dkim=pass (2048-bit key) header.d=google.com header.i=@google.com
 header.b=oOVNY9z5; arc=none smtp.client-ip=209.85.214.201
Authentication-Results: smtp.subspace.kernel.org;
 dmarc=pass (p=reject dis=none) header.from=google.com
Authentication-Results: smtp.subspace.kernel.org;
 spf=pass smtp.mailfrom=flex--irogers.bounces.google.com
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=google.com header.i=@google.com
 header.b="oOVNY9z5"
Received: by mail-pl1-f201.google.com with SMTP id
 d9443c01a7336-224192ff68bso69801005ad.1
        for <linux-kernel@vger.kernel.org>;
 Mon, 24 Mar 2025 09:46:02 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=google.com; s=20230601; t=1742834762; x=1743439562;
 darn=vger.kernel.org;
        h=cc:to:from:subject:message-id:references:mime-version:in-reply-to
         :date:from:to:cc:subject:date:message-id:reply-to;
        bh=aOKv+RE9GVYPUsIbet19o8Ujd1At3Uyf2EUgP1dN0LA=;
        b=oOVNY9z57JzRUlbZ4eGOdsG+azCc4jdxDTfnkCnrfWcIyc+vBaOlevyDTFgHvfobl1
         ttoR365ee2zfZOZF5bcK13KnVorni9L6kKBA6o7GVEtDW7yP2eVEw7oT3WBX6FIwKAtN
         ddrViPKUt88SmTac9zSAu7IftgHym6meUBoguzmx9SAJ9PHITMkkEDSEArWs5bl3a+46
         mqBU2MX8G8jm4MRIpfD8sjXKDCmCvnwfH0L9V+XUElL0xYsydDeY0b/TDDe9r6c5TBt4
         sPx3AAe4auo74d3R6tGtQJicSuVOOqW2ChQihfEcGm3kF+NaypROl5nrkRSfAMVJ6prt
         rNqw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1742834762; x=1743439562;
        h=cc:to:from:subject:message-id:references:mime-version:in-reply-to
         :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
        bh=aOKv+RE9GVYPUsIbet19o8Ujd1At3Uyf2EUgP1dN0LA=;
        b=w/BWu+QZgVRJ5mMYgnEjW8kc8HqnSHpAYfXaeZLKyOtNOCPRDO47OJ9MnpZSZGhbY9
         retuJ6HA2cQOiUNvJKuY+yzCqxdqaIGUofgsoZJa6OKPBUVarcRMzB/Bn98IyeLN/U9Q
         XzCU+P39FY3VDTW5ZPypLQtlKIDnFibnmqTOD8JDLiy2ekA8vyl4Qb4rkvBKbgnKzQI1
         qAM9GnMAW0byfuaNSp01pQXC77xNVBoq6vZrPmzX2hsuq5uONSmjcFZ+JOqMET43MetP
         pNMuEI1/JFMEXrPxUncfv/YUIRwOjsY56Dx5uD3FtzMZdpSpdcJVNZm3Wr/b61q7IYH7
         WE7Q==
X-Forwarded-Encrypted: i=1;
 AJvYcCXQgwLgeId5hHFqZ3rskcHuNpJMJ2Mxr7Fm+4lKcE1lJEKq/qGbHMDmqPuXUn9ikX3t6TUsLAS0mcehXi8=@vger.kernel.org
X-Gm-Message-State: AOJu0Yz5Gv6uRbqVlGXgoL6/gsyeShRYCHeIeuyIciDm49Ye3OobISGG
	jQX+2AUza+xOXcr/EJ3fj+TrV+hD5zp914b25VxV1kihhxiBOgT8d9YfInT+ekrS1ZECNClzSh+
	l5abZog==
X-Google-Smtp-Source: 
 AGHT+IGBHhsPQI40bxF8e5SZUalli4eDczXVHBI0ne3gaUoq80rI6UrqnCCns2/QyBvGAVbiwmVw9Lw3aojp
X-Received: from plblc15.prod.google.com
 ([2002:a17:902:fa8f:b0:223:67ac:e082])
 (user=irogers job=prod-delivery.src-stubby-dispatcher) by
 2002:a17:903:1a2f:b0:210:fce4:11ec
 with SMTP id d9443c01a7336-22780c69ce3mr210455165ad.1.1742834762326; Mon, 24
 Mar 2025 09:46:02 -0700 (PDT)
Date: Mon, 24 Mar 2025 09:45:41 -0700
In-Reply-To: <20250324164543.62574-1-irogers@google.com>
Precedence: bulk
X-Mailing-List: linux-kernel@vger.kernel.org
List-Id: <linux-kernel.vger.kernel.org>
List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org>
List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org>
Mime-Version: 1.0
References: <20250324164543.62574-1-irogers@google.com>
X-Mailer: git-send-email 2.49.0.395.g12beb8f557-goog
Message-ID: <20250324164543.62574-2-irogers@google.com>
Subject: [PATCH v6 1/2] perf record: Skip don't fail for events that don't
 open
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>, Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
 Namhyung Kim <namhyung@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
 Jiri Olsa <jolsa@kernel.org>,
	Ian Rogers <irogers@google.com>, Adrian Hunter <adrian.hunter@intel.com>,
	Kan Liang <kan.liang@linux.intel.com>, James Clark <james.clark@linaro.org>,
	Ze Gao <zegao2021@gmail.com>, Weilin Wang <weilin.wang@intel.com>,
	Dominique Martinet <asmadeus@codewreck.org>,
	Jean-Philippe Romain <jean-philippe.romain@foss.st.com>,
 Junhao He <hejunhao3@huawei.com>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	Aditya Bodkhe <Aditya.Bodkhe1@ibm.com>
Cc: Leo Yan <leo.yan@arm.com>, Atish Patra <atishp@rivosinc.com>
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

Whilst for many tools it is an expected behavior that failure to open
a perf event is a failure, ARM decided to name PMU events the same as
legacy events and then failed to rename such events on a server uncore
SLC PMU. As perf's default behavior when no PMU is specified is to
open the event on all PMUs that advertise/"have" the event, this
yielded failures when trying to make the priority of legacy and
sysfs/json events uniform - something requested by RISC-V and ARM. A
legacy event user on ARM hardware may find their event opened on an
uncore PMU which for perf record will fail. Arnaldo suggested skipping
such events which this patch implements. Rather than have the skipping
conditional on running on ARM, the skipping is done on all
architectures as such a fundamental behavioral difference could lead
to problems with tools built/depending on perf.

An example of perf record failing to open events on x86 is:
```
$ perf record -e data_read,cycles,LLC-prefetch-read -a sleep 0.1
Error:
Failure to open event 'data_read' on PMU 'uncore_imc_free_running_0' which =
will be removed.
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for e=
vent (data_read).
"dmesg | grep -i perf" may provide additional information.

Error:
Failure to open event 'data_read' on PMU 'uncore_imc_free_running_1' which =
will be removed.
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for e=
vent (data_read).
"dmesg | grep -i perf" may provide additional information.

Error:
Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be remove=
d.
The LLC-prefetch-read event is not supported.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 2.188 MB perf.data (87 samples) ]

$ perf report --stats
Aggregated stats:
               TOTAL events:      17255
                MMAP events:        284  ( 1.6%)
                COMM events:       1961  (11.4%)
                EXIT events:          1  ( 0.0%)
                FORK events:       1960  (11.4%)
              SAMPLE events:         87  ( 0.5%)
               MMAP2 events:      12836  (74.4%)
             KSYMBOL events:         83  ( 0.5%)
           BPF_EVENT events:         36  ( 0.2%)
      FINISHED_ROUND events:          2  ( 0.0%)
            ID_INDEX events:          1  ( 0.0%)
          THREAD_MAP events:          1  ( 0.0%)
             CPU_MAP events:          1  ( 0.0%)
           TIME_CONV events:          1  ( 0.0%)
       FINISHED_INIT events:          1  ( 0.0%)
cycles stats:
              SAMPLE events:         87
```

If all events fail to open then the perf record will fail:
```
$ perf record -e LLC-prefetch-read true
Error:
Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be remove=
d.
The LLC-prefetch-read event is not supported.
Error:
Failure to open any events for recording
```

As an evlist may have dummy events that open when all command line
events fail we ignore dummy events when detecting if at least some
events open. This still permits the dummy event on its own to be used
as a permission check:
```
$ perf record -e dummy true
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.046 MB perf.data ]
```
but allows failure when a dummy event is implicilty inserted or when
there are insufficient permissions to open it:
```
$ perf record -e LLC-prefetch-read -a true
Error:
Failure to open event 'LLC-prefetch-read' on PMU 'cpu' which will be remove=
d.
The LLC-prefetch-read event is not supported.
Error:
Failure to open any events for recording
```

The issue with legacy events is that on RISC-V they want the driver to
not have mappings from legacy to non-legacy config encodings for each
vendor/model due to size, complexity and difficulty to update. It was
reported that on ARM Apple-M? CPUs the legacy mapping in the driver
was broken and the sysfs/json events should always take precedent,
however, it isn't clear this is still the case. It is the case that
without working around this issue a legacy event like cycles without a
PMU can encode differently than when specified with a PMU - the
non-PMU version favoring legacy encodings, the PMU one avoiding legacy
encodings.

The patch removes events and then adjusts the idx value for each
evsel. This is done so that the dense xyarrays used for file
descriptors, etc. don't contain broken entries. As event opening
happens relatively late in the record process, use of the idx value
before the open will have become corrupted, so it is expected there
are latent bugs hidden behind this change - the change is best
effort. As the only vendor that has broken event names is ARM, this
will principally effect ARM users. They will also experience warning
messages like those above because of the uncore PMU advertising legacy
event names.

Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: James Clark <james.clark@linaro.org>
Tested-by: Leo Yan <leo.yan@arm.com>
Tested-by: Atish Patra <atishp@rivosinc.com>
---
 tools/perf/builtin-record.c | 47 ++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ba20bf7c011d..00f6a1c23254 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -962,7 +962,6 @@ static int record__config_tracking_events(struct record=
 *rec)
 	 */
 	if (opts->target.initial_delay || target__has_cpu(&opts->target) ||
 	    perf_pmus__num_core_pmus() > 1) {
-
 		/*
 		 * User space tasks can migrate between CPUs, so when tracing
 		 * selected CPUs, sideband for all CPUs is still needed.
@@ -1367,6 +1366,7 @@ static int record__open(struct record *rec)
 	struct perf_session *session =3D rec->session;
 	struct record_opts *opts =3D &rec->opts;
 	int rc =3D 0;
+	bool skipped =3D false;
=20
 	evlist__for_each_entry(evlist, pos) {
 try_again:
@@ -1382,15 +1382,50 @@ static int record__open(struct record *rec)
 			        pos =3D evlist__reset_weak_group(evlist, pos, true);
 				goto try_again;
 			}
-			rc =3D -errno;
 			evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg));
-			ui__error("%s\n", msg);
-			goto out;
+			ui__error("Failure to open event '%s' on PMU '%s' which will be removed=
.\n%s\n",
+				  evsel__name(pos), evsel__pmu_name(pos), msg);
+			pos->skippable =3D true;
+			skipped =3D true;
+		} else {
+			pos->supported =3D true;
 		}
-
-		pos->supported =3D true;
 	}
=20
+	if (skipped) {
+		struct evsel *tmp;
+		int idx =3D 0;
+		bool evlist_empty =3D true;
+
+		/* Remove evsels that failed to open and update indices. */
+		evlist__for_each_entry_safe(evlist, tmp, pos) {
+			if (pos->skippable) {
+				evlist__remove(evlist, pos);
+				continue;
+			}
+
+			/*
+			 * Note, dummy events may be command line parsed or
+			 * added by the tool. We care about supporting `perf
+			 * record -e dummy` which may be used as a permission
+			 * check. Dummy events that are added to the command
+			 * line and opened along with other events that fail,
+			 * will still fail as if the dummy events were tool
+			 * added events for the sake of code simplicity.
+			 */
+			if (!evsel__is_dummy_event(pos))
+				evlist_empty =3D false;
+		}
+		evlist__for_each_entry(evlist, pos) {
+			pos->core.idx =3D idx++;
+		}
+		/* If list is empty then fail. */
+		if (evlist_empty) {
+			ui__error("Failure to open any events for recording.\n");
+			rc =3D -1;
+			goto out;
+		}
+	}
 	if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) {
 		pr_warning(
 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
--=20
2.49.0.395.g12beb8f557-goog
From nobody Fri May  9 11:48:33 2025
Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com
 [209.85.216.73])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03F36263F40
	for <linux-kernel@vger.kernel.org>; Mon, 24 Mar 2025 16:46:04 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=209.85.216.73
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1742834766; cv=none;
 b=r8NF5Iw4ei8BSvPKi/YkCuYXaCFPxE/UInwv3zKX/fGk1qu1mAz756WMkyFFXw973S4dXN1YFL/xQADuxY0CAzzYUg5HaDBQ6L1VV83X5lsu5djTBubiWUwTvw85pDzxgVWBLmJFlZe212RgqbC2403cie8n6dpqvZIFhKEK0dY=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1742834766; c=relaxed/simple;
	bh=xO9XeqO4FUSuYO61Dfds0tzBhFOyw8Et+cqs1nSl4Hw=;
	h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From:
	 To:Cc:Content-Type;
 b=AwH4dB5GB3zJgc20/JdYUkvqPsqtH45nTTwqLgmmebnva0EF7jPGquleAX4wh8l7yBd/3g2h7Og5GdYOT11bYq9o3Yj8BVGMu/QnnQF3160EoeEg+CZoqTRAgjhMzf1QgANmadJNMs5rSU9dr/5Vuh6HKimJMqEIdPEQB52gQJ0=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dmarc=pass (p=reject dis=none) header.from=google.com;
 spf=pass smtp.mailfrom=flex--irogers.bounces.google.com;
 dkim=pass (2048-bit key) header.d=google.com header.i=@google.com
 header.b=1INgl1Un; arc=none smtp.client-ip=209.85.216.73
Authentication-Results: smtp.subspace.kernel.org;
 dmarc=pass (p=reject dis=none) header.from=google.com
Authentication-Results: smtp.subspace.kernel.org;
 spf=pass smtp.mailfrom=flex--irogers.bounces.google.com
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=google.com header.i=@google.com
 header.b="1INgl1Un"
Received: by mail-pj1-f73.google.com with SMTP id
 98e67ed59e1d1-2fec3e38c2dso12364461a91.2
        for <linux-kernel@vger.kernel.org>;
 Mon, 24 Mar 2025 09:46:04 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=google.com; s=20230601; t=1742834764; x=1743439564;
 darn=vger.kernel.org;
        h=cc:to:from:subject:message-id:references:mime-version:in-reply-to
         :date:from:to:cc:subject:date:message-id:reply-to;
        bh=lyWvHd4BtbK+3yGaCjWTrHoIvu1HDim/7/52tq5OE9U=;
        b=1INgl1UnTv57zf/lFC9/n87rZcnhxwnmAJK0NXUu56HrN1UZDfJpy0f2G9WBK12G/T
         kWXlJ4S2HKFMNfM6z4jD3mx4KNKe8ombap9NN01QwUcTMGn1iq4VsHazgEfN3y5ZUO0Z
         rNYKNkD89D3jKmB6K3UGS/aRQQ4S64Qvzx6uu6hBmXxS+fyGNHjlYkLaOJt6BPwvitIQ
         1+TdPyh/g/ssaRzCGgZ7InbCQv9l2x7ckAuEJunK9Jza8oe/TX5avzGQeObOsKO5BQUr
         EQC7HvNJ4IWlKDN/EgXfVQx4Zp4uc2wb3j2is3IfiUSBb12dlcwjwGn6jdg0LdRdMe2O
         jd1w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1742834764; x=1743439564;
        h=cc:to:from:subject:message-id:references:mime-version:in-reply-to
         :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
        bh=lyWvHd4BtbK+3yGaCjWTrHoIvu1HDim/7/52tq5OE9U=;
        b=bpV8a50Fb4bhXG2ejAmIpnjAX61rOpKvG01iNNa7zecXv2l2TqguB/liPfwnbJGLIv
         GExZX3sqv9m/oqRY0ufS/eOKk0Lb7xdpt8/lBx3UCVcx7AQWH+UlR/eTawg2Yz1pePLs
         Og6ewERvsAuR9OaOWSfreKONHHSdgSEWrlsxsj/82QT24dX/dw33CoK3XpScU6DcASzC
         68QwjFPZ+rzDqbO75VtH0rmIoYQTcfD0mjYqWgixOOAjbf9rB5DplcF7RFByzJq071+n
         0YVRCKCca5y7dYVVtIJbswbm8Ye7rPtA5BDUD9uYA6YVodyyCv3CVZ0Nc4Ye+KwKRQBS
         A3Og==
X-Forwarded-Encrypted: i=1;
 AJvYcCWbGY2mqMt6q6mg4XCinSKt4YlM5Ih0MU8HJT6CiU+snVnzTD0L1QWgaWQ1iOM1SD7KviM2d4AmuFKFCw0=@vger.kernel.org
X-Gm-Message-State: AOJu0YzkLBEceIKLmfuQE2xKj7Yqk6MkZzIJNyQihjSihtLmDWVCca6n
	lah5VrbRj04DvJYfm5mDvW2orlXqxaDX1P3Pw8xkVqbo1fgQc5uNnCWPlO12jivcDT7P8pqqi5g
	UkmJUvg==
X-Google-Smtp-Source: 
 AGHT+IEH8uDIa3ThDPIKOKWNfJrvulB8GlFJeT25fcBnQjgw5EmXt6jC2y681fLkwj3GSPfbGSpNv/jwWBRS
X-Received: from pjur15.prod.google.com ([2002:a17:90a:d40f:b0:2fa:210c:d068])
 (user=irogers job=prod-delivery.src-stubby-dispatcher) by
 2002:a17:90b:1f81:b0:2ee:b8ac:73b0
 with SMTP id 98e67ed59e1d1-3030fe6df0amr24783166a91.2.1742834764248; Mon, 24
 Mar 2025 09:46:04 -0700 (PDT)
Date: Mon, 24 Mar 2025 09:45:42 -0700
In-Reply-To: <20250324164543.62574-1-irogers@google.com>
Precedence: bulk
X-Mailing-List: linux-kernel@vger.kernel.org
List-Id: <linux-kernel.vger.kernel.org>
List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org>
List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org>
Mime-Version: 1.0
References: <20250324164543.62574-1-irogers@google.com>
X-Mailer: git-send-email 2.49.0.395.g12beb8f557-goog
Message-ID: <20250324164543.62574-3-irogers@google.com>
Subject: [PATCH v6 2/2] perf parse-events: Reapply "Prefer sysfs/JSON hardware
 events over legacy"
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>, Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
 Namhyung Kim <namhyung@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
 Jiri Olsa <jolsa@kernel.org>,
	Ian Rogers <irogers@google.com>, Adrian Hunter <adrian.hunter@intel.com>,
	Kan Liang <kan.liang@linux.intel.com>, James Clark <james.clark@linaro.org>,
	Ze Gao <zegao2021@gmail.com>, Weilin Wang <weilin.wang@intel.com>,
	Dominique Martinet <asmadeus@codewreck.org>,
	Jean-Philippe Romain <jean-philippe.romain@foss.st.com>,
 Junhao He <hejunhao3@huawei.com>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	Aditya Bodkhe <Aditya.Bodkhe1@ibm.com>
Cc: Atish Patra <atishp@rivosinc.com>, Leo Yan <leo.yan@arm.com>,
	Beeman Strong <beeman@rivosinc.com>,
 Arnaldo Carvalho de Melo <acme@redhat.com>
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

Originally posted and merged from:
https://lore.kernel.org/r/20240416061533.921723-10-irogers@google.com
This reverts commit 4f1b067359ac8364cdb7f9fda41085fa85789d0f although
the patch is now smaller due to related fixes being applied in commit
22a4db3c3603 ("perf evsel: Add alternate_hw_config and use in
evsel__match").
The original commit message was:

It was requested that RISC-V be able to add events to the perf tool so
the PMU driver didn't need to map legacy events to config encodings:
https://lore.kernel.org/lkml/20240217005738.3744121-1-atishp@rivosinc.com/

This change makes the priority of events specified without a PMU the
same as those specified with a PMU, namely sysfs and JSON events are
checked first before using the legacy encoding.

The hw_term is made more generic as a hardware_event that encodes a
pair of string and int value, allowing parse_events_multi_pmu_add to
fall back on a known encoding when the sysfs/JSON adding fails for
core events. As this covers PE_VALUE_SYM_HW, that token is removed and
related code simplified.

Signed-off-by: Ian Rogers <irogers@google.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Tested-by: Atish Patra <atishp@rivosinc.com>
Tested-by: James Clark <james.clark@linaro.org>
Tested-by: Leo Yan <leo.yan@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Beeman Strong <beeman@rivosinc.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/parse-events.c | 26 +++++++++---
 tools/perf/util/parse-events.l | 76 +++++++++++++++++-----------------
 tools/perf/util/parse-events.y | 60 ++++++++++++++++++---------
 3 files changed, 98 insertions(+), 64 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5152fd5a6ead..cc9cd8069cab 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1551,8 +1551,8 @@ int parse_events_multi_pmu_add(struct parse_events_st=
ate *parse_state,
 	struct list_head *list =3D NULL;
 	struct perf_pmu *pmu =3D NULL;
 	YYLTYPE *loc =3D loc_;
-	int ok =3D 0;
-	const char *config;
+	int ok =3D 0, core_ok =3D 0;
+	const char *tmp;
 	struct parse_events_terms parsed_terms;
=20
 	*listp =3D NULL;
@@ -1565,15 +1565,15 @@ int parse_events_multi_pmu_add(struct parse_events_=
state *parse_state,
 			return ret;
 	}
=20
-	config =3D strdup(event_name);
-	if (!config)
+	tmp =3D strdup(event_name);
+	if (!tmp)
 		goto out_err;
=20
 	if (parse_events_term__num(&term,
 				   PARSE_EVENTS__TERM_TYPE_USER,
-				   config, /*num=3D*/1, /*novalue=3D*/true,
+				   tmp, /*num=3D*/1, /*novalue=3D*/true,
 				   loc, /*loc_val=3D*/NULL) < 0) {
-		zfree(&config);
+		zfree(&tmp);
 		goto out_err;
 	}
 	list_add_tail(&term->list, &parsed_terms.terms);
@@ -1604,6 +1604,8 @@ int parse_events_multi_pmu_add(struct parse_events_st=
ate *parse_state,
 			pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf);
 			strbuf_release(&sb);
 			ok++;
+			if (pmu->is_core)
+				core_ok++;
 		}
 	}
=20
@@ -1620,6 +1622,18 @@ int parse_events_multi_pmu_add(struct parse_events_s=
tate *parse_state,
 		}
 	}
=20
+	if (hw_config !=3D PERF_COUNT_HW_MAX && !core_ok) {
+		/*
+		 * The event wasn't found on core PMUs but it has a hardware
+		 * config version to try.
+		 */
+		if (!parse_events_add_numeric(parse_state, list,
+						PERF_TYPE_HARDWARE, hw_config,
+						const_parsed_terms,
+						/*wildcard=3D*/true))
+			ok++;
+	}
+
 out_err:
 	parse_events_terms__exit(&parsed_terms);
 	if (ok)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 7ed86e3e34e3..324b7dc8a0d3 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -117,12 +117,12 @@ do {								\
 	yyless(0);						\
 } while (0)
=20
-static int sym(yyscan_t scanner, int type, int config)
+static int sym(yyscan_t scanner, int config)
 {
 	YYSTYPE *yylval =3D parse_events_get_lval(scanner);
=20
-	yylval->num =3D (type << 16) + config;
-	return type =3D=3D PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
+	yylval->num =3D config;
+	return PE_VALUE_SYM_SW;
 }
=20
 static int term(yyscan_t scanner, enum parse_events__term_type type)
@@ -133,13 +133,13 @@ static int term(yyscan_t scanner, enum parse_events__=
term_type type)
 	return PE_TERM;
 }
=20
-static int hw_term(yyscan_t scanner, int config)
+static int hw(yyscan_t scanner, int config)
 {
 	YYSTYPE *yylval =3D parse_events_get_lval(scanner);
 	char *text =3D parse_events_get_text(scanner);
=20
-	yylval->hardware_term.str =3D strdup(text);
-	yylval->hardware_term.num =3D PERF_TYPE_HARDWARE + config;
+	yylval->hardware_event.str =3D strdup(text);
+	yylval->hardware_event.num =3D config;
 	return PE_TERM_HW;
 }
=20
@@ -335,16 +335,16 @@ aux-output		{ return term(yyscanner, PARSE_EVENTS__TE=
RM_TYPE_AUX_OUTPUT); }
 aux-action		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_ACTION); }
 aux-sample-size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMP=
LE_SIZE); }
 metric-id		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
-cpu-cycles|cycles				{ return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES)=
; }
-stalled-cycles-frontend|idle-cycles-frontend	{ return hw_term(yyscanner, P=
ERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend	{ return hw_term(yyscanner, PER=
F_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions					{ return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references				{ return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERE=
NCES); }
-cache-misses					{ return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches			{ return hw_term(yyscanner, PERF_COUNT_HW_B=
RANCH_INSTRUCTIONS); }
-branch-misses					{ return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES)=
; }
-bus-cycles					{ return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles					{ return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
+cpu-cycles|cycles				{ return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend	{ return hw(yyscanner, PERF_C=
OUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend	{ return hw(yyscanner, PERF_COU=
NT_HW_STALLED_CYCLES_BACKEND); }
+instructions					{ return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references				{ return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES)=
; }
+cache-misses					{ return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches			{ return hw(yyscanner, PERF_COUNT_HW_BRANCH=
_INSTRUCTIONS); }
+branch-misses					{ return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles					{ return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles					{ return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
 r{num_raw_hex}		{ return str(yyscanner, PE_RAW); }
 r0x{num_raw_hex}	{ return str(yyscanner, PE_RAW); }
 ,			{ return ','; }
@@ -390,28 +390,28 @@ r0x{num_raw_hex}	{ return str(yyscanner, PE_RAW); }
 <<EOF>>			{ BEGIN(INITIAL); }
 }
=20
-cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUN=
T_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_=
TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TY=
PE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW=
_INSTRUCTIONS); }
-cache-references				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT=
_HW_CACHE_REFERENCES); }
-cache-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW=
_CACHE_MISSES); }
-branch-instructions|branches			{ return sym(yyscanner, PERF_TYPE_HARDWARE,=
 PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_H=
W_BRANCH_MISSES); }
-bus-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_B=
US_CYCLES); }
-ref-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_R=
EF_CPU_CYCLES); }
-cpu-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CP=
U_CLOCK); }
-task-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_T=
ASK_CLOCK); }
-page-faults|faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU=
NT_SW_PAGE_FAULTS); }
-minor-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW=
_PAGE_FAULTS_MIN); }
-major-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW=
_PAGE_FAULTS_MAJ); }
-context-switches|cs				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_CO=
UNT_SW_CONTEXT_SWITCHES); }
-cpu-migrations|migrations			{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PE=
RF_COUNT_SW_CPU_MIGRATIONS); }
-alignment-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT=
_SW_ALIGNMENT_FAULTS); }
-emulation-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT=
_SW_EMULATION_FAULTS); }
-dummy						{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY=
); }
-bpf-output					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_B=
PF_OUTPUT); }
-cgroup-switches					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT=
_SW_CGROUP_SWITCHES); }
+cpu-cycles|cycles				{ return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend	{ return hw(yyscanner, PERF_C=
OUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend	{ return hw(yyscanner, PERF_COU=
NT_HW_STALLED_CYCLES_BACKEND); }
+instructions					{ return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references				{ return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES)=
; }
+cache-misses					{ return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches			{ return hw(yyscanner, PERF_COUNT_HW_BRANCH=
_INSTRUCTIONS); }
+branch-misses					{ return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles					{ return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles					{ return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
+cpu-clock					{ return sym(yyscanner, PERF_COUNT_SW_CPU_CLOCK); }
+task-clock					{ return sym(yyscanner, PERF_COUNT_SW_TASK_CLOCK); }
+page-faults|faults				{ return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS); }
+minor-faults					{ return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
+major-faults					{ return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
+context-switches|cs				{ return sym(yyscanner, PERF_COUNT_SW_CONTEXT_SWITC=
HES); }
+cpu-migrations|migrations			{ return sym(yyscanner, PERF_COUNT_SW_CPU_MIGR=
ATIONS); }
+alignment-faults				{ return sym(yyscanner, PERF_COUNT_SW_ALIGNMENT_FAULTS=
); }
+emulation-faults				{ return sym(yyscanner, PERF_COUNT_SW_EMULATION_FAULTS=
); }
+dummy						{ return sym(yyscanner, PERF_COUNT_SW_DUMMY); }
+bpf-output					{ return sym(yyscanner, PERF_COUNT_SW_BPF_OUTPUT); }
+cgroup-switches					{ return sym(yyscanner, PERF_COUNT_SW_CGROUP_SWITCHES)=
; }
=20
 {lc_type}			{ return str(yyscanner, PE_LEGACY_CACHE); }
 {lc_type}-{lc_op_result}	{ return str(yyscanner, PE_LEGACY_CACHE); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index f888cbb076d6..d2ef1890007e 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -55,7 +55,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 %}
=20
 %token PE_START_EVENTS PE_START_TERMS
-%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
+%token PE_VALUE PE_VALUE_SYM_SW PE_TERM
 %token PE_EVENT_NAME
 %token PE_RAW PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
@@ -65,11 +65,9 @@ static void free_list_evsel(struct list_head* list_evsel)
 %token PE_DRV_CFG_TERM
 %token PE_TERM_HW
 %type <num> PE_VALUE
-%type <num> PE_VALUE_SYM_HW
 %type <num> PE_VALUE_SYM_SW
 %type <mod> PE_MODIFIER_EVENT
 %type <term_type> PE_TERM
-%type <num> value_sym
 %type <str> PE_RAW
 %type <str> PE_NAME
 %type <str> PE_LEGACY_CACHE
@@ -85,6 +83,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 %type <list_terms> opt_pmu_config
 %destructor { parse_events_terms__delete ($$); } <list_terms>
 %type <list_evsel> event_pmu
+%type <list_evsel> event_legacy_hardware
 %type <list_evsel> event_legacy_symbol
 %type <list_evsel> event_legacy_cache
 %type <list_evsel> event_legacy_mem
@@ -102,8 +101,8 @@ static void free_list_evsel(struct list_head* list_evse=
l)
 %destructor { free_list_evsel ($$); } <list_evsel>
 %type <tracepoint_name> tracepoint_name
 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
-%type <hardware_term> PE_TERM_HW
-%destructor { free ($$.str); } <hardware_term>
+%type <hardware_event> PE_TERM_HW
+%destructor { free ($$.str); } <hardware_event>
=20
 %union
 {
@@ -118,10 +117,10 @@ static void free_list_evsel(struct list_head* list_ev=
sel)
 		char *sys;
 		char *event;
 	} tracepoint_name;
-	struct hardware_term {
+	struct hardware_event {
 		char *str;
 		u64 num;
-	} hardware_term;
+	} hardware_event;
 }
 %%
=20
@@ -264,6 +263,7 @@ PE_EVENT_NAME event_def
 event_def
=20
 event_def: event_pmu |
+	   event_legacy_hardware |
 	   event_legacy_symbol |
 	   event_legacy_cache sep_dc |
 	   event_legacy_mem sep_dc |
@@ -306,24 +306,45 @@ PE_NAME sep_dc
 	$$ =3D list;
 }
=20
-value_sym:
-PE_VALUE_SYM_HW
+event_legacy_hardware:
+PE_TERM_HW opt_pmu_config
+{
+	/* List of created evsels. */
+	struct list_head *list =3D NULL;
+	int err =3D parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, $2, =
&list, &@1);
+
+	free($1.str);
+	parse_events_terms__delete($2);
+	if (err)
+		PE_ABORT(err);
+
+	$$ =3D list;
+}
 |
-PE_VALUE_SYM_SW
+PE_TERM_HW sep_dc
+{
+	struct list_head *list;
+	int err;
+
+	err =3D parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, NULL, &l=
ist, &@1);
+	free($1.str);
+	if (err)
+		PE_ABORT(err);
+	$$ =3D list;
+}
=20
 event_legacy_symbol:
-value_sym '/' event_config '/'
+PE_VALUE_SYM_SW '/' event_config '/'
 {
 	struct list_head *list;
-	int type =3D $1 >> 16;
-	int config =3D $1 & 255;
 	int err;
-	bool wildcard =3D (type =3D=3D PERF_TYPE_HARDWARE || type =3D=3D PERF_TYP=
E_HW_CACHE);
=20
 	list =3D alloc_list();
 	if (!list)
 		YYNOMEM;
-	err =3D parse_events_add_numeric(_parse_state, list, type, config, $3, wi=
ldcard);
+	err =3D parse_events_add_numeric(_parse_state, list,
+				/*type=3D*/PERF_TYPE_SOFTWARE, /*config=3D*/$1,
+				$3, /*wildcard=3D*/false);
 	parse_events_terms__delete($3);
 	if (err) {
 		free_list_evsel(list);
@@ -332,18 +353,17 @@ value_sym '/' event_config '/'
 	$$ =3D list;
 }
 |
-value_sym sep_slash_slash_dc
+PE_VALUE_SYM_SW sep_slash_slash_dc
 {
 	struct list_head *list;
-	int type =3D $1 >> 16;
-	int config =3D $1 & 255;
-	bool wildcard =3D (type =3D=3D PERF_TYPE_HARDWARE || type =3D=3D PERF_TYP=
E_HW_CACHE);
 	int err;
=20
 	list =3D alloc_list();
 	if (!list)
 		YYNOMEM;
-	err =3D parse_events_add_numeric(_parse_state, list, type, config, /*head=
_config=3D*/NULL, wildcard);
+	err =3D parse_events_add_numeric(_parse_state, list,
+				/*type=3D*/PERF_TYPE_SOFTWARE, /*config=3D*/$1,
+				/*head_config=3D*/NULL, /*wildcard=3D*/false);
 	if (err)
 		PE_ABORT(err);
 	$$ =3D list;
--=20
2.49.0.395.g12beb8f557-goog