Skip to content

Commit 6789fb9

Browse files
author
James Morse
committed
arm_mpam: resctrl: Add CDP emulation
Intel RDT's CDP feature allows the cache to use a different control value depending on whether the accesses was for instruction fetch or a data access. MPAM's equivalent feature is the other way up: the CPU assigns a different partid label to traffic depending on whether it was instruction fetch or a data access, which causes the cache to use a different control value based solely on the partid. MPAM can emulate CDP, with the side effect that the alternative partid is seen by all MSC, it can't be enabled per-MSC. Add the resctrl hooks to turn this on or off. Add the helpers that match a closid against a task, which need to be aware that the value written to hardware is not the same as the one resctrl is using. Update the 'arm64_mpam_global_default' variable the arch code uses during context switch to know when the per-cpu value should be used instead. Also, update these per-cpu values and sync the resulting mpam partid/pmg configuration to hardware. resctrl can enable CDP for L2 caches, L3 caches or both. When it is enabled by one and not the other MPAM globally enabled CDP but hides the effect on the other cache resource. This hiding is possible as CPOR is the only supported cache control and that uses a resource bitmap; two partids with the same bitmap act as one. Awkwardly, the MB controls don't implement CDP and CDP can't be hidden as the memory bandwidth control is a maximum per partid which can't be modelled with more partids. If the total maximum is used for both the data and instruction partids then then the maximum may be exceeded and if it is split in two then the one using more bandwidth will hit a lower limit. Hence, hide the MB controls completely if CDP is enabled for any resource. Tested-by: Gavin Shan <gshan@redhat.com> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Tested-by: Peter Newman <peternewman@google.com> Tested-by: Zeng Heng <zengheng4@huawei.com> Tested-by: Punit Agrawal <punit.agrawal@oss.qualcomm.com> Tested-by: Jesse Chick <jessechick@os.amperecomputing.com> Cc: Dave Martin <Dave.Martin@arm.com> Cc: Amit Singh Tomar <amitsinght@marvell.com> Reviewed-by: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Co-developed-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: James Morse <james.morse@arm.com>
1 parent 9d2e1a9 commit 6789fb9

4 files changed

Lines changed: 126 additions & 0 deletions

File tree

arch/arm64/include/asm/mpam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef __ASM__MPAM_H
55
#define __ASM__MPAM_H
66

7+
#include <linux/arm_mpam.h>
78
#include <linux/bitfield.h>
89
#include <linux/jump_label.h>
910
#include <linux/percpu.h>

drivers/resctrl/mpam_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ struct mpam_resctrl_dom {
342342
struct mpam_resctrl_res {
343343
struct mpam_class *class;
344344
struct rdt_resource resctrl_res;
345+
bool cdp_enabled;
345346
};
346347

347348
static inline int mpam_alloc_csu_mon(struct mpam_class *class)

drivers/resctrl/mpam_resctrl.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ static struct mpam_resctrl_res mpam_resctrl_controls[RDT_NUM_RESOURCES];
3535
/* The lock for modifying resctrl's domain lists from cpuhp callbacks. */
3636
static DEFINE_MUTEX(domain_list_lock);
3737

38+
/*
39+
* MPAM emulates CDP by setting different PARTID in the I/D fields of MPAM0_EL1.
40+
* This applies globally to all traffic the CPU generates.
41+
*/
3842
static bool cdp_enabled;
3943

4044
bool resctrl_arch_alloc_capable(void)
@@ -50,6 +54,74 @@ bool resctrl_arch_alloc_capable(void)
5054
return false;
5155
}
5256

