From: Chen Yu <yu.c.chen@intel.com>
To: Reinette Chatre <reinette.chatre@intel.com>,
Tony Luck <tony.luck@intel.com>
Cc: Ben Horgan <ben.horgan@arm.com>,
"James Morse" <james.morse@arm.com>,
Dave Martin <Dave.Martin@arm.com>,
Babu Moger <babu.moger@amd.com>, Fenghua Yu <fenghuay@nvidia.com>,
Borislav Petkov <bp@alien8.de>,
Thomas Gleixner <tglx@linutronix.de>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
Peter Newman <peternewman@google.com>,
chen.yu@linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 28/31] x86/resctrl: Emulate the legacy MBA controller via the region MAX controls
Date: Mon, 3 Aug 2026 00:08:06 +0800 [thread overview]
Message-ID: <4023c8b8f84d1b896d46b56dd3737ec96325ac3a.1785680802.git.yu.c.chen@intel.com> (raw)
In-Reply-To: <cover.1785680802.git.yu.c.chen@intel.com>
On ERDT platforms the legacy MBA "default" controller does have hardware of
its own, but the region-based MAX controllers are the preferred way to
throttle memory bandwidth. Rather than programming the legacy MSR, realize
the default controller's effect through the MAX controller of every memory
region, which keeps a single consistent throttling mechanism in use. Link
the default controller to the MAX controller of every available region via
resctrl_ctrl::emul in erdt_get_mem_config() so they are associated once
the controllers are created.
Route the arch control writes accordingly. When a control is emulated
(ctrl->emul is not empty), do not program the legacy MSR; instead
translate the configured value into each emulation controller's units and
program that controller's hardware.
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
---
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 75 ++++++++++++++++++++---
arch/x86/kernel/cpu/resctrl/erdt.c | 18 ++++++
include/linux/resctrl.h | 3 +
3 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index 7bacb8bf2e27..7fe48912d2d5 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -28,6 +28,48 @@ static void ctrl_hw_update(struct resctrl_ctrl *ctrl, struct rdt_ctrl_domain *d,
smp_call_function_any(&d->hdr.cpu_mask, rdt_ctrl_update, m, 1);
}
+static u32 emul_translate_val(struct resctrl_ctrl *src, struct resctrl_ctrl *dst,
+ u32 val)
+{
+ return val * dst->scalar.max_bw / src->scalar.max_bw;
+}
+
+static void _resctrl_arch_update_emul(struct rdt_resource *r,
+ struct resctrl_ctrl *ctrl,
+ struct rdt_ctrl_domain *d, u32 low, u32 high)
+{
+ struct rdt_hw_ctrl_domain *emul_hw_dom;
+ struct rdt_hw_ctrl_domain *hw_dom;
+ struct rdt_ctrl_domain *emul_d;
+ struct resctrl_ctrl *emul;
+ struct rdt_domain_hdr *hdr;
+ struct hw_param emul_param;
+ unsigned int i;
+
+ hw_dom = resctrl_to_arch_ctrl_dom(d);
+
+ for_each_emul_ctrl(emul, ctrl) {
+ hdr = resctrl_find_domain(&emul->domains, d->hdr.id, NULL);
+ if (!hdr)
+ continue;
+
+ emul_d = container_of(hdr, struct rdt_ctrl_domain, hdr);
+ emul_hw_dom = resctrl_to_arch_ctrl_dom(emul_d);
+
+ for (i = low; i < high; i++)
+ emul_hw_dom->ctrl_val[i] = emul_translate_val(ctrl, emul,
+ hw_dom->ctrl_val[i]);
+
+ emul_param.res = r;
+ emul_param.ctrl = emul;
+ emul_param.dom = emul_d;
+ emul_param.low = low;
+ emul_param.high = high;
+
+ ctrl_hw_update(emul, emul_d, &emul_param);
+ }
+}
+
int resctrl_arch_update_one(struct rdt_resource *r, struct resctrl_ctrl *ctrl,
struct rdt_ctrl_domain *d, u32 closid,
enum resctrl_conf_type t, u32 cfg_val)
@@ -42,12 +84,20 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct resctrl_ctrl *ctrl,
hw_dom->ctrl_val[idx] = cfg_val;
- hw_param.res = r;
- hw_param.ctrl = ctrl;
- hw_param.dom = d;
- hw_param.low = idx;
- hw_param.high = idx + 1;
- hw_ctrl->hw_update(&hw_param);
+ /*
+ * When this control is emulated, program the emulation controllers'
+ * hardware instead.
+ */
+ if (!list_empty(&ctrl->emul)) {
+ _resctrl_arch_update_emul(r, ctrl, d, idx, idx + 1);
+ } else {
+ hw_param.res = r;
+ hw_param.ctrl = ctrl;
+ hw_param.dom = d;
+ hw_param.low = idx;
+ hw_param.high = idx + 1;
+ hw_ctrl->hw_update(&hw_param);
+ }
return 0;
}
@@ -89,8 +139,17 @@ static void _resctrl_arch_update_domains(struct rdt_resource *r,
hw_param.high = max(hw_param.high, idx + 1);
}
}
- if (hw_param.res)
- ctrl_hw_update(ctrl, d, &hw_param);
+ if (hw_param.res) {
+ /*
+ * When this control is emulated, program the emulation
+ * controllers' hardware instead.
+ */
+ if (!list_empty(&ctrl->emul))
+ _resctrl_arch_update_emul(r, ctrl, d,
+ hw_param.low, hw_param.high);
+ else
+ ctrl_hw_update(ctrl, d, &hw_param);
+ }
}
}
diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resctrl/erdt.c
index 6464463973bb..4515e3251476 100644
--- a/arch/x86/kernel/cpu/resctrl/erdt.c
+++ b/arch/x86/kernel/cpu/resctrl/erdt.c
@@ -325,6 +325,7 @@ static void marc_hw_update(struct hw_param *m)
__init bool erdt_get_mem_config(struct rdt_resource *r)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+ struct resctrl_ctrl *def_ctrl = NULL, *ctrl;
struct resctrl_hw_ctrl *hw_ctrl;
struct erdt_domain_info *d;
struct acpi_erdt_marc *marc;
@@ -343,6 +344,13 @@ __init bool erdt_get_mem_config(struct rdt_resource *r)
max_regions = acpi_mrrm_max_mem_region();
hw_res->num_closid = max(hw_res->num_closid, erdt_max_clos + 1);
+ for_each_resource_ctrl(ctrl, r) {
+ if (ctrl->name == RESCTRL_CTRL_NAME_DEF) {
+ def_ctrl = ctrl;
+ break;
+ }
+ }
+
for (region = 0; region < max_regions; region++) {
for (type = RESCTRL_CTRL_REGION_TYPE_OPT; type < RESCTRL_CTRL_REGION_NR_CTRLS; type++) {
if (type == RESCTRL_CTRL_REGION_TYPE_OPT && !(marc->flags & MARC_FLAG_OPT))
@@ -374,6 +382,16 @@ __init bool erdt_get_mem_config(struct rdt_resource *r)
/* MARC controls live in MMIO, program from any CPU. */
hw_ctrl->r_ctrl.flags |= RESCTRL_CTRL_FLAG_ANY_CPU;
list_add_tail(&hw_ctrl->r_ctrl.entry, &r->controls);
+
+ /*
+ * Throttle memory bandwidth through the region MAX
+ * controls rather than the legacy MBA MSR, so let the
+ * MAX control of every region emulate the legacy MBA
+ * control.
+ */
+ if (def_ctrl && type == RESCTRL_CTRL_REGION_TYPE_MAX)
+ list_add_tail(&hw_ctrl->r_ctrl.emul_entry,
+ &def_ctrl->emul);
}
}
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 8260b09aa323..57615af637ad 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -51,6 +51,9 @@ int proc_resctrl_show(struct seq_file *m,
#define for_each_resource_ctrl(ctrl, r) \
list_for_each_entry(ctrl, &r->controls, entry)
+#define for_each_emul_ctrl(emul, ctrl) \
+ list_for_each_entry(emul, &ctrl->emul, emul_entry)
+
enum resctrl_res_level {
RDT_RESOURCE_L3,
RDT_RESOURCE_L2,
--
2.43.0
next prev parent reply other threads:[~2026-08-02 16:17 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-02 15:57 [RFC PATCH 00/31] Introduce region-aware RDT support Chen Yu
2026-08-02 16:02 ` [RFC PATCH 01/31] x86/topology: Export topo_lookup_cpuid() for resctrl use Chen Yu
2026-08-02 16:02 ` [RFC PATCH 02/31] x86/resctrl: Require 64-bit x86 for resctrl support Chen Yu
2026-08-02 16:02 ` [RFC PATCH 03/31] x86/resctrl: Parse ACPI ERDT table and save CACD cpumask for RMDD domains Chen Yu
2026-08-02 16:03 ` [RFC PATCH 04/31] x86/resctrl: Attach ACPI ERDT information to L3 mon domain on CPU online Chen Yu
2026-08-02 16:03 ` [RFC PATCH 05/31] x86/resctrl: Parse ACPI CMRC table Chen Yu
2026-08-04 17:19 ` Luck, Tony
2026-08-04 18:13 ` Luck, Tony
2026-08-05 4:59 ` Chen, Yu C
2026-08-02 16:03 ` [RFC PATCH 06/31] x86/resctrl: Refactor the monitor read function Chen Yu
2026-08-02 16:04 ` [RFC PATCH 07/31] fs/resctrl: Do not invoke smp_processor_id() in preemptible context Chen Yu
2026-08-02 16:04 ` [RFC PATCH 08/31] x86/resctrl: Introduce erdt_cpu_has() and erdt_support() Chen Yu
2026-08-02 16:05 ` [RFC PATCH 09/31] x86/resctrl: Add MMIO-based LLC occupancy monitoring support Chen Yu
2026-08-02 16:05 ` [RFC PATCH 10/31] Revert "x86/resctrl: NOT_FOR_INCLUSION: Example support for multiple controls" Chen Yu
2026-08-02 16:05 ` [RFC PATCH 11/31] x86/resctrl: Rename struct resctrl_membw to struct resctrl_ctrl_scalar Chen Yu
2026-08-02 16:05 ` [RFC PATCH 12/31] x86/resctrl: Rename struct resctrl_cache to struct resctrl_ctrl_bitmap Chen Yu
2026-08-02 16:05 ` [RFC PATCH 13/31] x86/resctrl: Add per-control and per-resource flags Chen Yu
2026-08-02 16:06 ` [RFC PATCH 14/31] x86/resctrl: Add emulation controller list to resctrl_ctrl Chen Yu
2026-08-02 16:06 ` [RFC PATCH 15/31] x86/resctrl: Parse ACPI MMRC table Chen Yu
2026-08-02 16:06 ` [RFC PATCH 16/31] x86/resctrl: Replace "msr" in monitoring data identifiers Chen Yu
2026-08-02 16:06 ` [RFC PATCH 17/31] x86/resctrl: Introduce region aware MBM event definitions Chen Yu
2026-08-02 16:06 ` [RFC PATCH 18/31] x86/resctrl: Introduce memory region based MBM read callback on MMIO space Chen Yu
2026-08-02 16:06 ` [RFC PATCH 19/31] x86/resctrl: Enable the region based events by adding them into the event Chen Yu
2026-08-02 16:06 ` [RFC PATCH 20/31] x86/resctrl: Rename msr_update to hw_update Chen Yu
2026-08-02 16:07 ` [RFC PATCH 21/31] x86/resctrl: Parse ACPI MARC table Chen Yu
2026-08-02 16:07 ` [RFC PATCH 22/31] fs/resctrl: Add region-based control names and resctrl_ctrl_name_region() Chen Yu
2026-08-02 16:07 ` [RFC PATCH 23/31] x86/resctrl: Add region aware MBA controllers Chen Yu
2026-08-02 16:07 ` [RFC PATCH 24/31] x86/resctrl: Attach ACPI ERDT information to ctrl domain on CPU online Chen Yu
2026-08-02 16:07 ` [RFC PATCH 25/31] x86/resctrl: Introduce region-based MBA write implementation on MMIO space Chen Yu
2026-08-04 21:13 ` Luck, Tony
2026-08-05 6:32 ` Chen, Yu C
2026-08-02 16:07 ` [RFC PATCH 26/31] x86/resctrl: Allow control writes from any CPU for MMIO controllers Chen Yu
2026-08-02 16:07 ` [RFC PATCH 27/31] x86/resctrl: Enable region-aware MBM/MBA via the RDT_CTRL register Chen Yu
2026-08-02 16:08 ` Chen Yu [this message]
2026-08-02 16:08 ` [RFC PATCH 29/31] fs/resctrl: Expose emulation controllers in a resource_schemata subdir Chen Yu
2026-08-02 16:08 ` [RFC PATCH 30/31] fs/resctrl: Fix excessive padding in schemata output Chen Yu
2026-08-02 16:08 ` [RFC PATCH 31/31] x86,fs/resctrl: Update Documentation for region aware RDT Chen Yu
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=4023c8b8f84d1b896d46b56dd3737ec96325ac3a.1785680802.git.yu.c.chen@intel.com \
--to=yu.c.chen@intel.com \
--cc=Dave.Martin@arm.com \
--cc=babu.moger@amd.com \
--cc=ben.horgan@arm.com \
--cc=bp@alien8.de \
--cc=chen.yu@linux.dev \
--cc=dave.hansen@linux.intel.com \
--cc=fenghuay@nvidia.com \
--cc=james.morse@arm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peternewman@google.com \
--cc=reinette.chatre@intel.com \
--cc=tglx@linutronix.de \
--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®