[PATCH v2 10/16] x86/resctrl: Add PLZA state tracking and context switch handling

Babu Moger
2026-03-12T20:38:51Z

When kernel mode (e.g., PLZA) is enabled, the resctrl sched-in path must
program MSR_IA32_PQR_PLZA_ASSOC in addition to IA32_PQR_ASSOC.

Add resctrl_kmode_mon_en() to indicate whether kernel mode monitoring needs
to be enabled (GLOBAL_ASSIGN_CTRL_ASSIGN_MON). Task's kmode takes
precedence when kmode is enabled for that task; otherwise, fall back to the
per-CPU default_kmode. Write MSR_IA32_PQR_PLZA_ASSOC only when kmode is
changed.

Protect the PLZA path with rdt_kmode_enable_key to avoid overhead when
kmode is disabled.

Signed-off-by: Babu Moger <babu.moger@amd.com>
---
v2: Updated code comments.
Added new function resctrl_kmode_mon_en() to check if kernel mode
monitoring needs to be enabled.
---
arch/x86/include/asm/resctrl.h | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index 167be18983c1..ccfd95b98bac 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -57,6 +57,9 @@ DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state);
extern bool rdt_alloc_capable;
extern bool rdt_mon_capable;

+/* Global kernel mode config; used by resctrl_kmode_mon_en(). */
+extern struct resctrl_kmode_cfg resctrl_kcfg;
+
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
@@ -108,6 +111,17 @@ static inline void resctrl_arch_disable_kmode(void)
static_branch_dec_cpuslocked(&rdt_enable_key);
}

+/**
+ * resctrl_kmode_mon_en() - True when kernel mode requires RMID in PLZA MSR
+ *
+ * When GLOBAL_ASSIGN_CTRL_ASSIGN_MON is active, MSR_IA32_PQR_PLZA_ASSOC must
+ * program both CLOSID and RMID for kernel work; otherwise only CLOSID is used.
+ */
+static bool resctrl_kmode_mon_en(void)
+{
+ return resctrl_kcfg.kmode_cur & GLOBAL_ASSIGN_CTRL_ASSIGN_MON;
+}
+
/*
* __resctrl_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR
*
@@ -127,6 +141,7 @@ static inline void __resctrl_sched_in(struct task_struct *tsk)
struct resctrl_pqr_state *state = this_cpu_ptr(&pqr_state);
u32 closid = READ_ONCE(state->default_closid);
u32 rmid = READ_ONCE(state->default_rmid);
+ u32 kmode = READ_ONCE(state->default_kmode);
u32 tmp;

/*
@@ -150,6 +165,24 @@ static inline void __resctrl_sched_in(struct task_struct *tsk)
state->cur_rmid = rmid;
wrmsr(MSR_IA32_PQR_ASSOC, rmid, closid);
}
+
+ /*
+ * When kernel mode (e.g. PLZA) is enabled, program MSR_IA32_PQR_PLZA_ASSOC.
+ * Task's kmode overrides per-CPU default_kmode. Only write the MSR when
+ * kmode has changed to avoid unnecessary writes on the scheduler hot path.
+ */
+ if (static_branch_likely(&rdt_kmode_enable_key)) {
+ tmp = READ_ONCE(tsk->kmode);
+ if (tmp)
+ kmode = tmp;
+
+ if (kmode != state->cur_kmode) {
+ state->cur_kmode = kmode;
+ wrmsr(MSR_IA32_PQR_PLZA_ASSOC,
+ resctrl_kmode_mon_en() ? (RMID_EN | state->kmode_rmid) : 0,
+ (kmode ? PLZA_EN : 0) | (CLOSID_EN | state->kmode_closid));
+ }
+ }
}

static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
--
2.43.0