mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shakeel Butt <shakeel.butt@linux.dev>
To: Reinette Chatre <reinette.chatre@intel.com>,
	Tony Luck <tony.luck@intel.com>
Cc: Dave Martin <Dave.Martin@arm.com>,
	James Morse <james.morse@arm.com>,
	Babu Moger <babu.moger@amd.com>,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Peter Newman <peternewman@google.com>,
	Meta kernel team <kernel-team@meta.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH] x86,resctrl: Read event counters with an IPI when the read cannot block
Date: Tue, 20 Oct 2026 08:13:52 -0700	[thread overview]
Message-ID: <20261020151352.2346257-1-shakeel.butt@linux.dev> (raw)

In the Meta fleet, readers of the resctrl mon_data files often sleep
while holding rdtgroup_mutex. Over several hours, a lock profiler on
several thousand hosts (almost all AMD) caught:

  - 96,368 reads that held rdtgroup_mutex and cpu_hotplug_lock for
    17 ms on average and up to several seconds, mostly sleeping.
  - Three different userspace applications [1, 2, 3] doing these reads.
  - Other readers and the MBM overflow worker waiting for the mutex.

These long stalls put gaps in the monitoring data for these
applications.

The read has to run on a CPU in the L3 domain. mon_event_read() uses
smp_call_on_cpu() for that. It queues work on that CPU and sleeps until
a kworker runs it. When that CPU is busy, this takes a long time, and
the mutex stays held all along.

Commit 09909e098113 ("x86/resctrl: Queue mon_event_read() instead of
sending an IPI") did this for MPAM, whose reads may sleep. On x86 a
read is just one WRMSR and one RDMSR and it don't need to sleep.

Add CONFIG_RESCTRL_MON_READ_IRQSAFE, which x86 selects. With it, read
the counter with interrupts off: on the current CPU if it is a
housekeeping (not nohz_full) CPU in the domain, otherwise with an IPI
to one. If every CPU in the domain is nohz_full, keep the existing
smp_call_function_any() fallback. MPAM and other architectures keep
the old path. Peter Newman posted a similar change in 2024 [4].

Results on a 316-CPU AMD EPYC with busy target CPUs, and readers that
copy the fleet agents, per 60 s run:

                                       before    after
  hold time per read, average          350 us    4 us
  hold time per read, worst            3.4 ms    109 us
  time off CPU while holding           9 s       0
  one pass over 750 files, average     360 ms    7.4 ms

The cost: interrupts are off on the reading CPU for about 0.5 us per
counter, and up to 131 us for a root group read with 128 MON groups.
A reader that runs every 100 ms used up to 29% more system time,
because it now spins for the IPI. A kernel with lockdep and
DEBUG_ATOMIC_SLEEP gave no warnings while groups were created and
removed and CPUs went offline under the readers.

Link: https://github.com/facebookincubator/below [1]
Link: https://github.com/sched-ext/scx [2]
Link: https://github.com/facebookincubator/dynolog [3]
Link: https://lore.kernel.org/20241106154306.2721688-2-peternewman@google.com [4]
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
---
 arch/x86/Kconfig         |  1 +
 fs/resctrl/Kconfig       |  8 ++++++++
 fs/resctrl/ctrlmondata.c | 12 ++++++++++--
 include/linux/resctrl.h  |  5 +++++
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 15fd9ec5ecac..8512b0980f6a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -523,6 +523,7 @@ config X86_CPU_RESCTRL
 	select ARCH_HAS_CPU_RESCTRL
 	select RESCTRL_FS
 	select RESCTRL_FS_PSEUDO_LOCK
+	select RESCTRL_MON_READ_IRQSAFE
 	help
 	  Enable x86 CPU resource control support.
 
diff --git a/fs/resctrl/Kconfig b/fs/resctrl/Kconfig
index 21671301bd8a..912626bb18f6 100644
--- a/fs/resctrl/Kconfig
+++ b/fs/resctrl/Kconfig
@@ -37,3 +37,11 @@ config RESCTRL_RMID_DEPENDS_ON_CLOSID
 	  Enabled by the architecture when the RMID values depend on the CLOSID.
 	  This causes the CLOSID allocator to search for CLOSID with clean
 	  RMID.
+
+config RESCTRL_MON_READ_IRQSAFE
+	bool
+	depends on RESCTRL_FS
+	help
+	  Enabled by the architecture when reading a monitoring counter
+	  never sleeps. resctrl then reads it with interrupts off, on the
+	  local CPU or by IPI, instead of sleeping with rdtgroup_mutex held.
diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index cafebdff70dc..c6fea953e962 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -601,10 +601,18 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
 	 * MPAM's resctrl_arch_rmid_read() is unable to read the
 	 * counters on some platforms if its called in IRQ context.
 	 */
-	if (tick_nohz_full_cpu(cpu))
+	if (tick_nohz_full_cpu(cpu)) {
 		smp_call_function_any(cpumask, mon_event_count, rr, 1);
-	else
+	} else if (IS_ENABLED(CONFIG_RESCTRL_MON_READ_IRQSAFE)) {
+		int this_cpu = raw_smp_processor_id();
+
+		if (cpumask_test_cpu(this_cpu, cpumask) &&
+		    !tick_nohz_full_cpu(this_cpu))
+			cpu = this_cpu;
+		smp_call_function_single(cpu, mon_event_count, rr, true);
+	} else {
 		smp_call_on_cpu(cpu, smp_mon_event_count, rr, false);
+	}
 
 out_ctx_free:
 	if (rr->arch_mon_ctx)
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 10dfdca7f4bf..2c6a19263d98 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -570,6 +570,9 @@ void resctrl_arch_pre_mount(void);
  * a CPU that belongs to domain @d. e.g. use smp_call_on_cpu() or
  * schedule_work_on(). This function can be called with interrupts masked,
  * e.g. using smp_call_function_any(), but may consistently return an error.
+ * If the architecture selects CONFIG_RESCTRL_MON_READ_IRQSAFE, event file
+ * reads that must run in domain @d are done with interrupts masked. The
+ * overflow and limbo handlers still call it from process context.
  *
  * Return:
  * 0 on success, or -EIO, -EINVAL etc on error.
@@ -679,6 +682,8 @@ void resctrl_arch_config_cntr(struct rdt_resource *r, struct rdt_l3_mon_domain *
  * Called on a CPU that belongs to domain @d when "mbm_event" mode is enabled.
  * Called from a non-migrateable process context via smp_call_on_cpu() unless all
  * CPUs are nohz_full, in which case it is called via IPI (smp_call_function_any()).
+ * If the architecture selects CONFIG_RESCTRL_MON_READ_IRQSAFE, event file
+ * reads are instead done with interrupts masked, directly or via IPI.
  *
  * Return:
  * 0 on success, or -EIO, -EINVAL etc on error.
-- 
2.53.0-Meta


                 reply	other threads:[~2026-10-20 15:14 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261020151352.2346257-1-shakeel.butt@linux.dev \
    --to=shakeel.butt@linux.dev \
    --cc=Dave.Martin@arm.com \
    --cc=babu.moger@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=james.morse@arm.com \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peternewman@google.com \
    --cc=reinette.chatre@intel.com \
    --cc=tglx@kernel.org \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®