57+
bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid)
58+
{
59+
return mpam_resctrl_controls[rid].cdp_enabled;
60+
}
61+
62+
/**
63+
* resctrl_reset_task_closids() - Reset the PARTID/PMG values for all tasks.
64+
*
65+
* At boot, all existing tasks use partid zero for D and I.
66+
* To enable/disable CDP emulation, all these tasks need relabelling.
67+
*/
68+
static void resctrl_reset_task_closids(void)
69+
{
70+
struct task_struct *p, *t;
71+
72+
read_lock(&tasklist_lock);
73+
for_each_process_thread(p, t) {
74+
resctrl_arch_set_closid_rmid(t, RESCTRL_RESERVED_CLOSID,
75+
RESCTRL_RESERVED_RMID);
76+
}
77+
read_unlock(&tasklist_lock);
78+
}
79+
80+
int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
81+
{
82+
u32 partid_i = RESCTRL_RESERVED_CLOSID, partid_d = RESCTRL_RESERVED_CLOSID;
83+
int cpu;
84+
85+
/*
86+
* resctrl_arch_set_cdp_enabled() is only called with enable set to
87+
* false on error and unmount.
88+
*/
89+
cdp_enabled = enable;
90+
mpam_resctrl_controls[rid].cdp_enabled = enable;
91+
92+
/* The mbw_max feature can't hide cdp as it's a per-partid maximum. */
93+
if (cdp_enabled && !mpam_resctrl_controls[RDT_RESOURCE_MBA].cdp_enabled)
94+
mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = false;
95+
96+
if (mpam_resctrl_controls[RDT_RESOURCE_MBA].cdp_enabled &&
97+
mpam_resctrl_controls[RDT_RESOURCE_MBA].class)
98+
mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = true;
99+
100+
if (enable) {
101+
if (mpam_partid_max < 1)
102+
return -EINVAL;
103+
104+
partid_d = resctrl_get_config_index(RESCTRL_RESERVED_CLOSID, CDP_DATA);
105+
partid_i = resctrl_get_config_index(RESCTRL_RESERVED_CLOSID, CDP_CODE);
106+
}
107+
108+
mpam_set_task_partid_pmg(current, partid_d, partid_i, 0, 0);
109+
WRITE_ONCE(arm64_mpam_global_default, mpam_get_regval(current));
110+
111+
resctrl_reset_task_closids();
112+
113+
for_each_possible_cpu(cpu)
114+
mpam_set_cpu_defaults(cpu, partid_d, partid_i, 0, 0);
115+
on_each_cpu(resctrl_arch_sync_cpu_closid_rmid, NULL, 1);
116+
117+
return 0;
118+
}
119+
120+
static bool mpam_resctrl_hide_cdp(enum resctrl_res_level rid)
121+
{
122+
return cdp_enabled && !resctrl_arch_get_cdp_enabled(rid);
123+
}
124+
53125
/*
54126
* MSC may raise an error interrupt if it sees an out or range partid/pmg,
55127
* and go on to truncate the value. Regardless of what the hardware supports,
@@ -115,6 +187,30 @@ void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
115187
}
116188
}
117189

190+
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
191+
{
192+
u64 regval = mpam_get_regval(tsk);
193+
u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
194+
195+
if (cdp_enabled)
196+
tsk_closid >>= 1;
197+
198+
return tsk_closid == closid;
199+
}
200+
201+
/* The task's pmg is not unique, the partid must be considered too */
202+
bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
203+
{
204+
u64 regval = mpam_get_regval(tsk);
205+
u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
206+
u32 tsk_rmid = FIELD_GET(MPAM0_EL1_PMG_D, regval);
207+
208+
if (cdp_enabled)
209+
tsk_closid >>= 1;
210+
211+
return (tsk_closid == closid) && (tsk_rmid == rmid);
212+
}
213+
118214
struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
119215
{
120216
if (l >= RDT_NUM_RESOURCES)
@@ -247,6 +343,14 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
247343
dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
248344
cprops = &res->class->props;
249345

346+
/*
347+
* When CDP is enabled, but the resource doesn't support it,
348+
* the control is cloned across both partids.
349+
* Pick one at random to read:
350+
*/
351+
if (mpam_resctrl_hide_cdp(r->rid))
352+
type = CDP_DATA;
353+
250354
partid = resctrl_get_config_index(closid, type);
251355
cfg = &dom->ctrl_comp->cfg[partid];
252356

@@ -274,6 +378,7 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
274378
int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
275379
u32 closid, enum resctrl_conf_type t, u32 cfg_val)
276380
{
381+
int err;
277382
u32 partid;
278383
struct mpam_config cfg;
279384
struct mpam_props *cprops;
@@ -291,6 +396,9 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
291396
dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
292397
cprops = &res->class->props;
293398

399+
if (mpam_resctrl_hide_cdp(r->rid))
400+
t = CDP_DATA;
401+
294402
partid = resctrl_get_config_index(closid, t);
295403
if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r)) {
296404
pr_debug("Not alloc capable or computed PARTID out of range\n");
@@ -313,6 +421,20 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
313421
return -EINVAL;
314422
}
315423

424+
/*
425+
* When CDP is enabled, but the resource doesn't support it, we need to
426+
* apply the same configuration to the other partid.
427+
*/
428+
if (mpam_resctrl_hide_cdp(r->rid)) {
429+
partid = resctrl_get_config_index(closid, CDP_CODE);
430+
err = mpam_apply_config(dom->ctrl_comp, partid, &cfg);
431+
if (err)
432+
return err;
433+
434+
partid = resctrl_get_config_index(closid, CDP_DATA);
435+
return mpam_apply_config(dom->ctrl_comp, partid, &cfg);
436+
}
437+
316438
return mpam_apply_config(dom->ctrl_comp, partid, &cfg);
317439
}
318440

include/linux/arm_mpam.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ void resctrl_arch_set_cpu_default_closid(int cpu, u32 closid);
5656
void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
5757
void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid);
5858
void resctrl_arch_sched_in(struct task_struct *tsk);
59+
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid);
60+
bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
5961

6062
/**
6163
* mpam_register_requestor() - Register a requestor with the MPAM driver

0 commit comments

Comments
 (0)