From nobody Sun Feb 8 09:10:42 2026 Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (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 753EE3161AB for ; Thu, 16 Oct 2025 14:47:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626025; cv=none; b=pQbGkOM1LU6hMmpOyziY43l14TYiXfbGpPcvztdIJjqRRU8gaPiN8+eGJN5reUg68GuINu4Bz7y/jStbW5djgPPnRdCBVPEr9GPGpTuxmEiIy1wMKlNa+nFxuRODGmJm5ZY867rNe8OtOqDiBWWI4KrS1RL1sO9HSrXsBBZd1ys= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626025; c=relaxed/simple; bh=udG4u+C2ZRYoWfcR0oorTmw5eUGfOQlVhzCX6e7sXHQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=akKqfefMZrse/Fz+fCFTBpxZKAZFHONu3nBgiGZYUyj54ojECxjo/1Bh5lkoBGU4y5HVTDXd7UDp+oas2Wsn4cZcvqqyGJDRGHmZUw3+fBmLZnbhp3KWh7DZrVetV5cH7ATjTsjS+iGf7qu1rexTFdbUOO2EmFD9W5h2kY+pajI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.210.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f51.google.com with SMTP id 46e09a7af769-7b00927607eso585793a34.0 for ; Thu, 16 Oct 2025 07:47:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626022; x=1761230822; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oBHn6CsGRDAUCK2Z49Yacln3ofSUz8trsXQy6V4TvmY=; b=I7oBaMcKnWAm3Y6W4V7rMex9RbR9Rr/BxCxCILzGlrZ/AF4CVytz5TV2uGqmXkUJG3 IWIU4FD7XTMBAdFP8uKxCHKtQRKk/8L+gPTEFq4EmTzfR4cRBagPIxj+/rZMVUr+DTbp XDsLZmZHMpEb0g4hponQeANWjQ7H/G5rBfUchdCXTLx5UgbWjUOjbgW9Vh4pD7G/8lWC 2w8XgS3fx1dlxK99wQmDCvFe+URgze9EtXMxl+jkLvMEiuW2PLZnG+syO2D/YZSOjS83 dPkXpr9uMZYp7M+sZhZT0DCuZz8nV7y6069C1GGqjlnxvfFZEzB6NKXzjKXbiRY0VFf7 D4Aw== X-Forwarded-Encrypted: i=1; AJvYcCVuGlaWTq9jfZTu9bnreJYcJYVTCG2TQXuYT914e80l1qmH8Dzak7ilJwiV1ClJgO4/WimFMT0Sh+ySmWY=@vger.kernel.org X-Gm-Message-State: AOJu0YyJ7IuwKrYcGt8AMAhxxS7E7DkDD5rfRjQqqpU+1xMBt92/tdHV MSZ8dpYd4uIiNb00dsM5fEBc6V9oQPHifGN0joNmZy1w7QL596F2lxvG X-Gm-Gg: ASbGncuYsLLSZxAB4jSO95tY/DTbMPzKGD3B4eXsraI6EmtcyiaWasAy0A8G8GdY359 V8JlAT5HOwSrcYokqZYqypaoZqjxRoeKNuKvzTFwPlv16eld6wksJx6o9SQhYFiBEVjvEaICcas 4oHocVY+NpWd0n/EmF6xT3t4wNzqpJPBdrcN2ONdgh400+HnoE5B9zpvEFrDUodQHDtdYQPs73p 3KOA8iXbN3lvwmYCmIiBCwB34bmxKsQL6H0OlPjbOzNX260VZjdWLxbscpuUwn9FRM386S6QFtl V0aWukEteP/Zxp3C1CUFCTXt9v5/521hS75a4VsJGobt7GdLaIrxz5FsQHpgxnRiBH6uQ2wlUx7 7TX4lXDRYBZBPKLZ4QhwWwpBEb36f9GZXKbKgtz9ab4rt2w/YhcbqrVKNL+HCyTl7thCmMbVTrj sIsU3LIY+YpeW9EL/B5DijpzAnfp6wkB1pnOciMp3PzEAPQdxgL2mKCpywqjaXD5IeVh0= X-Google-Smtp-Source: AGHT+IFDXse00m2TWPZi7Thsyfiz1q30tLZZikOylS+Gewam/P4dv7Cstc52U+FEl+CdZhH12tCOWg== X-Received: by 2002:a05:6808:1514:b0:43f:6f82:e16f with SMTP id 5614622812f47-443a2dd8597mr136457b6e.12.1760626022395; Thu, 16 Oct 2025 07:47:02 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.01 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:02 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 1/8] resctrl: Pin rdtgroup for mon_data file lifetime Date: Thu, 16 Oct 2025 09:46:49 -0500 Message-ID: <20251016144656.74928-2-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add .open and .release handlers to mon_data kernfs files so a monitoring file holds a reference to its rdtgroup for the file's lifetime. Store the rdtgroup in of->priv on open and drop it on release. Provide rdtgroup_get()/rdtgroup_put() helpers. This lets code that only has an open monitoring fd (e.g. the resctrl PMU event_init path) safely resolve the rdtgroup without having a kernfs active reference. No functional change intended. Signed-off-by: Jonathan Perry --- fs/resctrl/internal.h | 2 ++ fs/resctrl/rdtgroup.c | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index cf1fd82dc5a9..63fb4d6c21a7 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -360,6 +360,8 @@ void resctrl_mon_resource_exit(void); void mon_event_count(void *info); =20 int rdtgroup_mondata_show(struct seq_file *m, void *arg); +int rdtgroup_mondata_open(struct kernfs_open_file *of); +void rdtgroup_mondata_release(struct kernfs_open_file *of); =20 void mon_event_read(struct rmid_read *rr, struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 0320360cd7a6..17b61dcfad07 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -332,6 +332,8 @@ static const struct kernfs_ops rdtgroup_kf_single_ops = =3D { static const struct kernfs_ops kf_mondata_ops =3D { .atomic_write_len =3D PAGE_SIZE, .seq_show =3D rdtgroup_mondata_show, + .open =3D rdtgroup_mondata_open, + .release =3D rdtgroup_mondata_release, }; =20 static bool is_cpu_list(struct kernfs_open_file *of) @@ -2512,12 +2514,26 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct k= ernfs_node *kn) } } =20 +/* + * Convert an kernfs active reference to an rdtgroup reference. + */ static void rdtgroup_kn_get(struct rdtgroup *rdtgrp, struct kernfs_node *k= n) { atomic_inc(&rdtgrp->waitcount); kernfs_break_active_protection(kn); } =20 +/* + * Get rdtgroup reference count from existing reference + */ +void rdtgroup_get(struct rdtgroup *rdtgrp) +{ + atomic_inc(&rdtgrp->waitcount); +} + +/* + * Decrement rdtgroup reference count, when converted from kernfs active r= ef + */ static void rdtgroup_kn_put(struct rdtgroup *rdtgrp, struct kernfs_node *k= n) { if (atomic_dec_and_test(&rdtgrp->waitcount) && @@ -2532,6 +2548,20 @@ static void rdtgroup_kn_put(struct rdtgroup *rdtgrp,= struct kernfs_node *kn) } } =20 +/* + * Decrement rdtgroup reference count + */ +void rdtgroup_put(struct rdtgroup *rdtgrp) +{ + if (atomic_dec_and_test(&rdtgrp->waitcount) && + (rdtgrp->flags & RDT_DELETED)) { + if (rdtgrp->mode =3D=3D RDT_MODE_PSEUDO_LOCKSETUP || + rdtgrp->mode =3D=3D RDT_MODE_PSEUDO_LOCKED) + rdtgroup_pseudo_lock_remove(rdtgrp); + rdtgroup_remove(rdtgrp); + } +} + struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn) { struct rdtgroup *rdtgrp =3D kernfs_to_rdtgroup(kn); @@ -3364,6 +3394,38 @@ static int mkdir_mondata_all(struct kernfs_node *par= ent_kn, return ret; } =20 +int rdtgroup_mondata_open(struct kernfs_open_file *of) +{ + struct rdtgroup *rdtgrp; + + rdtgrp =3D rdtgroup_kn_lock_live(of->kn); + if (!rdtgrp) { + rdtgroup_kn_unlock(of->kn); + return -ENOENT; + } + + /* + * resctrl relies an kernfs active references to guard access to struct + * rdtgroup from kernfs_open_file. Hold a reference in the file + * descriptor so perf_event_open() can retrieve the rdtgroup. + */ + rdtgroup_get(rdtgrp); + of->priv =3D rdtgrp; + + rdtgroup_kn_unlock(of->kn); + return 0; +} + +void rdtgroup_mondata_release(struct kernfs_open_file *of) +{ + struct rdtgroup *rdtgrp =3D of->priv; + + if (rdtgrp) { + rdtgroup_put(rdtgrp); + of->priv =3D NULL; + } +} + /** * cbm_ensure_valid - Enforce validity on provided CBM * @_val: Candidate CBM From nobody Sun Feb 8 09:10:42 2026 Received: from mail-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (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 782EB3431FE for ; Thu, 16 Oct 2025 14:47:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626026; cv=none; b=CuYaKXEzhyEPD/ayQ0E0f9MQERDU+6gU6edUTMcjBK32o26VUq1trElBqg2T5hJ6quZBtcs/RaPBR9iADkAx0YOIn2eLBAH0ZiC1ovxhAxxi/uAsdRu6/OaFov6nxDo7VMyMdlc3EJ6blKII3Ckg34T9GaRmDWMKkojIExxMeRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626026; c=relaxed/simple; bh=BtawZQfHc3r94zhdPsLAO1Sny98T6rBbY+VgVvkTtNI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=E1PxyAt+xFnyNT7te2DqyAWsreHa751z1X4CDVN/ZaLyUU9XlrLbD4WL/d0l/DI6nBjiNHOlVIWuyhTsj08W5L972icrTFVbdqT6A6Z4vUZWC/QojncL2re8eBBA9IB8LZXMHjr9yWjEaMZ+2iSKv8LApY80cCr2lNK76RnGiGg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.210.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f44.google.com with SMTP id 46e09a7af769-7bc626c5467so522570a34.2 for ; Thu, 16 Oct 2025 07:47:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626023; x=1761230823; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/EHCgPHyfakU523tKXhaAbUatgQF6sU/svILEddytVE=; b=Kl/ruCv3Rrz/DwXiZGQJ4wVf3x8SWONRu+dG8Y9FNMuPEGU61GJWJ52oat+BVBstjC 00gjUJpinH4yoKo5e2IKdRYx8ktR82wEQApRRLxqn8KHG58hAegAYxtQNy8eM/iMG4EU PCH9+614r80SZlwXEZkC3Mwj1j94RWWxwm3ETAQu/4um1I3GBKAEyJTkCPnwRLMtWs/w cMZx9pSILTTddbRIT5FCO8DKFkLeBtAG7OxozTbu/RPhQ2AqdmXIFhQxVDK+OEfGtDCL sRodn9zqDOyTTYwXl9TXLHaFCy9P0L1oMk9u+pa+Ymxf0/VXKBGwQtqHBtxn2F2Q6hRa dREQ== X-Forwarded-Encrypted: i=1; AJvYcCVQNK/g9wSYeM4H0xm9sw2nSkLS/N64i9RI4twZO2trMmNXXle7DX1ytIqBqG5MX/+TfaIoA8Ix6q1Y3dM=@vger.kernel.org X-Gm-Message-State: AOJu0YwHcjUJkrJQLV4B0V96I8yB9nbtFLtggC1xvzJgG28U6jUARh/Q geloxdNhlYunh/QWFBGEt5NggAB+UcCp3/caAMqbctUknt+SFad6TDv9 X-Gm-Gg: ASbGncts16jDgGmTdXuxmuTUtM54+OyRA03EcyE+Maz+P9391cfqq/OLd631Km3dKCA UhgRtcjeb+rZLEjOAJ7H8jESoIL6DAfKdcMEhcdm/FWF0F0kC/U4+u9JDqpxz2gQT0ESzeVAlqC KopkTN+sqmGQiE+nPxf/SuFJyvLY8WmIUzoNQEKkFeyuviX36iFacWs6mrdPtwDx8hcAYNHDdfB 1yE53B17Xi9D2pDM7GH+QOtj838WgUSPj4T3dsByAQ6GibYLbpLN8NbHk6jCvyZ08GKDGYF08Oe 1pPBeUPSON9ghgugguH/GUjN3lUkdFKWaWyM1F++hq/+ac7VU2Q808IHOFMu9i/Ms6sejQe4G7p CoVNrD7vwveblOEnGDTb8jOhK0xZjW73M8SWPJHd3fP50wRwAcx+GJahN2KRogwmbBB3jdBkddB r1/LEMrCz3yw5pr9j/pz9cFpdv31Dljbn1VVbyoRITj+Kw1qFaUKEGJ6Zt X-Google-Smtp-Source: AGHT+IFaoc5h662tQMy3sYuAt7P7VYvJhJI8+JkPL9/LadjSZTqNRwdw+T5zs/QxcPeMC09gOumcZw== X-Received: by 2002:a05:6808:250a:b0:441:c9c5:b76d with SMTP id 5614622812f47-443a2e63051mr110288b6e.28.1760626023486; Thu, 16 Oct 2025 07:47:03 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.02 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:03 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 2/8] resctrl/mon: Split RMID read init from execution Date: Thu, 16 Oct 2025 09:46:50 -0500 Message-ID: <20251016144656.74928-3-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce rmid_read_init() to fill struct rmid_read (resource, domain, rdtgroup, event id, flags, ci). Change mon_event_read() to accept a prepared rmid_read and a CPU mask. Update callers to use rmid_read_init() + mon_event_read(). This prepares reuse from contexts that pre-select the CPU (e.g. the perf PMU) without duplicating initialization logic. No functional change intended. Signed-off-by: Jonathan Perry --- fs/resctrl/ctrlmondata.c | 40 ++++++++++++++++++++++------------------ fs/resctrl/internal.h | 5 +++-- fs/resctrl/rdtgroup.c | 6 ++++-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 0d0ef54fc4de..82f8ad2b3053 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -546,28 +546,31 @@ struct rdt_domain_hdr *resctrl_find_domain(struct lis= t_head *h, int id, return NULL; } =20 -void mon_event_read(struct rmid_read *rr, struct rdt_resource *r, +void rmid_read_init(struct rmid_read *rr, struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, - cpumask_t *cpumask, int evtid, int first) + int evtid, int first, struct cacheinfo *ci) { - int cpu; - - /* When picking a CPU from cpu_mask, ensure it can't race with cpuhp */ - lockdep_assert_cpus_held(); - - /* - * Setup the parameters to pass to mon_event_count() to read the data. - */ + memset(rr, 0, sizeof(*rr)); rr->rgrp =3D rdtgrp; rr->evtid =3D evtid; rr->r =3D r; rr->d =3D d; rr->first =3D first; + rr->ci =3D ci; if (resctrl_arch_mbm_cntr_assign_enabled(r) && - resctrl_is_mbm_event(evtid)) { + resctrl_is_mbm_event(evtid)) rr->is_mbm_cntr =3D true; - } else { - rr->arch_mon_ctx =3D resctrl_arch_mon_ctx_alloc(r, evtid); +} + +void mon_event_read(struct rmid_read *rr, cpumask_t *cpumask) +{ + int cpu; + + /* When picking a CPU from cpu_mask, ensure it can't race with cpuhp */ + lockdep_assert_cpus_held(); + + if (!rr->is_mbm_cntr) { + rr->arch_mon_ctx =3D resctrl_arch_mon_ctx_alloc(rr->r, rr->evtid); if (IS_ERR(rr->arch_mon_ctx)) { rr->err =3D -EINVAL; return; @@ -588,7 +591,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_re= source *r, smp_call_on_cpu(cpu, smp_mon_event_count, rr, false); =20 if (rr->arch_mon_ctx) - resctrl_arch_mon_ctx_free(r, evtid, rr->arch_mon_ctx); + resctrl_arch_mon_ctx_free(rr->r, rr->evtid, rr->arch_mon_ctx); } =20 int rdtgroup_mondata_show(struct seq_file *m, void *arg) @@ -635,9 +638,9 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) ci =3D get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); if (!ci) continue; - rr.ci =3D ci; - mon_event_read(&rr, r, NULL, rdtgrp, - &ci->shared_cpu_map, evtid, false); + rmid_read_init(&rr, r, NULL, rdtgrp, + evtid, false, ci); + mon_event_read(&rr, &ci->shared_cpu_map); goto checkresult; } } @@ -654,7 +657,8 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) goto out; } d =3D container_of(hdr, struct rdt_mon_domain, hdr); - mon_event_read(&rr, r, d, rdtgrp, &d->hdr.cpu_mask, evtid, false); + rmid_read_init(&rr, r, d, rdtgrp, evtid, false, NULL); + mon_event_read(&rr, &d->hdr.cpu_mask); } =20 checkresult: diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index 63fb4d6c21a7..dcc0b7bea3ac 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -363,9 +363,10 @@ int rdtgroup_mondata_show(struct seq_file *m, void *ar= g); int rdtgroup_mondata_open(struct kernfs_open_file *of); void rdtgroup_mondata_release(struct kernfs_open_file *of); =20 -void mon_event_read(struct rmid_read *rr, struct rdt_resource *r, +void rmid_read_init(struct rmid_read *rr, struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, - cpumask_t *cpumask, int evtid, int first); + int evtid, int first, struct cacheinfo *ci); +void mon_event_read(struct rmid_read *rr, cpumask_t *cpumask); =20 int resctrl_mon_resource_init(void); =20 diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 17b61dcfad07..34337abe5345 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -3235,8 +3235,10 @@ static int mon_add_all_files(struct kernfs_node *kn,= struct rdt_mon_domain *d, if (ret) return ret; =20 - if (!do_sum && resctrl_is_mbm_event(mevt->evtid)) - mon_event_read(&rr, r, d, prgrp, &d->hdr.cpu_mask, mevt->evtid, true); + if (!do_sum && resctrl_is_mbm_event(mevt->evtid)) { + rmid_read_init(&rr, r, d, prgrp, mevt->evtid, true, NULL); + mon_event_read(&rr, &d->hdr.cpu_mask); + } } =20 return 0; From nobody Sun Feb 8 09:10:42 2026 Received: from mail-oi1-f182.google.com (mail-oi1-f182.google.com [209.85.167.182]) (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 90AB3343D9C for ; Thu, 16 Oct 2025 14:47:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626027; cv=none; b=Sc5Pk8T07sbmMkLQNUxh4r9+LkL6vvrBwZ7iD4SYtWPxDFHRiomHT6O7uLxip/2x4aGdoTBcK/jIE+6y4baqhwpek3gfACWgu5SW7SIkDAJFaF/awW5l3DvnZMiaQo6XLOEzFotQmjI95ZOoI2chzI5PIUeKbGeLxuj300OVmeM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626027; c=relaxed/simple; bh=5Mr6LH7k/o5N9dQgkLvHYmi0+jVFwD/oBoWEfwCDc/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=R+vh/ilqonzqhnZDPmKj/VgMspAInGPGDcNQ7MSNnxmHl+HqHb/3qUzHtgeeDhRoErWpfz/msZaeWp04e1/3S6K3m89C8VVqnhGpB0LuWSpX1z+i4XD6gtkUjV5vYyxn/FYgPY52fVhkSyH1KBfZy1vPoNC3tB7Gjm53/t+FNq8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.167.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oi1-f182.google.com with SMTP id 5614622812f47-43f64a5014aso489404b6e.1 for ; Thu, 16 Oct 2025 07:47:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626024; x=1761230824; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+ChrD91ZzeSyIGW13Mo1kwbcyPzEVs4Rp2LDBd96Ha0=; b=Mm/Zb+lTS4kstoGKLd+A/7J25sADOZZ4/UrVAOzRNichV5BzCEsE5QgxqKMZoowXU4 et+D0YOCGT7aLFJnU4BrlF4BX2X3VThvWbHAcbquV3MYHPQ236PCuRKqRWk6uEAXo/8K bf/a61wud+O8UTbXNucwS5Nq4hpw+WWCj5/NCeCCTuFTUxZTEvOQj5vBO/bnrAQn/FjY DTzHzpWUOtZnuA8WV8XryAK69VAWYI7nYh/Z1tIPlX5IWjdqK01wlClbpZMNqrN17dUZ x9mLch4AzhCFby1fK0qh5pSqsj4GGjLFJ1dKiQXLckCpm/lQqj7qtgXjCDvbMtGaotu3 u+5A== X-Forwarded-Encrypted: i=1; AJvYcCVEyo9BNROZWTLJmxIJtEXMm/5f3DXJpxAT3UVeNaf8Xa249v+dASvdL+3i2eB32c334/dRioRCwfRqs4E=@vger.kernel.org X-Gm-Message-State: AOJu0YxZ8CiRYIOjDjdgInCzBU1ID3zLXmL97hDDHtejDNk2BClGkF6M zJOtTN94oime73p9ebAIx4iq8hWmqjBKZLFaiA16VgN/ABVfk0WdzgNS X-Gm-Gg: ASbGncvYJVT1dR+hsbZlPXBheINfDZAyoUkxmlQRyRehGYLmpPOjhUgFI700kCZaen9 vNrq15GWIueDs98xHUMYwfnGQTBQzdacRptx1Yj+cSguKfzHqoivGkFPpn0FDcVlIcIAsS8fwl2 GHuMfUWEgoktfOagjqIaLcRP3WptqvWV+JfpEDgCC51/J3rdMMtLtMwBXd0uU9HHlUKJt22ffFV VySwK/Qxow0nwM/EmUXnUZNcIYypHI9LBNGBLfZ/TB7BWgZk+jbTqHgo4z1Ld6nmLWiGTk0sTAp cb5NvoltyKexpgL4JzFbCr1NOCqzQFHSdQHbRIu0G1bNheRg6ucuViPmWd6WxeBlYOzY2TBwDPx F6Q5fWbqtKbhl+CBjFBuX84mbwl4DtS4PUHL23S0Vi4uv4LIZVXUCh+LODXiMT5c+90p34FMY2A KlebDXN1X2aLNCJH0xyFxcMG+3eBjKZMO8ZCTLVWJZD/Abg3MF/OtNSCBn+rYrtF5AoR99BxGSx JaGxw== X-Google-Smtp-Source: AGHT+IGuFXjZd7WjvD1BFyxWZ/lTP2idxYYov/LGI6HCXqPlTW9NLsW1AmAB2FZK/Y+DjuFd+yYXvg== X-Received: by 2002:a05:6808:1512:b0:43f:7a07:44d7 with SMTP id 5614622812f47-443a305da05mr102589b6e.47.1760626024580; Thu, 16 Oct 2025 07:47:04 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.03 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:04 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 3/8] resctrl/mon: Select cpumask before invoking mon_event_read() Date: Thu, 16 Oct 2025 09:46:51 -0500 Message-ID: <20251016144656.74928-4-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor rdtgroup_mondata_show() to pick the appropriate CPU mask first and then call mon_event_read() once. No functional change intended. Signed-off-by: Jonathan Perry --- fs/resctrl/ctrlmondata.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 82f8ad2b3053..f28328c49479 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -607,6 +607,7 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) struct rdt_resource *r; struct cacheinfo *ci; struct mon_data *md; + cpumask_t *cpumask; =20 rdtgrp =3D rdtgroup_kn_lock_live(of->kn); if (!rdtgrp) { @@ -639,9 +640,9 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) if (!ci) continue; rmid_read_init(&rr, r, NULL, rdtgrp, - evtid, false, ci); - mon_event_read(&rr, &ci->shared_cpu_map); - goto checkresult; + evtid, false, ci); + cpumask =3D &ci->shared_cpu_map; + goto perform; } } ret =3D -ENOENT; @@ -658,10 +659,11 @@ int rdtgroup_mondata_show(struct seq_file *m, void *a= rg) } d =3D container_of(hdr, struct rdt_mon_domain, hdr); rmid_read_init(&rr, r, d, rdtgrp, evtid, false, NULL); - mon_event_read(&rr, &d->hdr.cpu_mask); + cpumask =3D &d->hdr.cpu_mask; } =20 -checkresult: +perform: + mon_event_read(&rr, cpumask); =20 /* * -ENOENT is a special case, set only when "mbm_event" counter assignment From nobody Sun Feb 8 09:10:42 2026 Received: from mail-oa1-f45.google.com (mail-oa1-f45.google.com [209.85.160.45]) (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 6BE203451B8 for ; Thu, 16 Oct 2025 14:47:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626029; cv=none; b=dEdkKpXfff8afgOaDgOMq7SJt3GmRa+5cTBnEi72oHoQC7cPoTvcu2Uw2cP2zaBCo4JbbRSpSmAXgXTeZDztW7kpHv/OwpTJkjkO5cRLNcRn4JW7/YlfiAMe4Gs3K70yPnyVFaEypYFNyHM2s6rWVEjh9W3kgQPhU3WOQ7D2fUk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626029; c=relaxed/simple; bh=vxd5viqIAF53p9qHcx2+SSC6DWLKIshKJ2YVAGNmP6A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ez2UUf1tbJFYzUSyhSnSySZuA/30wLPhYiGnnk38Zv/iALLmN9VGXqG3tFPP1yIyHdjdHC3vbXQ2UG8styOuJNjsmxkmm0F7YU3lSy1PQi7kOoMDQJ377ByBCmj5GoULnAsksEtgjKnOcBMyiq9xEhXUsPj0ebZzKx/2ru8md8A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.160.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f45.google.com with SMTP id 586e51a60fabf-3c972dec6easo517756fac.3 for ; Thu, 16 Oct 2025 07:47:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626025; x=1761230825; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WkeQ5GVzAIUDDgYC2BBLNxE47r9RQHz/6gTcvpiCb7E=; b=WEyuGW7fOZ5FtQ5vTzRpceyv/k6s1sZ4Nb5JyMiXdTASPdlTYBrJUbPeTGub9RUcfU Dr1879doOxONdt7wTxtmkv78ocBSX/lypUwxqDi0O7PD1xyIUYWQefEqKOEb0myrjqPa L/w5P5azM4qs3Ou+WhknSCfkspKut7qPvuDE6XZUhREV8H5Skx71JA73sz0LTFweVtaj +WKDkdQ1Pywbdz5helAPjpbCFAzKpyXeA97bYrtSn2bCsn7IC+m49npljH8tBVZ6lBPt nkyhGj1pw2+3kIHhPUe8mc41RZ9gmoQvO6ybVNNbMWnAnY5YhcpALvXc5UHwUUKhpRUp fy4Q== X-Forwarded-Encrypted: i=1; AJvYcCX4o8DNIHZGaiHbVx+zRrv0Gdw3PzbJE2cein3cyYZEMEoBXkbjcHI0H8y766HbVpcJ2RSMUDj1hDni7vw=@vger.kernel.org X-Gm-Message-State: AOJu0YwOzPrZxEIEj1EYNlfjlYM/pmy8VSirnsvZd15He73MdHHEXw9T VKAhskxbvavxmxMttgy0kTt+ZDKO4/QRdRDvxpz8vYY8KGA8JViojVU1 X-Gm-Gg: ASbGnct11Hm36cFPfGtHxCcQempNOKs+qgSltcM4zmUNZ4GvsqoPHMaKkfRSa79jKFz DhkUtfXROCdSsqYuC3sX/P1qkqKQ5mHuu1bbLaJnBrHASXN235u/Yz1gIa6+58gluBA9rHQlff6 yiHlrOcc0uEPsAqWhM+qq4fJiosLkspfjWFa/2oIs7aM4kGGuxPN9C9XDPe7ENsqKXBBhCI2OEB xjbD3qqcrKBb75MlBIkewtf6dc8qdCFjVoKRamhujaGx3APjImyVUj2Wi0Hbbhlz0RCQ/j2t8jg btyeoQ95N7JFdJ25w4MsLLEx2IKqPeAt1pokrVGKGxbufbi9kCfY+ILqRvga931+ANjJIZBPr4K rni4+Ijn7A0xQM/YjIDpWd/kcWaUlm6M4ERzBNkGhbD45PgbwJ4/qn3Fz4h6A4kIxkgVzObDNoz J8p68u3db2oJMHd3DHnwCj7uBkzupRa+FAgd34SqkOqO6HrOZ2lsX4ZPd6 X-Google-Smtp-Source: AGHT+IHad8QU7400Suvztwz7R3TknwRXuPTBhGJThjhex4bA27wajLbo4tHyKKwflCEojRIUm28PFg== X-Received: by 2002:a05:6808:14c5:b0:43f:507f:ced2 with SMTP id 5614622812f47-443a2f1b8camr127533b6e.23.1760626025484; Thu, 16 Oct 2025 07:47:05 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.04 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:05 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 4/8] resctrl/mon: Create mon_event_setup_read() helper Date: Thu, 16 Oct 2025 09:46:52 -0500 Message-ID: <20251016144656.74928-5-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor the selection of monitored event from the kernfs seq_show handler to a helper function. This provides a single setup path that the resctrl PMU will reuse. Add mon_event_setup_read() to encapsulate domain lookup, rmid_read_init(), and selection of the valid CPU mask for the read. Rework rdtgroup_mondata_show() to call the helper before reading. No functional change intended. Signed-off-by: Jonathan Perry --- fs/resctrl/ctrlmondata.c | 71 ++++++++++++++++++++++------------------ fs/resctrl/internal.h | 2 ++ 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index f28328c49479..d1e4cf6f2128 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -594,32 +594,16 @@ void mon_event_read(struct rmid_read *rr, cpumask_t *= cpumask) resctrl_arch_mon_ctx_free(rr->r, rr->evtid, rr->arch_mon_ctx); } =20 -int rdtgroup_mondata_show(struct seq_file *m, void *arg) +int mon_event_setup_read(struct rmid_read *rr, cpumask_t **cpumask, + struct mon_data *md, struct rdtgroup *rdtgrp) { - struct kernfs_open_file *of =3D m->private; enum resctrl_res_level resid; enum resctrl_event_id evtid; struct rdt_domain_hdr *hdr; - struct rmid_read rr =3D {0}; struct rdt_mon_domain *d; - struct rdtgroup *rdtgrp; - int domid, cpu, ret =3D 0; struct rdt_resource *r; struct cacheinfo *ci; - struct mon_data *md; - cpumask_t *cpumask; - - rdtgrp =3D rdtgroup_kn_lock_live(of->kn); - if (!rdtgrp) { - ret =3D -ENOENT; - goto out; - } - - md =3D of->kn->priv; - if (WARN_ON_ONCE(!md)) { - ret =3D -EIO; - goto out; - } + int domid, cpu; =20 resid =3D md->rid; domid =3D md->domid; @@ -639,30 +623,53 @@ int rdtgroup_mondata_show(struct seq_file *m, void *a= rg) ci =3D get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); if (!ci) continue; - rmid_read_init(&rr, r, NULL, rdtgrp, - evtid, false, ci); - cpumask =3D &ci->shared_cpu_map; - goto perform; + rmid_read_init(rr, r, NULL, rdtgrp, + evtid, false, ci); + *cpumask =3D &ci->shared_cpu_map; + return 0; } } - ret =3D -ENOENT; - goto out; + return -ENOENT; } else { /* * This file provides data from a single domain. Search * the resource to find the domain with "domid". */ hdr =3D resctrl_find_domain(&r->mon_domains, domid, NULL); - if (!hdr || WARN_ON_ONCE(hdr->type !=3D RESCTRL_MON_DOMAIN)) { - ret =3D -ENOENT; - goto out; - } + if (!hdr || WARN_ON_ONCE(hdr->type !=3D RESCTRL_MON_DOMAIN)) + return -ENOENT; + d =3D container_of(hdr, struct rdt_mon_domain, hdr); - rmid_read_init(&rr, r, d, rdtgrp, evtid, false, NULL); - cpumask =3D &d->hdr.cpu_mask; + rmid_read_init(rr, r, d, rdtgrp, evtid, false, NULL); + *cpumask =3D &d->hdr.cpu_mask; + return 0; } +} =20 -perform: +int rdtgroup_mondata_show(struct seq_file *m, void *arg) +{ + struct kernfs_open_file *of =3D m->private; + struct rmid_read rr =3D {0}; + struct rdtgroup *rdtgrp; + int ret =3D 0; + struct mon_data *md; + cpumask_t *cpumask; + + rdtgrp =3D rdtgroup_kn_lock_live(of->kn); + if (!rdtgrp) { + ret =3D -ENOENT; + goto out; + } + + md =3D of->kn->priv; + if (WARN_ON_ONCE(!md)) { + ret =3D -EIO; + goto out; + } + + ret =3D mon_event_setup_read(&rr, &cpumask, md, rdtgrp); + if (ret) + goto out; mon_event_read(&rr, cpumask); =20 /* diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index dcc0b7bea3ac..486cbca8d0ec 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -366,6 +366,8 @@ void rdtgroup_mondata_release(struct kernfs_open_file *= of); void rmid_read_init(struct rmid_read *rr, struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, int evtid, int first, struct cacheinfo *ci); +int mon_event_setup_read(struct rmid_read *rr, cpumask_t **cpumask, + struct mon_data *md, struct rdtgroup *rdtgrp); void mon_event_read(struct rmid_read *rr, cpumask_t *cpumask); =20 int resctrl_mon_resource_init(void); From nobody Sun Feb 8 09:10:42 2026 Received: from mail-oo1-f44.google.com (mail-oo1-f44.google.com [209.85.161.44]) (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 4C8943451D4 for ; Thu, 16 Oct 2025 14:47:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626028; cv=none; b=q+y7i87o0QgcvVQdbrTWiWGEa1rsdODqf+jGo7NMp37bb5Q4la8EM6ORjKANNcJdnn3IWoofVFq70mvyCP2US5dJMsmY1AtBrdwVwwWB4ZwR1nhgugwCGd9/HfEDWSZCnfEMZ9bsi8BSmm7VOHPIP1vsz7jkO2eGaJXThQpDhVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626028; c=relaxed/simple; bh=qrYx4OQbtVttMxYPNSKZyKUM/2EziepE/DMT9sZuO9M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MkDipp+oaAqHfO27lZ8qwPopnkpZbbSw8VG2TUPfE26ONobi87cI0d/9DJUObPsgSzdMqOYrF2SAcFZ53rSd+uAElbDdJ/XD6W0MA4xaHHWrE6iQy4BFeavyl2e/WgJ41uj2WzbRGx6PrVMrTDmEQEYy0pnd/jmRYN4YjKOhSd8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.161.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo1-f44.google.com with SMTP id 006d021491bc7-651c521980cso201222eaf.2 for ; Thu, 16 Oct 2025 07:47:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626026; x=1761230826; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=P6FTC4pXxezWlArm57ZmRQwBfAYH7sPfczRlTm0tzCY=; b=KJ+EGm9BsgG/veLP+hLNS51rIoOSHDkUyxwHy7KHUrudKGUcxfvnYzSm6UCAVkk6Pu uBSSBZXBjHbu2ZXT0TfC8DUi8Fpeg9E9LSeLp0lh7UJpRq7V1HyeeqwAPZytmHwh1/hU sLImSicyMeUEiP/tGHt0fcb6Sm8hkvLdPinLETlBTTMa0lGBjvBoN9N1adLaa7p3MLrQ okamhjqndIBJPIt2hH8LwZC60a1CF6gP2F9ghsmkFyTmnerFBO+5dh0PGNci1XL3GYpm qG5TP+orTDFk/9o5UA2HHxrbIDvAy65IP23xnKzL/RjEUdoqND/fSg7YPXCuWM/nXTf8 +olQ== X-Forwarded-Encrypted: i=1; AJvYcCXnB5Coeqxr5Ftd3A//00NxSq4On7FsmV8YuN6mqOhLKLieygWkVZv1s6wFfIXtOvs9ocU64eYXw9Ef1aY=@vger.kernel.org X-Gm-Message-State: AOJu0YwbrR/yBxQx4mqT36TftrVD4DEu0IMIOpPJhGYfiOkOFHjKFHuW OFxOwfR8HMugE6Enb6EO8P1BnMLqABmeOcB4YtvMVjUkI8uMz31KdBZk X-Gm-Gg: ASbGncuSPZBvgn+lg1FTq596VH1rX8sRrycpHvuBAnnr1XJqpovqqQLigSVCp9vXER8 1huKiHm+0hLE7syk4K3ygZJEVO5wCDzEh3vzXIC/E647seljIYE0Pj0LHQBjpEAZPF4h7Sh0q+G e/60K1qaa4nEk1QqLcMLnrnUE0aUR19VdKcR7eG11G7OMrCO5tQ2Mw9JBvw9ySDq+TbzL439ww4 cIsWodIWv1ICy+DINNoiduRvnKuxTT0IEIbSQZ82p9ZzVMmm6cA/bqIM187P6fA/NR9ZZFb7Tvo aE0CPNsQYZg9Qvm2EDAGaUM24q5JvoAi44V6q6RbiRAP6uPi6Q4nJhq9G9+4uGBrkQwOmJKIWvf H6s5MMsuxpgWXok86KpHiZiTMn2lXbkv/+y/EvANC8F7UgKvy3RSgp4LiYzR2yfjS88i9B9rsx/ FCkaFKdfB18DoIDuHL662EF6ax/ANG1DfhRlvi6hwBeX2DiHOtovyHDFYsV1iXHXhikQI= X-Google-Smtp-Source: AGHT+IEqY0Itcc1XjdzEUHZg7NibgLkNaNHb6IF/rm8TnzxUng5S0hLv2Izsxr0tjhoHkMDieMlXEQ== X-Received: by 2002:a05:6808:4f0a:b0:441:fb07:c178 with SMTP id 5614622812f47-443a2ed0503mr112853b6e.8.1760626026415; Thu, 16 Oct 2025 07:47:06 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.05 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:06 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 5/8] resctrl: Propagate CPU mask validation error via rr->err Date: Thu, 16 Oct 2025 09:46:53 -0500 Message-ID: <20251016144656.74928-6-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When __mon_event_count() rejects a CPU because it is not in the domain's mask (or does not match the cacheinfo domain), it returned -EINVAL but did not set rr->err. mon_event_count() then discarded the return value, which made failures harder to diagnose. Set rr->err =3D -EINVAL before returning in both validation checks so the error is visible to callers and can trigger WARN_ONCE() in the PMU .read path. Signed-off-by: Jonathan Perry --- fs/resctrl/monitor.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index 4076336fbba6..4d19c2ec823f 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -445,8 +445,10 @@ static int __mon_event_count(struct rdtgroup *rdtgrp, = struct rmid_read *rr) =20 if (rr->d) { /* Reading a single domain, must be on a CPU in that domain. */ - if (!cpumask_test_cpu(cpu, &rr->d->hdr.cpu_mask)) + if (!cpumask_test_cpu(cpu, &rr->d->hdr.cpu_mask)) { + rr->err =3D -EINVAL; return -EINVAL; + } if (rr->is_mbm_cntr) rr->err =3D resctrl_arch_cntr_read(rr->r, rr->d, closid, rmid, cntr_id, rr->evtid, &tval); @@ -462,8 +464,10 @@ static int __mon_event_count(struct rdtgroup *rdtgrp, = struct rmid_read *rr) } =20 /* Summing domains that share a cache, must be on a CPU for that cache. */ - if (!cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map)) + if (!cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map)) { + rr->err =3D -EINVAL; return -EINVAL; + } =20 /* * Legacy files must report the sum of an event across all From nobody Sun Feb 8 09:10:42 2026 Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (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 8258F3451BE for ; Thu, 16 Oct 2025 14:47:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626030; cv=none; b=l5yDJJfm9XTyfqG7OTEYFlTl/+RUF+S3rhu5X6pTP10HNaM/a8yl7hBa6qUNJ8HY7Y+o/2pTU54R23LpCBTjYs4AaH7dE+jjWgjrFv+QV0+NRsToQ5YO0iUfII1eNDoYNTw2ClGtSSCGphm3V64sxSBzi/qqWenW+wY3nlmcbFk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626030; c=relaxed/simple; bh=4PkymEnoVdRtepOzzfqNBr9XSbvC+t1sAFB6PLtH3vg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j+N+ZPz79wt8HFH2F1EcFJoW3W0uTglG1Be5YVoU0OkZMpv51zemZH3slDqx/8qt7Uzn9ZvQj2+QQeGdC2WZIC2/4vWfobpRvRs6KqoeMGHU2lfVB8CNXFZs6BWV0vYEt9HdDIgOJu+UBYN1rxweEfKCSwkK/Gvmj/xHy6I7lF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.210.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f51.google.com with SMTP id 46e09a7af769-7ae21804971so280075a34.0 for ; Thu, 16 Oct 2025 07:47:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626027; x=1761230827; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ur3B9LnadG5KKvwOBpgGnRJ5DQSqBj6YAeCWZFDvocU=; b=EeA//vC+ZyCgtb3NyOUf4LcDlGlM2ZtHqYfDzmzJKq5WkU6fKJUPRUISR+bHhsOcHg Fa5yz9BK/erJ5tUBq9+NbTr8Q49Iqzt+2Z/LrNy9UnmRNsKv1iChlm1kDOVgeWDT3wuk Ur8uEG4TpDp6tndsiWYiBwKoa1UJnYzzCzSVJmy99N09Adf3VYL1f/hM0fpb00gpMzSN EzFS/HVM76YmgiIXLww5MB9dc3L13+Mko3MO1z7S71tsKgja8OMmy8ihWSvsW7wPPsIO YRt3M84Jo6v+dv9jKp/Uyr+H+lq0Z1vgjK9kMwC3/Ss5iG5ldpVDtc8IhH6LVQCTyHmc bNxw== X-Forwarded-Encrypted: i=1; AJvYcCUrhrHHdPekByw52jTkJHW4kAvRTaJ7v6tgS7weXqbKe9ZgDhUOURm8NKo2o699Qna+iTVY4+VIw1Dl1qc=@vger.kernel.org X-Gm-Message-State: AOJu0YwUkhgPHyptPEiAWBlfNKPq2AFDRbtk2SrQD3OgjMeYUE38k2U6 HGSmCNpW5NAfP8W15qKmVKOE/FTFWX1EWTjq5blFJAqDvpkejTJ5MKBl X-Gm-Gg: ASbGncsC7377Dw7YNpZv87iwpwdjKMFbfiTcndKgnjBjSYRJU+NDxs12ZD4LvSKp1U9 xHP5+2bP2/lWScR6sQPPd9WqruK8mkkpyjoeTbcfw7YHh9Y/K/TfoH+oJ+aOqwoWeDpkhkB/1DW qeFulgd58itTyVC0TDBPpChPEYabXlaioszXj3s2R/+ZnUYmCm6Xj6IsbiJU4o9Ic037Y1zDEjp DU+tCWRPkcIpjmb0byhBCmm4ceTgk6Ma37A8B0pqIOavZT4NLK593vYButmviZvleWtY2Ry+XKR sboWbewFDy2o6WHapqRV+AhTE9AfUOCF+UaM4OoP4SzqFJE0Q4YiIVgp6keFAUDYP6OHQpFPwfy cZAtGJYj8i1oQssZsH70cKu+uqnbcrKU6sc2m/GYWRwW5umT7iek5FmP2N6EkC7MmHPGsT+O5sF oHnG8anOu4FMsrlRv/wsoiffxhDcQ93ynNLi/4UQrVVUVS2RPAhnJwOsmh/k2euY24YHE= X-Google-Smtp-Source: AGHT+IH6p3EoDt2Q2OjQfChqhrM9XWfpgsCGhAglt0qBiNiKR3HS881D+1RpYhTtN0m0f3G7oz8JfQ== X-Received: by 2002:a05:6808:18a7:b0:438:8ad:16b9 with SMTP id 5614622812f47-443a30d1062mr72092b6e.32.1760626027423; Thu, 16 Oct 2025 07:47:07 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.06 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:07 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 6/8] resctrl/pmu: Introduce skeleton PMU and selftests Date: Thu, 16 Oct 2025 09:46:54 -0500 Message-ID: <20251016144656.74928-7-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Register a read-only "resctrl" PMU and implement minimal perf hooks (event_init, add, del, start, stop, read, destroy). The PMU accepts a resctrl monitoring file descriptor via attr.config, resolves the rdtgroup, and pins it for the event's lifetime. Call PMU init/exit in resctrl_init()/resctrl_exit(). Add a selftest to exercise PMU registration and verify that only allowed monitoring files can be opened via perf. Signed-off-by: Jonathan Perry --- fs/resctrl/Makefile | 2 +- fs/resctrl/internal.h | 12 ++ fs/resctrl/pmu.c | 139 ++++++++++++ fs/resctrl/rdtgroup.c | 53 +++++ tools/testing/selftests/resctrl/pmu_test.c | 202 ++++++++++++++++++ tools/testing/selftests/resctrl/resctrl.h | 1 + .../testing/selftests/resctrl/resctrl_tests.c | 1 + 7 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 fs/resctrl/pmu.c create mode 100644 tools/testing/selftests/resctrl/pmu_test.c diff --git a/fs/resctrl/Makefile b/fs/resctrl/Makefile index e67f34d2236a..f738b0165ccc 100644 --- a/fs/resctrl/Makefile +++ b/fs/resctrl/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_RESCTRL_FS) +=3D rdtgroup.o ctrlmondata.o monitor.o +obj-$(CONFIG_RESCTRL_FS) +=3D rdtgroup.o ctrlmondata.o monitor.o pmu.o obj-$(CONFIG_RESCTRL_FS_PSEUDO_LOCK) +=3D pseudo_lock.o =20 # To allow define_trace.h's recursive include: diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index 486cbca8d0ec..b42c625569a8 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -4,6 +4,7 @@ =20 #include #include +#include #include #include =20 @@ -362,6 +363,17 @@ void mon_event_count(void *info); int rdtgroup_mondata_show(struct seq_file *m, void *arg); int rdtgroup_mondata_open(struct kernfs_open_file *of); void rdtgroup_mondata_release(struct kernfs_open_file *of); +void rdtgroup_get(struct rdtgroup *rdtgrp); +void rdtgroup_put(struct rdtgroup *rdtgrp); + +/* PMU support */ +/* + * Get rdtgroup from a resctrl monitoring file and take a reference. + * Returns a valid pointer with an extra reference on success, or ERR_PTR = on failure. + */ +struct rdtgroup *rdtgroup_get_from_file(struct file *file); +int resctrl_pmu_init(void); +void resctrl_pmu_exit(void); =20 void rmid_read_init(struct rmid_read *rr, struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, diff --git a/fs/resctrl/pmu.c b/fs/resctrl/pmu.c new file mode 100644 index 000000000000..e7915a0a3520 --- /dev/null +++ b/fs/resctrl/pmu.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Perf event access to resctrl monitoring (cache occupancy, memory bandwi= dth) + */ + +#define pr_fmt(fmt) "resctrl_pmu: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +static struct pmu resctrl_pmu; + +/* + * Event private data - stores information about the monitored resctrl gro= up + */ +struct resctrl_pmu_event { + struct rdtgroup *rdtgrp; /* Reference to rdtgroup being monitored */ +}; + +static void resctrl_event_destroy(struct perf_event *event); + +/* + * Initialize a new resctrl perf event + * The config field contains the file descriptor of the monitoring file + */ +static int resctrl_event_init(struct perf_event *event) +{ + struct resctrl_pmu_event *resctrl_event; + struct file *file; + struct rdtgroup *rdtgrp; + int fd; + int ret; + + fd =3D (int)event->attr.config; + if (fd < 0) + return -EINVAL; + + file =3D fget(fd); + if (!file) + return -EBADF; + + /* Resolve rdtgroup from the monitoring file and take a reference */ + rdtgrp =3D rdtgroup_get_from_file(file); + fput(file); + if (IS_ERR(rdtgrp)) + return PTR_ERR(rdtgrp); + + resctrl_event =3D kzalloc(sizeof(*resctrl_event), GFP_KERNEL); + if (!resctrl_event) { + rdtgroup_put(rdtgrp); + return -ENOMEM; + } + + resctrl_event->rdtgrp =3D rdtgrp; + event->pmu_private =3D resctrl_event; + event->destroy =3D resctrl_event_destroy; + + return 0; +} + +static void resctrl_event_destroy(struct perf_event *event) +{ + struct resctrl_pmu_event *resctrl_event =3D event->pmu_private; + + if (resctrl_event) { + struct rdtgroup *rdtgrp =3D resctrl_event->rdtgrp; + + if (rdtgrp) + rdtgroup_put(rdtgrp); + + kfree(resctrl_event); + event->pmu_private =3D NULL; + } +} + +static void resctrl_event_update(struct perf_event *event) +{ + /* Currently just a stub - would read actual cache occupancy here */ + local64_set(&event->hw.prev_count, 0); +} + +static void resctrl_event_start(struct perf_event *event, int flags) +{ + resctrl_event_update(event); +} + +static void resctrl_event_stop(struct perf_event *event, int flags) +{ + if (flags & PERF_EF_UPDATE) + resctrl_event_update(event); +} + +static int resctrl_event_add(struct perf_event *event, int flags) +{ + if (flags & PERF_EF_START) + resctrl_event_start(event, flags); + + return 0; +} + +static void resctrl_event_del(struct perf_event *event, int flags) +{ + resctrl_event_stop(event, PERF_EF_UPDATE); +} + +static struct pmu resctrl_pmu =3D { + .task_ctx_nr =3D perf_invalid_context, + .event_init =3D resctrl_event_init, + .add =3D resctrl_event_add, + .del =3D resctrl_event_del, + .start =3D resctrl_event_start, + .stop =3D resctrl_event_stop, + .read =3D resctrl_event_update, + .capabilities =3D PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, +}; + +int resctrl_pmu_init(void) +{ + int ret; + + ret =3D perf_pmu_register(&resctrl_pmu, "resctrl", -1); + if (ret) { + pr_err("Failed to register resctrl PMU: %d\n", ret); + return ret; + } + + return 0; +} + +void resctrl_pmu_exit(void) +{ + perf_pmu_unregister(&resctrl_pmu); +} diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 34337abe5345..4f4139edafbf 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -3428,6 +3428,53 @@ void rdtgroup_mondata_release(struct kernfs_open_fil= e *of) } } =20 +/* + * rdtgroup_get_from_file - Resolve rdtgroup from a resctrl mon data file + * @file: struct file opened on a resctrl monitoring data file + * + * Validate that @file belongs to resctrl and refers to a monitoring data + * file (kf_mondata_ops). Then, using the kernfs_open_file stored in the + * seq_file, safely fetch the rdtgroup that was pinned at open time and ta= ke + * an additional rdtgroup reference for the caller under rdtgroup_mutex. + * + * Returns: rdtgroup* with an extra reference on success; ERR_PTR on failu= re. + */ +struct rdtgroup *rdtgroup_get_from_file(struct file *file) +{ + struct rdtgroup *rdtgrp =3D NULL; + struct kernfs_open_file *of; + struct seq_file *seq; + struct inode *inode; + + if (!file) + return ERR_PTR(-EBADF); + + inode =3D file_inode(file); + /* Check the file is part of the resctrl filesystem */ + if (!inode || !inode->i_sb || inode->i_sb->s_type !=3D &rdt_fs_type) + return ERR_PTR(-EINVAL); + + /* kernfs monitoring files use seq_file; seq_file->private is kernfs_open= _file */ + seq =3D (struct seq_file *)file->private_data; + if (!seq) + return ERR_PTR(-EINVAL); + + of =3D (struct kernfs_open_file *)seq->private; + /* Check this is a monitoring file */ + if (!of || !of->kn || of->kn->attr.ops !=3D &kf_mondata_ops) + return ERR_PTR(-EINVAL); + + /* Hold rdtgroup_mutex to prevent race with release callback */ + guard(mutex)(&rdtgroup_mutex); + + rdtgrp =3D of->priv; + if (!rdtgrp || (rdtgrp->flags & RDT_DELETED)) + return ERR_PTR(-ENOENT); + + rdtgroup_get(rdtgrp); + return rdtgrp; +} + /** * cbm_ensure_valid - Enforce validity on provided CBM * @_val: Candidate CBM @@ -4509,6 +4556,10 @@ int resctrl_init(void) */ debugfs_resctrl =3D debugfs_create_dir("resctrl", NULL); =20 + ret =3D resctrl_pmu_init(); + if (ret) + pr_warn("Failed to initialize resctrl PMU: %d\n", ret); + return 0; =20 cleanup_mountpoint: @@ -4558,6 +4609,8 @@ static bool resctrl_online_domains_exist(void) */ void resctrl_exit(void) { + resctrl_pmu_exit(); + cpus_read_lock(); WARN_ON_ONCE(resctrl_online_domains_exist()); =20 diff --git a/tools/testing/selftests/resctrl/pmu_test.c b/tools/testing/sel= ftests/resctrl/pmu_test.c new file mode 100644 index 000000000000..29a0ac329619 --- /dev/null +++ b/tools/testing/selftests/resctrl/pmu_test.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Resctrl PMU test + * + * Test program to verify the resctrl PMU functionality. + * Walks resctrl filesystem and verifies only allowed files can be + * used with the resctrl PMU via perf_event_open. + */ + +#include "resctrl.h" +#include +#include + +#define RESCTRL_PMU_NAME "resctrl" + +static int find_pmu_type(const char *pmu_name) +{ + char path[256]; + FILE *file; + int type; + + snprintf(path, sizeof(path), "/sys/bus/event_source/devices/%s/type", + pmu_name); + + file =3D fopen(path, "r"); + if (!file) { + ksft_print_msg("Failed to open %s: %s\n", path, + strerror(errno)); + return -1; + } + + if (fscanf(file, "%d", &type) !=3D 1) { + ksft_print_msg("Failed to read PMU type from %s\n", path); + fclose(file); + return -1; + } + + fclose(file); + return type; +} + +static bool is_allowed_file(const char *filename) +{ + const char *base; + + /* Only exact llc_occupancy and mbm files (no *_config) are allowed */ + base =3D strrchr(filename, '/'); + base =3D base ? base + 1 : filename; + + return (!strcmp(base, "llc_occupancy") || + !strcmp(base, "mbm_total_bytes") || + !strcmp(base, "mbm_local_bytes")); +} + +static int test_file_safety(int pmu_type, const char *filepath) +{ + struct perf_event_attr pe =3D { 0 }; + int fd, perf_fd; + bool should_succeed; + + /* Try to open the file */ + fd =3D open(filepath, O_RDONLY); + if (fd < 0) { + /* File couldn't be opened, skip it */ + return 0; + } + + should_succeed =3D is_allowed_file(filepath); + + /* Setup perf event attributes */ + pe.type =3D pmu_type; + pe.config =3D fd; + pe.size =3D sizeof(pe); + pe.disabled =3D 1; + pe.exclude_kernel =3D 0; + pe.exclude_hv =3D 0; + + /* Try to open the perf event */ + perf_fd =3D perf_event_open(&pe, -1, 0, -1, 0); + + if (should_succeed) { + if (perf_fd < 0) { + ksft_print_msg("FAIL: unexpected - perf_event_open failed for %s: %s\n", + filepath, strerror(errno)); + close(fd); + return -1; + } + ksft_print_msg("PASS: Allowed file %s successfully opened perf event\n", + filepath); + close(perf_fd); + } else { + if (perf_fd >=3D 0) { + ksft_print_msg("FAIL: unexpected - perf_event_open succeeded for %s\n", + filepath); + close(perf_fd); + close(fd); + return -1; + } + ksft_print_msg("PASS: Blocked file %s correctly failed perf_event_open: = %s\n", + filepath, strerror(errno)); + } + +out: + close(fd); + return 0; +} + +static int walk_directory_recursive(int pmu_type, const char *dir_path) +{ + DIR *dir; + struct dirent *entry; + char full_path[1024]; + struct stat statbuf; + int ret =3D 0; + + dir =3D opendir(dir_path); + if (!dir) { + ksft_print_msg("Failed to open directory %s: %s\n", dir_path, + strerror(errno)); + return -1; + } + + while ((entry =3D readdir(dir)) !=3D NULL) { + /* Skip . and .. */ + if (strcmp(entry->d_name, ".") =3D=3D 0 || + strcmp(entry->d_name, "..") =3D=3D 0) + continue; + + snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, + entry->d_name); + + if (stat(full_path, &statbuf) !=3D 0) { + ksft_print_msg("Failed to stat %s: %s\n", full_path, + strerror(errno)); + continue; + } + + if (S_ISDIR(statbuf.st_mode)) { + /* Recursively walk subdirectories */ + if (walk_directory_recursive(pmu_type, full_path) !=3D 0) + ret =3D -1; + } else if (S_ISREG(statbuf.st_mode)) { + /* Test regular files */ + if (test_file_safety(pmu_type, full_path) !=3D 0) + ret =3D -1; + } + } + + closedir(dir); + return ret; +} + +static int test_resctrl_pmu_safety(int pmu_type) +{ + ksft_print_msg("Testing resctrl PMU safety - walking all files in %s\n", + RESCTRL_PATH); + + /* Walk through all files and directories in /sys/fs/resctrl */ + return walk_directory_recursive(pmu_type, RESCTRL_PATH); +} + +static bool pmu_feature_check(const struct resctrl_test *test) +{ + return resctrl_mon_feature_exists("L3_MON", "llc_occupancy"); +} + +static int pmu_run_test(const struct resctrl_test *test, + const struct user_params *uparams) +{ + int pmu_type, ret; + + ksft_print_msg("Testing resctrl PMU file access safety\n"); + + /* Find the resctrl PMU type */ + pmu_type =3D find_pmu_type(RESCTRL_PMU_NAME); + if (pmu_type < 0) { + ksft_print_msg("Resctrl PMU not found - PMU is not registered?\n"); + return -1; + } + + ksft_print_msg("Found resctrl PMU with type: %d\n", pmu_type); + + /* Run the safety test to ensure only appropriate files work */ + ret =3D test_resctrl_pmu_safety(pmu_type); + + if (ret =3D=3D 0) + ksft_print_msg("Resctrl PMU safety test completed successfully\n"); + else + ksft_print_msg("Resctrl PMU safety test failed\n"); + + return ret; +} + +struct resctrl_test pmu_test =3D { + .name =3D "PMU", + .group =3D "pmu", + .resource =3D "L3", + .vendor_specific =3D 0, + .feature_check =3D pmu_feature_check, + .run_test =3D pmu_run_test, + .cleanup =3D NULL, +}; diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/self= tests/resctrl/resctrl.h index cd3adfc14969..5b0e6074eaba 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -244,5 +244,6 @@ extern struct resctrl_test cmt_test; extern struct resctrl_test l3_cat_test; extern struct resctrl_test l3_noncont_cat_test; extern struct resctrl_test l2_noncont_cat_test; +extern struct resctrl_test pmu_test; =20 #endif /* RESCTRL_H */ diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c b/tools/testin= g/selftests/resctrl/resctrl_tests.c index 5154ffd821c4..11ba9000e015 100644 --- a/tools/testing/selftests/resctrl/resctrl_tests.c +++ b/tools/testing/selftests/resctrl/resctrl_tests.c @@ -21,6 +21,7 @@ static struct resctrl_test *resctrl_tests[] =3D { &l3_cat_test, &l3_noncont_cat_test, &l2_noncont_cat_test, + &pmu_test, }; =20 static int detect_vendor(void) From nobody Sun Feb 8 09:10:42 2026 Received: from mail-oi1-f180.google.com (mail-oi1-f180.google.com [209.85.167.180]) (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 7DE063469EC for ; Thu, 16 Oct 2025 14:47:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626031; cv=none; b=GaPdT5RMn9UlQDTT0cvNKBOFk6IiHkObGHFSlgKkVx/b2W7Si+ZZvmyQA2+BQW852zBS0rqqEUBO/4/wHFA43e9ok7Ng8/fr8X9R85YTxghymw4VaLO58h94gEsZYGM2SmzODbjKJRiHeLKlAqnq6orLoiTYgyruw1POfdUMsVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626031; c=relaxed/simple; bh=kcz2Za79jyB/wIwvQCRpYXCOBX9SihfQEP++MwdUQKg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=g+Ds9H2xTePc5oiCmOzmESRWFU4na2pD2RVMaWxXXsZAgpi3VhAVyMhLM1ef+zylK+t6HW/BpieCpWvymNpyIUFNT6UiSBgzLFCl1NZ8OCwQkjNeu/oJx78flg+S18Dad6TEexGteC5dnJIKbHpS2yvKLFY8KaXBQND1WSpzHdU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.167.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oi1-f180.google.com with SMTP id 5614622812f47-43f64a5014aso489438b6e.1 for ; Thu, 16 Oct 2025 07:47:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626028; x=1761230828; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uKKw+1FOvuGpZeJoYuJP4D2T/0Igapy6n2jKP9t0Gf4=; b=NjMSAN0mS5XMky36D3bfHVutXTigQyzQ0T4mInnXLinsDnn9vNba8bAzyeLXbEg2Ny PcuqNmzlgEXmdQXj61mpBuYJ9p4pyJ46IPqt0sKrKS0OcPlxF22mGeO74Qfq0t+Pu3wf Pm59GnhitamhYSI6m9GDM2q/+WlM+Eq/UfKdxmnnbrFAJF/PxPX2x/ldR9HylUIsMB2k lNAOpMnjxTT26/vQM58QfJZc7ZLVjsJPpWNzQVDNlmoivg0BpvJJKd889wBB4/1V4nvJ KNDlk0UMXVI0rJPj6F/Ocv/aDR+i4npyp1/uWtyhg88xbTEmYaQIrZdOglLfwgtnJrGW bCOQ== X-Forwarded-Encrypted: i=1; AJvYcCXjsvUWJOS9TYPUC7OeaVj7/RhYAOIecD1gwVsvNVVtIIoS8nfLFYtwcx5R+Cd5e3hi9jh9B8/Y4dj2Pnk=@vger.kernel.org X-Gm-Message-State: AOJu0Yz9b9dMW4EOgi6aUdoyg7hb/6Fqimd0v943zBvwdmrIpWGVvkba ATN8+pGwMYfgpyXWaw/2zvZsObz3XA7tv75jMbAGj76cObS6R4iHUJf3 X-Gm-Gg: ASbGncscu0VFwZ4b8p802PVQWYRaVwOFafiUsW9xxSKKRCBCyjErAO1azsd0InQ6oQw 14987EOJUzTxmuokBrELcOWkcjR1KQs3TohMvpJp3g/OdmpHJ5pc1yeG3ZqR7/NwYPhAREplbz9 0H2vUOFng8nY4KsLGP5x8LQB8T5KZGWvW56jdp2gbLbMY/eSX6HO42uJysVXKgYIA/EbMwakPPB 8IYa3oe+hMeWfGddnY+vkcXcZT7jJX8Ru9q02nl1hrqqc0Do6jzF+v7rTNiB2omMQTcUJHd43MG xmymUH3Zc809f7noJcKhQMMHQopXEav18CvcTIFkRpCaBDN3nQFvMAhl5pav9mL2LDO1eDleK28 ou3XU6wIwG03xscIYvfNd04UsrftsYtmK8OPPbwYbsJUg8NRV9D1lz8fphzFekD+OFJ/KGcfx1W vkBX8OlLpnw4ujjT3VeBjfEgesRVHsrdmgc4akec7h1h+q7N4+lya4QI8c2syijClxIbc= X-Google-Smtp-Source: AGHT+IEl+McCmwNj5n5UABPh5EXtH7pj4NhPOnj1CYi5KF1wA0afnYHvrsjxYZpRFSVlVKKD3j3GHQ== X-Received: by 2002:a05:6808:16a4:b0:441:8f74:fcd with SMTP id 5614622812f47-443a309882cmr102090b6e.58.1760626028347; Thu, 16 Oct 2025 07:47:08 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.07 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:08 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 7/8] resctrl/pmu: Use mon_event_setup_read() and validate CPU Date: Thu, 16 Oct 2025 09:46:55 -0500 Message-ID: <20251016144656.74928-8-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" During event_init, extract mon_data from the monitoring file and call mon_event_setup_read() to prepare rmid_read and the valid CPU mask for that file. Require a CPU-bound event and verify the bound CPU is in the mask. Store the prepared rmid_read and CPU mask in the event private data along with the pinned rdtgroup. Split the helper that gets the pinned rdtgroup in two, so event_init can get the mon_data from kernfs_open_file: - rdtgroup_get_mondata_open_file() gets kernfs_open_file from file - rdtgroup_get_from_mondata_file() gets pinned rdtgroup from kernfs_open_file Extend the selftest to test CPU validation and verify that pid-bound events are rejected. Signed-off-by: Jonathan Perry --- fs/resctrl/internal.h | 2 + fs/resctrl/pmu.c | 59 +++++++- fs/resctrl/rdtgroup.c | 24 ++- tools/testing/selftests/resctrl/pmu_test.c | 164 ++++++++++++++++++--- 4 files changed, 214 insertions(+), 35 deletions(-) diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index b42c625569a8..8cc3a3747c2f 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -365,6 +365,8 @@ int rdtgroup_mondata_open(struct kernfs_open_file *of); void rdtgroup_mondata_release(struct kernfs_open_file *of); void rdtgroup_get(struct rdtgroup *rdtgrp); void rdtgroup_put(struct rdtgroup *rdtgrp); +struct kernfs_open_file *rdtgroup_get_mondata_open_file(struct file *file); +struct rdtgroup *rdtgroup_get_from_mondata_file(struct kernfs_open_file *o= f); =20 /* PMU support */ /* diff --git a/fs/resctrl/pmu.c b/fs/resctrl/pmu.c index e7915a0a3520..bdca0b3a5b0b 100644 --- a/fs/resctrl/pmu.c +++ b/fs/resctrl/pmu.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" =20 static struct pmu resctrl_pmu; @@ -21,6 +22,8 @@ static struct pmu resctrl_pmu; */ struct resctrl_pmu_event { struct rdtgroup *rdtgrp; /* Reference to rdtgroup being monitored */ + struct rmid_read rr; /* RMID read setup for monitoring */ + cpumask_t *cpumask; /* Valid CPUs for this monitoring file */ }; =20 static void resctrl_event_destroy(struct perf_event *event); @@ -34,9 +37,16 @@ static int resctrl_event_init(struct perf_event *event) struct resctrl_pmu_event *resctrl_event; struct file *file; struct rdtgroup *rdtgrp; + struct kernfs_open_file *of; + struct mon_data *md; + struct rmid_read rr =3D {0}; + cpumask_t *cpumask; int fd; int ret; =20 + if (event->cpu < 0) + return -EINVAL; + fd =3D (int)event->attr.config; if (fd < 0) return -EINVAL; @@ -45,11 +55,46 @@ static int resctrl_event_init(struct perf_event *event) if (!file) return -EBADF; =20 - /* Resolve rdtgroup from the monitoring file and take a reference */ - rdtgrp =3D rdtgroup_get_from_file(file); + of =3D rdtgroup_get_mondata_open_file(file); + if (IS_ERR(of)) { + ret =3D PTR_ERR(of); + goto out_fput; + } + + /* Extract mon_data which specifies which resource to measure */ + if (!of->kn || !of->kn->priv) { + ret =3D -EIO; + goto out_fput; + } + md =3D of->kn->priv; + + rdtgrp =3D rdtgroup_get_from_mondata_file(of); + if (IS_ERR(rdtgrp)) { + ret =3D PTR_ERR(rdtgrp); + goto out_fput; + } + fput(file); - if (IS_ERR(rdtgrp)) - return PTR_ERR(rdtgrp); + file =3D NULL; + + cpus_read_lock(); + + ret =3D mon_event_setup_read(&rr, &cpumask, md, rdtgrp); + if (ret) { + cpus_read_unlock(); + rdtgroup_put(rdtgrp); + return ret; + } + + /* Validate that the requested CPU is in the valid CPU mask for this moni= toring file */ + if (!cpumask_test_cpu(event->cpu, cpumask)) { + ret =3D -EINVAL; + cpus_read_unlock(); + rdtgroup_put(rdtgrp); + return ret; + } + + cpus_read_unlock(); =20 resctrl_event =3D kzalloc(sizeof(*resctrl_event), GFP_KERNEL); if (!resctrl_event) { @@ -58,10 +103,16 @@ static int resctrl_event_init(struct perf_event *event) } =20 resctrl_event->rdtgrp =3D rdtgrp; + resctrl_event->rr =3D rr; + resctrl_event->cpumask =3D cpumask; event->pmu_private =3D resctrl_event; event->destroy =3D resctrl_event_destroy; =20 return 0; + +out_fput: + fput(file); + return ret; } =20 static void resctrl_event_destroy(struct perf_event *event) diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 4f4139edafbf..ed7d9feccd94 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -3429,19 +3429,16 @@ void rdtgroup_mondata_release(struct kernfs_open_fi= le *of) } =20 /* - * rdtgroup_get_from_file - Resolve rdtgroup from a resctrl mon data file + * Resolve kernfs_open_file from a resctrl mon data file. * @file: struct file opened on a resctrl monitoring data file * * Validate that @file belongs to resctrl and refers to a monitoring data - * file (kf_mondata_ops). Then, using the kernfs_open_file stored in the - * seq_file, safely fetch the rdtgroup that was pinned at open time and ta= ke - * an additional rdtgroup reference for the caller under rdtgroup_mutex. + * file (kf_mondata_ops). * - * Returns: rdtgroup* with an extra reference on success; ERR_PTR on failu= re. + * Returns: kernfs_open_file* on success; ERR_PTR on failure. */ -struct rdtgroup *rdtgroup_get_from_file(struct file *file) +struct kernfs_open_file *rdtgroup_get_mondata_open_file(struct file *file) { - struct rdtgroup *rdtgrp =3D NULL; struct kernfs_open_file *of; struct seq_file *seq; struct inode *inode; @@ -3464,6 +3461,19 @@ struct rdtgroup *rdtgroup_get_from_file(struct file = *file) if (!of || !of->kn || of->kn->attr.ops !=3D &kf_mondata_ops) return ERR_PTR(-EINVAL); =20 + return of; +} + +/* + * Get rdtgroup from a resctrl mon data open file. + * @of: kernfs_open_file opened on a resctrl monitoring data file + * + * Returns: rdtgroup* with an extra reference on success; ERR_PTR on failu= re. + */ +struct rdtgroup *rdtgroup_get_from_mondata_file(struct kernfs_open_file *o= f) +{ + struct rdtgroup *rdtgrp =3D NULL; + /* Hold rdtgroup_mutex to prevent race with release callback */ guard(mutex)(&rdtgroup_mutex); =20 diff --git a/tools/testing/selftests/resctrl/pmu_test.c b/tools/testing/sel= ftests/resctrl/pmu_test.c index 29a0ac329619..fb3eec721e43 100644 --- a/tools/testing/selftests/resctrl/pmu_test.c +++ b/tools/testing/selftests/resctrl/pmu_test.c @@ -3,13 +3,16 @@ * Resctrl PMU test * * Test program to verify the resctrl PMU functionality. - * Walks resctrl filesystem and verifies only allowed files can be - * used with the resctrl PMU via perf_event_open. + * Walks resctrl filesystem and verifies only allowed monitoring files + * can be used with the resctrl PMU via perf_event_open when pinned to + * CPUs in the correct L3 domain. Also validates that PID-bound events + * are rejected for all files. */ =20 #include "resctrl.h" #include #include +#include =20 #define RESCTRL_PMU_NAME "resctrl" =20 @@ -52,11 +55,51 @@ static bool is_allowed_file(const char *filename) !strcmp(base, "mbm_local_bytes")); } =20 +/* Extract base filename from a path */ +static const char *base_name(const char *path) +{ + const char *slash =3D strrchr(path, '/'); + + return slash ? slash + 1 : path; +} + +/* Parse mon_L3_XX ID from a monitoring path. Returns true on success. */ +static bool parse_l3_id_from_path(const char *path, int *l3_id) +{ + const char *needle =3D "mon_data/mon_L3_"; + const char *p =3D strstr(path, needle); + char *endptr; + long id; + + if (!p) + return false; + + p +=3D strlen(needle); + + if (!isdigit((unsigned char)*p)) + return false; + + errno =3D 0; + id =3D strtol(p, &endptr, 10); + if (errno || endptr =3D=3D p) + return false; + + /* Accept only non-negative IDs */ + if (id < 0) + return false; + + *l3_id =3D (int)id; + return true; +} + static int test_file_safety(int pmu_type, const char *filepath) { struct perf_event_attr pe =3D { 0 }; int fd, perf_fd; - bool should_succeed; + bool is_monitoring =3D false; + int file_l3_id =3D -1; + int ret =3D 0; + const char *fname =3D base_name(filepath); =20 /* Try to open the file */ fd =3D open(filepath, O_RDONLY); @@ -65,7 +108,8 @@ static int test_file_safety(int pmu_type, const char *fi= lepath) return 0; } =20 - should_succeed =3D is_allowed_file(filepath); + /* Determine if this is a monitoring file under mon_L3_XX and allowed */ + is_monitoring =3D (is_allowed_file(fname) && parse_l3_id_from_path(filepa= th, &file_l3_id)); =20 /* Setup perf event attributes */ pe.type =3D pmu_type; @@ -75,34 +119,106 @@ static int test_file_safety(int pmu_type, const char = *filepath) pe.exclude_kernel =3D 0; pe.exclude_hv =3D 0; =20 - /* Try to open the perf event */ - perf_fd =3D perf_event_open(&pe, -1, 0, -1, 0); + /* PID-bound negative attempt: should fail for all files */ + perf_fd =3D perf_event_open(&pe, getpid(), -1, -1, 0); + if (perf_fd >=3D 0) { + ksft_print_msg("FAIL: pid-bound perf_event_open unexpectedly succeeded f= or %s\n", + filepath); + close(perf_fd); + close(fd); + return -1; + } + + int success_count =3D 0; + cpu_set_t mask; + int max_cpus, nconf; + + CPU_ZERO(&mask); + if (sched_getaffinity(0, sizeof(mask), &mask)) { + ksft_perror("sched_getaffinity failed"); + goto out; + } + + nconf =3D (int)sysconf(_SC_NPROCESSORS_CONF); + max_cpus =3D (nconf > 0 && nconf < CPU_SETSIZE) ? nconf : CPU_SETSIZE; + + for (int cpu =3D 0; cpu < max_cpus; cpu++) { + int cpu_l3; + + if (!CPU_ISSET(cpu, &mask)) + continue; + + if (get_domain_id("L3", cpu, &cpu_l3) < 0) { + ksft_print_msg("Failed to get L3 domain ID for CPU %d\n", cpu); + ret =3D -1; + break; + } =20 - if (should_succeed) { - if (perf_fd < 0) { - ksft_print_msg("FAIL: unexpected - perf_event_open failed for %s: %s\n", - filepath, strerror(errno)); - close(fd); - return -1; + perf_fd =3D perf_event_open(&pe, -1, cpu, -1, 0); + + if (is_monitoring) { + bool expected_ok =3D (cpu_l3 =3D=3D file_l3_id); + + if (expected_ok) { + if (perf_fd < 0) { + ksft_print_msg("FAIL: %s CPU %d (L3=3D%d) expected success, got %s\n", + filepath, cpu, cpu_l3, strerror(errno)); + ret =3D -1; + break; + } + success_count++; + close(perf_fd); + } else { + if (perf_fd >=3D 0) { + ksft_print_msg("FAIL: %s CPU %d (L3=3D%d) expected EINVAL fail, but o= pened\n", + filepath, cpu, cpu_l3); + close(perf_fd); + ret =3D -1; + break; + } + if (errno !=3D EINVAL) { + ksft_print_msg("FAIL: %s CPU %d expected errno=3DEINVAL, got %d (%s)\= n", + filepath, cpu, errno, strerror(errno)); + ret =3D -1; + break; + } + } + } else { + /* Non-monitoring files must fail on all CPUs with EINVAL */ + if (perf_fd >=3D 0) { + ksft_print_msg("FAIL: non-monitoring file %s CPU %d unexpectedly opene= d\n", + filepath, cpu); + close(perf_fd); + ret =3D -1; + break; + } + if (errno !=3D EINVAL) { + ksft_print_msg("FAIL: non-monitoring file %s CPU %d expected errno=3DE= INVAL, got %d (%s)\n", + filepath, cpu, errno, strerror(errno)); + ret =3D -1; + break; + } } - ksft_print_msg("PASS: Allowed file %s successfully opened perf event\n", + } + + if (!ret && is_monitoring && success_count < 1) { + ksft_print_msg("FAIL: monitoring file %s had no successful CPU opens\n", filepath); - close(perf_fd); - } else { - if (perf_fd >=3D 0) { - ksft_print_msg("FAIL: unexpected - perf_event_open succeeded for %s\n", + ret =3D -1; + } + + if (!ret) { + if (is_monitoring) + ksft_print_msg("PASS: monitoring %s: %d CPU(s) opened in-domain, others= rejected\n", + filepath, success_count); + else + ksft_print_msg("PASS: non-monitoring %s: all CPU-bound opens rejected w= ith EINVAL\n", filepath); - close(perf_fd); - close(fd); - return -1; - } - ksft_print_msg("PASS: Blocked file %s correctly failed perf_event_open: = %s\n", - filepath, strerror(errno)); } =20 out: close(fd); - return 0; + return ret; } =20 static int walk_directory_recursive(int pmu_type, const char *dir_path) From nobody Sun Feb 8 09:10:42 2026 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (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 87F793469FF for ; Thu, 16 Oct 2025 14:47:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626033; cv=none; b=lcdkn3lUsUuJNKRbUPmrBz52Qmny3JS7VTdzshkTzvsiO3EMWZj5qcsm1fQ3EfxXpFhFGtAjsYyK8H8r6js2/lGfYGv9IAabju1gg9thMnJsEU28syW6CPe7uXIXYbeVEIPdua4CZwiH5IXimhOqKiMsfNwyPuqj5mfFynHi8zg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760626033; c=relaxed/simple; bh=YGEk3Vxt0xAsLuoBTBKmO6oTHhcJNPGtkDPzHjbgv8I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SSxPbkQ8pYNMmGZEfSKC7MVeb/cMUO0CHFY48s0kRrrH4WWpa6ILmwOrL3qu48Zrq+KI9kbxSVvvr80rUQheZME/7/yCO9lhNFJvOLqHsdBwE4KpnCjvglNQHfNzhHSGimkFydDaLt2Q3eRznF6V7j/gOWahfk2atTV9c9gSAsg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.210.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=yonch.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-7c278c25aefso417202a34.1 for ; Thu, 16 Oct 2025 07:47:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760626029; x=1761230829; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4PBE8tsArPgVuwR9rYRWZy1yTOJeVVE4k+vcOQXANQY=; b=BUeX3F2Q62ds0MN/R1cywg7AXnV7ZuR84IPXIcF94+SCkUwBs5k4pqsOrek7pbWMj7 oiUKSe8FaAOVqP8Kt5Se9/wtwil6CesWutHcghR8RZOP97EOPg2EmpU+Ro1x8+Trp8vb BJqXBPGM5FpIDZVuWJOts4/qOi2B+d9vzA6LTGkdCH5HAp0fwsYQnUDCZXMjfFYwVjZv jPNF0ewwzD5pRMR0lBvu8Z2+s5sEaheHymaVZ0x2DGCuJrac44xv+cmrta7xHo8E9fMK yNh5EspHA7I27CyzuH6OmP8cSKCpTr5UnwPCtAe5asH5tFZs+g/4Kry6tI0xzAR/U06F G2FQ== X-Forwarded-Encrypted: i=1; AJvYcCV4WNYEqVHYvHcwqi86A/sEDhQmDXp5tFFe+UkQHIy+9XEk2hZ2DZr05sjtaY0nYwqG3LD7jfOCB/d9Dxs=@vger.kernel.org X-Gm-Message-State: AOJu0YwDXhWn+X7ir4jAx3FhOLEhv3cv9q6dEg7i3W2g7oY6QjX9qFzE iiybD7HX0X5VCEAOTGCCJPXtrrTxWXH59pOr18O/nqmeNqZQ00IOOZTe X-Gm-Gg: ASbGncs01hCgPGNHqWg8yK7fb4RSFtW9Ln/WAs3OaQKkKDLGfOWJduzA1BxJ5FvDVZg 1avyyCUjc9ZC6tdBjc4A9UZoCdPVPKkeumeWcHiImg4mKtDwyzugNZo0fHuer8MVX/qV6IVxk/c /EBTJXgta8wO7XX19mZVEvil2XApxRfiJFWTY+O63xYqs2Y6EIsk1KlPHBeC8qbU5KKR3cNYhBt G+vfn45qVZUtPlNOBWKnLDuzxcjpflGgYAhvjtJKq8iPM4rzDxYpQC9v3w2ynUEsaW6khHvNuwE QA/LaYdl6KavgUGm2ed7vfUvlas0rdBGlV7/Ff6iihXGuEvJn2gu7+fqiE8Fw/gneUrHwTMzJKE ZfW7cGeypgwFIB5FVcDRgjjOOV5F0S8L+RnFqltNou3QBr4mIGMj5e4Sshn8FG9CpnHJpqBmp76 Z5z6QxAkD1zIzBATPDuXG4pOQgNHVYL/Rjqlxz2KZ+eMyOvoEiqp9+mjzX X-Google-Smtp-Source: AGHT+IG5UTBXBR0mcF3hbn7sH8I5dAxaCZxah8MRjFva13+8nwHEh6GWtPkvzNt+eztgSnV1vDranQ== X-Received: by 2002:a05:6808:8953:b0:43f:4f34:dd52 with SMTP id 5614622812f47-443a2dd8953mr141131b6e.3.1760626029452; Thu, 16 Oct 2025 07:47:09 -0700 (PDT) Received: from localhost.localdomain (syn-067-079-108-173.biz.spectrum.com. [67.79.108.173]) by smtp.gmail.com with ESMTPSA id 5614622812f47-441cc812f24sm3678018b6e.12.2025.10.16.07.47.08 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Oct 2025 07:47:08 -0700 (PDT) From: Jonathan Perry To: Tony Luck , Reinette Chatre , linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, Jonathan Corbet , James Morse , Roman Storozhenko , Jonathan Perry Subject: [PATCH 8/8] resctrl/pmu: Implement .read via direct RMID read; add LLC selftest Date: Thu, 16 Oct 2025 09:46:56 -0500 Message-ID: <20251016144656.74928-9-yonch@yonch.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20251016144656.74928-1-yonch@yonch.com> References: <20251016144656.74928-1-yonch@yonch.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement reads of monitored values in resctrl_event_update(). If the rdtgroup was deleted, read zero. On RMID read errors, emit a WARN_ONCE and read zero. Introduce mon_event_read_this_cpu() to call mon_event_count() directly, with no IPI, as perf infra would ensure .read runs on the bound CPU. Augment the existing LLC occupancy selftest to also test the PMU. Document PMU usage in resctrl.rst. Signed-off-by: Jonathan Perry --- Documentation/filesystems/resctrl.rst | 64 ++++++++++++++ fs/resctrl/ctrlmondata.c | 17 ++++ fs/resctrl/internal.h | 1 + fs/resctrl/pmu.c | 31 ++++++- tools/testing/selftests/resctrl/cache.c | 94 ++++++++++++++++++++- tools/testing/selftests/resctrl/cmt_test.c | 17 +++- tools/testing/selftests/resctrl/pmu_test.c | 28 +----- tools/testing/selftests/resctrl/pmu_utils.c | 32 +++++++ tools/testing/selftests/resctrl/resctrl.h | 3 + 9 files changed, 253 insertions(+), 34 deletions(-) create mode 100644 tools/testing/selftests/resctrl/pmu_utils.c diff --git a/Documentation/filesystems/resctrl.rst b/Documentation/filesyst= ems/resctrl.rst index b7f35b07876a..8f91ba7d622b 100644 --- a/Documentation/filesystems/resctrl.rst +++ b/Documentation/filesystems/resctrl.rst @@ -628,6 +628,70 @@ Resource monitoring rules "mon_data" group. =20 =20 +Perf PMU access (resctrl PMU) +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D + +resctrl registers a perf PMU named "resctrl", which provides read-only acc= ess +to the same monitoring values exposed via the "mon_data" files. The PMU +enables access from eBPF and allows parallelizing reads as it does not lock +the system-wide `rdtgroup_mutex`. + +Selection and usage +------------------- +- Event selection is performed by passing the file descriptor of a + resctrl monitoring file, for example + "mon_data/mon_L3_00/llc_occupancy", in the `perf_event_attr.config` + field when calling perf_event_open(). +- The perf event must be CPU-bound (pid =3D -1 and cpu >=3D 0). +- The chosen CPU must be valid for the domain represented by the + monitoring file: + + - For a domain-specific file such as "mon_L3_00/...", choose a CPU that + belongs to that domain. + - For files that provide a sum across domains that share the same L3 + cache instance (for example on SNC systems), choose a CPU that + shares that L3 cache instance. See the "Cache IDs" section for the + concepts and mapping. +- Exclude flags must be zero. perf_event_open() fails if any exclude + flags are set. + +Semantics +--------- +- The values from the resctrl PMU match the values what would be + read from the corresponding "mon_data" file at the time of the read. +- Sampling is not supported. The PMU provides counts that can be read + on demand; there are no periodic interrupts or per-context filtering + semantics. +- It is safe to read a perf event whose underlying resctrl group has been + deleted. However, the returned values are unspecified: the current + implementation returns zeros, but this may change in the future. + +Discovering the PMU and example +------------------------------- +- The PMU type is exposed at + "/sys/bus/event_source/devices/resctrl/type" and must be placed in + `perf_event_attr.type`. +- A minimal example of opening a resctrl PMU event by passing a + monitoring file descriptor in `config`:: + + int pmu_type =3D read_int("/sys/bus/event_source/devices/resctrl/typ= e"); + int mon_fd =3D open("/sys/fs/resctrl/mon_data/mon_L3_00/llc_occupanc= y", O_RDONLY); + struct perf_event_attr pe =3D { 0 }; + + pe.type =3D pmu_type; + pe.size =3D sizeof(pe); + pe.config =3D mon_fd; /* select event via resctrl file descriptor */ + pe.disabled =3D 1; + + int cpu =3D /* a CPU in the L3_00 domain (see Cache IDs) */; + int fd =3D perf_event_open(&pe, -1 /* pid */, cpu /* cpu */, -1, 0); + + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + uint64_t val; + read(fd, &val, sizeof(val)); + ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + + Notes on cache occupancy monitoring and control =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D When moving a task from one group to another you should remember that diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index d1e4cf6f2128..02f8f256c680 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -594,6 +594,23 @@ void mon_event_read(struct rmid_read *rr, cpumask_t *c= pumask) resctrl_arch_mon_ctx_free(rr->r, rr->evtid, rr->arch_mon_ctx); } =20 +void mon_event_read_this_cpu(struct rmid_read *rr) +{ + /* Ensure we're not in a CPU hotplug race */ + lockdep_assert_cpus_held(); + + rr->arch_mon_ctx =3D resctrl_arch_mon_ctx_alloc(rr->r, rr->evtid); + if (IS_ERR(rr->arch_mon_ctx)) { + rr->err =3D -EINVAL; + return; + } + + /* Direct call on current CPU - no IPI needed */ + mon_event_count(rr); + + resctrl_arch_mon_ctx_free(rr->r, rr->evtid, rr->arch_mon_ctx); +} + int mon_event_setup_read(struct rmid_read *rr, cpumask_t **cpumask, struct mon_data *md, struct rdtgroup *rdtgrp) { diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h index 8cc3a3747c2f..c4adb6eaf101 100644 --- a/fs/resctrl/internal.h +++ b/fs/resctrl/internal.h @@ -383,6 +383,7 @@ void rmid_read_init(struct rmid_read *rr, struct rdt_re= source *r, int mon_event_setup_read(struct rmid_read *rr, cpumask_t **cpumask, struct mon_data *md, struct rdtgroup *rdtgrp); void mon_event_read(struct rmid_read *rr, cpumask_t *cpumask); +void mon_event_read_this_cpu(struct rmid_read *rr); =20 int resctrl_mon_resource_init(void); =20 diff --git a/fs/resctrl/pmu.c b/fs/resctrl/pmu.c index bdca0b3a5b0b..e6f5f13f29d2 100644 --- a/fs/resctrl/pmu.c +++ b/fs/resctrl/pmu.c @@ -132,8 +132,35 @@ static void resctrl_event_destroy(struct perf_event *e= vent) =20 static void resctrl_event_update(struct perf_event *event) { - /* Currently just a stub - would read actual cache occupancy here */ - local64_set(&event->hw.prev_count, 0); + struct resctrl_pmu_event *resctrl_event =3D event->pmu_private; + struct rdtgroup *rdtgrp =3D resctrl_event->rdtgrp; + struct rmid_read rr; + u64 value =3D 0; + + /* Check if rdtgroup has been deleted */ + if (rdtgrp->flags & RDT_DELETED) { + local64_set(&event->count, 0); + return; + } + + /* Setup rmid_read structure with current parameters */ + rr =3D resctrl_event->rr; + rr.val =3D 0; + rr.err =3D 0; + + /* Take cpus read lock only around the actual RMID read */ + cpus_read_lock(); + mon_event_read_this_cpu(&rr); + cpus_read_unlock(); + + /* Update counter value based on read result */ + if (!rr.err) + value =3D rr.val; + else + WARN_ONCE(1, "resctrl PMU: RMID read error (err=3D%d) for closid=3D%u, r= mid=3D%u, evtid=3D%d\n", + rr.err, rdtgrp->closid, rdtgrp->mon.rmid, rr.evtid); + + local64_set(&event->count, value); } =20 static void resctrl_event_start(struct perf_event *event, int flags) diff --git a/tools/testing/selftests/resctrl/cache.c b/tools/testing/selfte= sts/resctrl/cache.c index 1ff1104e6575..826c11589d34 100644 --- a/tools/testing/selftests/resctrl/cache.c +++ b/tools/testing/selftests/resctrl/cache.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 =20 #include +#include #include "resctrl.h" =20 char llc_occup_path[1024]; @@ -92,12 +93,62 @@ static int get_llc_occu_resctrl(unsigned long *llc_occu= pancy) return 0; } =20 +/* + * get_llc_occu_resctrl_pmu - Read LLC occupancy via resctrl PMU + * + * Uses the PMU to read LLC occupancy from the monitored resource given by= the + * global variable llc_occup_path. + * + * Return: =3D0 on success. <0 on failure. + */ +static int get_llc_occu_resctrl_pmu(unsigned long *llc_occupancy_pmu) +{ + int pmu_type, mon_fd =3D -1, perf_fd =3D -1; + struct perf_event_attr pe =3D { 0 }; + __u64 value =3D 0; + + if (!llc_occup_path[0]) + return -1; + + pmu_type =3D resctrl_find_pmu_type("resctrl"); + if (pmu_type < 0) + return -1; + + mon_fd =3D open(llc_occup_path, O_RDONLY); + if (mon_fd < 0) + return -1; + + memset(&pe, 0, sizeof(pe)); + pe.type =3D pmu_type; + pe.config =3D mon_fd; /* Pass the monitoring fd */ + pe.size =3D sizeof(pe); + pe.disabled =3D 0; /* Start enabled */ + + perf_fd =3D perf_event_open(&pe, -1, 0, -1, 0); + if (perf_fd < 0) + goto out_close_mon; + + if (read(perf_fd, &value, sizeof(value)) !=3D sizeof(value)) + goto out_close_all; + + *llc_occupancy_pmu =3D (unsigned long)value; + + close(perf_fd); + close(mon_fd); + return 0; + +out_close_all: + close(perf_fd); +out_close_mon: + close(mon_fd); + return -1; +} + /* * print_results_cache: the cache results are stored in a file * @filename: file that stores the results * @bm_pid: child pid that runs benchmark - * @llc_value: perf miss value / - * llc occupancy value reported by resctrl FS + * @llc_value: perf miss value * * Return: 0 on success, < 0 on error. */ @@ -121,6 +172,37 @@ static int print_results_cache(const char *filename, p= id_t bm_pid, __u64 llc_val return 0; } =20 +/* + * print_results_llc: prints LLC measurements to a file + * @filename: file that stores the results + * @bm_pid: child pid that runs benchmark + * @fs_value: llc occupancy value reported by resctrl FS + * @pmu_value: llc occupancy value reported by resctrl PMU + * + * Return: 0 on success, < 0 on error. + */ +static int print_results_llc(const char *filename, pid_t bm_pid, + unsigned long fs_value, unsigned long pmu_value) +{ + FILE *fp; + + if (strcmp(filename, "stdio") =3D=3D 0 || strcmp(filename, "stderr") =3D= =3D 0) { + printf("Pid: %d \t llc_value: %lu\t pmu_value: %lu\n", + (int)bm_pid, fs_value, pmu_value); + } else { + fp =3D fopen(filename, "a"); + if (!fp) { + ksft_perror("Cannot open results file"); + return -1; + } + fprintf(fp, "Pid: %d \t llc_value: %lu\t pmu_value: %lu\n", + (int)bm_pid, fs_value, pmu_value); + fclose(fp); + } + + return 0; +} + /* * perf_event_measure - Measure perf events * @filename: Filename for writing the results @@ -164,13 +246,19 @@ int perf_event_measure(int pe_fd, struct perf_event_r= ead *pe_read, int measure_llc_resctrl(const char *filename, pid_t bm_pid) { unsigned long llc_occu_resc =3D 0; + unsigned long llc_occu_pmu =3D 0; int ret; =20 ret =3D get_llc_occu_resctrl(&llc_occu_resc); if (ret < 0) return ret; =20 - return print_results_cache(filename, bm_pid, llc_occu_resc); + /* Try to get PMU value as well */ + ret =3D get_llc_occu_resctrl_pmu(&llc_occu_pmu); + if (ret < 0) + return ret; + + return print_results_llc(filename, bm_pid, llc_occu_resc, llc_occu_pmu); } =20 /* diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/sel= ftests/resctrl/cmt_test.c index d09e693dc739..28250903bbf0 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -78,6 +78,7 @@ static int check_results(struct resctrl_val_param *param,= size_t span, int no_of { char *token_array[8], temp[512]; unsigned long sum_llc_occu_resc =3D 0; + unsigned long sum_llc_occu_pmu =3D 0; int runs =3D 0; FILE *fp; =20 @@ -100,12 +101,24 @@ static int check_results(struct resctrl_val_param *pa= ram, size_t span, int no_of =20 /* Field 3 is llc occ resc value */ sum_llc_occu_resc +=3D strtoul(token_array[3], NULL, 0); + + /* Field 5: llc occupancy from PMU */ + sum_llc_occu_pmu +=3D strtoul(token_array[5], NULL, 0); runs++; } fclose(fp); =20 - return show_results_info(sum_llc_occu_resc, no_of_bits, span, - MAX_DIFF, MAX_DIFF_PERCENT, runs, true); + /* Filesystem-based results */ + ksft_print_msg("CMT (resctrl fs):\n"); + int ret_fs =3D show_results_info(sum_llc_occu_resc, no_of_bits, span, + MAX_DIFF, MAX_DIFF_PERCENT, runs, true); + + /* PMU-based results */ + ksft_print_msg("CMT (PMU):\n"); + int ret_pmu =3D show_results_info(sum_llc_occu_pmu, no_of_bits, span, + MAX_DIFF, MAX_DIFF_PERCENT, runs, true); + + return ret_fs || ret_pmu; } =20 static void cmt_test_cleanup(void) diff --git a/tools/testing/selftests/resctrl/pmu_test.c b/tools/testing/sel= ftests/resctrl/pmu_test.c index fb3eec721e43..e4d75a8c0a6c 100644 --- a/tools/testing/selftests/resctrl/pmu_test.c +++ b/tools/testing/selftests/resctrl/pmu_test.c @@ -16,32 +16,6 @@ =20 #define RESCTRL_PMU_NAME "resctrl" =20 -static int find_pmu_type(const char *pmu_name) -{ - char path[256]; - FILE *file; - int type; - - snprintf(path, sizeof(path), "/sys/bus/event_source/devices/%s/type", - pmu_name); - - file =3D fopen(path, "r"); - if (!file) { - ksft_print_msg("Failed to open %s: %s\n", path, - strerror(errno)); - return -1; - } - - if (fscanf(file, "%d", &type) !=3D 1) { - ksft_print_msg("Failed to read PMU type from %s\n", path); - fclose(file); - return -1; - } - - fclose(file); - return type; -} - static bool is_allowed_file(const char *filename) { const char *base; @@ -288,7 +262,7 @@ static int pmu_run_test(const struct resctrl_test *test, ksft_print_msg("Testing resctrl PMU file access safety\n"); =20 /* Find the resctrl PMU type */ - pmu_type =3D find_pmu_type(RESCTRL_PMU_NAME); + pmu_type =3D resctrl_find_pmu_type(RESCTRL_PMU_NAME); if (pmu_type < 0) { ksft_print_msg("Resctrl PMU not found - PMU is not registered?\n"); return -1; diff --git a/tools/testing/selftests/resctrl/pmu_utils.c b/tools/testing/se= lftests/resctrl/pmu_utils.c new file mode 100644 index 000000000000..2d65d8b6e9e3 --- /dev/null +++ b/tools/testing/selftests/resctrl/pmu_utils.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "resctrl.h" +#include + +int resctrl_find_pmu_type(const char *pmu_name) +{ + char path[256]; + FILE *file; + int type; + + if (!pmu_name) + return -1; + + snprintf(path, sizeof(path), "/sys/bus/event_source/devices/%s/type", + pmu_name); + + file =3D fopen(path, "r"); + if (!file) { + ksft_print_msg("Failed to open %s: %s\n", path, strerror(errno)); + return -1; + } + + if (fscanf(file, "%d", &type) !=3D 1) { + ksft_print_msg("Failed to read PMU type from %s\n", path); + fclose(file); + return -1; + } + + fclose(file); + return type; +} diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/self= tests/resctrl/resctrl.h index 5b0e6074eaba..d1d2891081cf 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -205,6 +205,9 @@ void signal_handler_unregister(void); unsigned int count_bits(unsigned long n); int snc_kernel_support(void); =20 +/* PMU utilities */ +int resctrl_find_pmu_type(const char *pmu_name); + void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config); void perf_event_initialize_read_format(struct perf_event_read *pe_read); int perf_open(struct perf_event_attr *pea, pid_t pid, int cpu_no);