2024-01-17 14:14:41

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 00/14] ARM: MPAM: add support for priority partitioning control

This patch-set is continuation to the RFC[1], we sent last year. The patches
that we sent earlier, embed the DSPRI (Downstream priority) value into already
existing schemata file, which is used to configure CAT (Cache Allocation Technology)
capabilities. For instance, in order to configure Downstream priority, DSPRI
value is passed in following way:

echo L3:0=ffff,a > schemata, where "a" dspri value, and ffff cache portion bitmaps.

But instead of using already existing, "L3" schemata, we can have new schemata
that is dedicated to this new/extended priority control (at the moment, extended
control is limited to only DSPRI but we can put new/more control same way). For
instance, this version uses new schemata L3DSPRI, and following is the way
to configure downstream priority value.

echo L3DSPRI:0=a > schemata, where "a" is dspri value.

Overall, the schemata for a system that support all these controls looks like:

MB:0=100
L3DSPRI:0=f
L3:0=ffff

and this approach aids in code decluttering, for instance, we don't have to
really care about dspri flags (dspri_store, dspri_show, used in RFC version).

To help creating new schemata, Patch(1/14) is introduced (new one), It
basically divide the resource control type into two groups, and map it
to list of schemata(s).

"SCHEMA_BASIC" type is for already exiting schemata ("L3", and "MB") used
to configure features like CAT (Cache Allocation Technology), and MBA
(Memory Bandwidth Allocation).

"SCHEMA_DSPRI" type is for schemata (L3DSPRI), and used to configure
Downstream priority values. This is used in patch (3/14) when the
schemata list is extended to support priority partition control.

Took this idea from openEuler Kernel[1], pointed by Jonathan in previous discussion.

This division into groups help in configuring resource control of different
types based on control types (patch 6/14, and patch 8/14).

For now, patch (5/14), and (9/14) is split for easy review, eventually these
get squashed.

Patch (12/14) is reworked, and now priority value is inverted based on
DSPRI_0_IS_LOW value.

Patch(14/14) is a new patch, that export Maximum DSPRI value to resctrl's info
directory.

At the moment, these patches are restricted to support only the Downstream priority
control, but if this approach looks okay, can have support for both the priority controls
in next variant.

Also, these patches[3] are still based on older MPAM tree[3] from James, as facing some
trouble setting up the resource control with latest snapshots.

[1]: https://lore.kernel.org/lkml/[email protected]/T/
[2]: https://github.com/openeuler-mirror/kernel/commit/8139268b70398c37843a38bf8c7b243ad1f20c97
[3]: https://github.com/Amit-Radur/linux/commit/71ac4cca1eccb831ce04d3094f0cf794fc9d2d72
[4]: https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git/log/?h=mpam/snapshot/v6.2

Amit Singh Tomar (14):
fs/resctrl: group the resource control types for schemata list
arm_mpam: resctrl: Detect priority partitioning capability
arm_mpam: resctrl: extend the schemata list to support priority
partition
fs/resctrl: Set-up downstream priority partition resources
fs/resctrl: fetch configuration based on control type
arm_mpam: resctrl: Retrieve priority values from arch code
fs/resctrl: Schemata write only for intended resource
fs/resctrl: Extend schemata write for priority partition control
fs/resctrl: set configuration based on Control type
arm_mpam: resctrl: Facilitate writing downstream priority value
arm_mpam: Fix Downstream and internal priority mask
arm_mpam: Program Downstream priority value
arm_mpam: Handle resource instances mapped to different controls
arm64/mpam: resctrl: export DSPRI value to info directory

arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 9 +-
drivers/platform/mpam/mpam_devices.c | 72 +++++++++++----
drivers/platform/mpam/mpam_internal.h | 1 +
drivers/platform/mpam/mpam_resctrl.c | 81 +++++++++++++----
fs/resctrl/ctrlmondata.c | 74 +++++++++++++--
fs/resctrl/monitor.c | 6 +-
fs/resctrl/rdtgroup.c | 105 ++++++++++++++++++----
include/linux/resctrl.h | 19 +++-
include/linux/resctrl_types.h | 9 ++
9 files changed, 309 insertions(+), 67 deletions(-)

--
2.25.1



2024-01-17 14:14:55

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 01/14] fs/resctrl: group the resource control types for schemata list

At the moment, resource control group support the basic control features
(that can be applied to system resources like cache, and Memory)
such as CAT (Cache Allocation Technology), and MBA (Memory Bandwidth
Allocation).

Apart from these basic controls, System can support other controls that
does not directly affect the allocation of memory-system resources.
Instead, it has an effect on conflicts that arise during access to
resources, such as Priority partitioning found on ARM MPAM.

In order to support control types of different nature, lets divide them
into different groups, already existing control features (CAT, and MBA)
is grouped under basic schemata type .i.e. SCHEMATA_BASIC, and to support
priority partition (the downstream priority one), it is placed under
SCHEMA_DSPRI control type. These control type is associated with list(s)
of schemata.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change, it's new patch.
---
fs/resctrl/rdtgroup.c | 26 ++++++++++++++++----------
include/linux/resctrl.h | 1 +
include/linux/resctrl_types.h | 6 ++++++
3 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 9c5dfaaa7fa2..12e31d4dddf6 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -2256,7 +2256,9 @@ static int rdt_enable_ctx(struct rdt_fs_context *ctx)
return ret;
}

-static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type)
+static int schemata_list_add(struct rdt_resource *r,
+ enum resctrl_conf_type type,
+ enum resctrl_ctrl_type ctrl_type)
{
struct resctrl_schema *s;
const char *suffix = "";
@@ -2284,10 +2286,12 @@ static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type
break;
}

- ret = snprintf(s->name, sizeof(s->name), "%s%s", r->name, suffix);
- if (ret >= sizeof(s->name)) {
- kfree(s);
- return -EINVAL;
+ if (ctrl_type == SCHEMA_BASIC) {
+ ret = snprintf(s->name, sizeof(s->name), "%s%s", r->name, suffix);
+ if (ret >= sizeof(s->name)) {
+ kfree(s);
+ return -EINVAL;
+ }
}

cl = strlen(s->name);
@@ -2300,14 +2304,15 @@ static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type
if (r->cdp_capable && !resctrl_arch_get_cdp_enabled(r->rid))
cl += 4;

- if (cl > max_name_width)
+ if (cl > max_name_width && ctrl_type == SCHEMA_BASIC)
max_name_width = cl;

/*
* Choose a width for the resource data based on the resource that has
* widest cbm/data_width.
*/
- max_data_width = max(max_data_width, r->data_width);
+ if (ctrl_type == SCHEMA_BASIC)
+ max_data_width = max(max_data_width, r->data_width);

INIT_LIST_HEAD(&s->list);
list_add(&s->list, &resctrl_schema_all);
@@ -2328,17 +2333,18 @@ static int schemata_list_create(void)
continue;

if (resctrl_arch_get_cdp_enabled(r->rid)) {
- ret = schemata_list_add(r, CDP_CODE);
+ ret = schemata_list_add(r, CDP_CODE, SCHEMA_BASIC);
if (ret)
break;

- ret = schemata_list_add(r, CDP_DATA);
+ ret = schemata_list_add(r, CDP_DATA, SCHEMA_BASIC);
} else {
- ret = schemata_list_add(r, CDP_NONE);
+ ret = schemata_list_add(r, CDP_NONE, SCHEMA_BASIC);
}

if (ret)
break;
+
}

return ret;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 3ad308e9e226..125c4b0c2ff7 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -249,6 +249,7 @@ struct resctrl_schema {
struct list_head list;
char name[8];
enum resctrl_conf_type conf_type;
+ enum resctrl_ctrl_type ctrl_type;
struct rdt_resource *res;
u32 num_closid;
};
diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h
index 3897de9c4ecb..b9268ec3ba71 100644
--- a/include/linux/resctrl_types.h
+++ b/include/linux/resctrl_types.h
@@ -57,6 +57,12 @@ enum resctrl_res_level {
RDT_NUM_RESOURCES,
};

+enum resctrl_ctrl_type {
+ SCHEMA_BASIC = 0,
+ SCHEMA_DSPRI,
+ SCHEMA_NUM_CTRL_TYPE
+};
+
#define CDP_NUM_TYPES (CDP_DATA + 1)

/*
--
2.25.1


2024-01-17 14:15:15

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 04/14] fs/resctrl: Set-up downstream priority partition resources

Upon resource control group creation, Cache portion bitmap, and Memory
bandwidth allocation gets initialized to the default/maximum values,
obtained from resource control code.

Let's replicate it for priority partition resource, and setup the default
downstream priority value.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Reworked a bit to support new Schemata L3DSPRI, for
instance, removed the "dspri_store" flag.
---
drivers/platform/mpam/mpam_resctrl.c | 1 +
fs/resctrl/rdtgroup.c | 21 +++++++++++++++++++++
include/linux/resctrl.h | 2 ++
3 files changed, 24 insertions(+)

diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 6fd2bfeffa0a..02efec42bbe2 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -735,6 +735,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
class->props.dspri_wd = 0x10;

r->dspri_data_width = (class->props.dspri_wd + 3) / 4;
+ r->default_dspri_ctrl = BIT_MASK(class->props.dspri_wd) - 1;
}

/*
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 568bb9bb7913..d57eb2c7afa7 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -3071,6 +3071,21 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
return 0;
}

+/* Initialize with default downstream priority values. */
+static int rdtgroup_init_dspri(struct rdt_resource *r, u32 closid)
+{
+ struct resctrl_staged_config *cfg;
+ struct rdt_domain *d;
+
+ list_for_each_entry(d, &r->domains, list) {
+ cfg = &d->staged_config[CDP_NONE];
+ cfg->new_ctrl = r->default_dspri_ctrl;
+ cfg->have_new_ctrl = true;
+ }
+
+ return 0;
+}
+
/* Initialize MBA resource with default values. */
static void rdtgroup_init_mba(struct rdt_resource *r, u32 closid)
{
@@ -3108,6 +3123,12 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
return ret;
}

+ if (r->priority_cap && s->ctrl_type == SCHEMA_DSPRI) {
+ ret = rdtgroup_init_dspri(r, rdtgrp->closid);
+ if (ret < 0)
+ return ret;
+ }
+
ret = resctrl_arch_update_domains(r, rdtgrp->closid);
if (ret < 0) {
rdt_last_cmd_puts("Failed to initialize allocations\n");
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index cb17c7704fd7..93b3e3b21d5d 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -207,6 +207,7 @@ struct resctrl_membw {
* @data_width: Character width of data when displaying
* @dspri_data_width Character width of dspri value when displaying
* @default_ctrl: Specifies default cache cbm or memory B/W percent.
+ * @default_dspri_ctrl: Specifies default downstream priority value.
* @format_str: Per resource format string to show domain value
* @evt_list: List of monitoring events
* @fflags: flags to choose base and info files
@@ -226,6 +227,7 @@ struct rdt_resource {
int data_width;
int dspri_data_width;
u32 default_ctrl;
+ u32 default_dspri_ctrl;
const char *format_str;
struct list_head evt_list;
unsigned long fflags;
--
2.25.1


2024-01-17 14:15:16

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 03/14] arm_mpam: resctrl: extend the schemata list to support priority partition

At the moment, "schemata" list is consist of two basic control types .i.e.
cache portion bitmap (CPBM), and memory bandwidth allocation (MBA),
represented as following under schemata file.

MB:0=0100
L3:0=ffff

Lets' extend the "schemata" list to support priority partition control,
This control is listed in following format (last column indicates the
priority value) under schemata file.

L3DSPRI:0=f

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* This patch is reworked, Now in order to configure DSPRI partition control
dedicated schemata is used (L3DSPRI).
---
drivers/platform/mpam/mpam_resctrl.c | 7 +++++-
fs/resctrl/rdtgroup.c | 34 ++++++++++++++++++++++------
include/linux/resctrl.h | 3 +++
include/linux/resctrl_types.h | 3 +++
4 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 09618d9ceb1d..6fd2bfeffa0a 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -729,8 +729,13 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
exposed_alloc_capable = true;
}

- if (has_ppart)
+ if (has_ppart) {
r->priority_cap = true;
+ if (class->props.dspri_wd > 0x10)
+ class->props.dspri_wd = 0x10;
+
+ r->dspri_data_width = (class->props.dspri_wd + 3) / 4;
+ }

/*
* MBWU counters may be 'local' or 'total' depending on where
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 12e31d4dddf6..568bb9bb7913 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -2261,7 +2261,7 @@ static int schemata_list_add(struct rdt_resource *r,
enum resctrl_ctrl_type ctrl_type)
{
struct resctrl_schema *s;
- const char *suffix = "";
+ const char *suffix = "", *ext_suffix = "";
int ret, cl;

s = kzalloc(sizeof(*s), GFP_KERNEL);
@@ -2286,12 +2286,22 @@ static int schemata_list_add(struct rdt_resource *r,
break;
}

- if (ctrl_type == SCHEMA_BASIC) {
+ s->ctrl_type = ctrl_type;
+ switch (ctrl_type) {
+ case SCHEMA_DSPRI:
+ ext_suffix = "DSPRI";
+ break;
+ }
+
+ if (ctrl_type == SCHEMA_BASIC)
ret = snprintf(s->name, sizeof(s->name), "%s%s", r->name, suffix);
- if (ret >= sizeof(s->name)) {
- kfree(s);
- return -EINVAL;
- }
+ else
+ ret = snprintf(s->name, sizeof(s->name), "%s%s%s", r->name,
+ suffix, ext_suffix);
+
+ if (ret >= sizeof(s->name)) {
+ kfree(s);
+ return -EINVAL;
}

cl = strlen(s->name);
@@ -2312,7 +2322,9 @@ static int schemata_list_add(struct rdt_resource *r,
* widest cbm/data_width.
*/
if (ctrl_type == SCHEMA_BASIC)
- max_data_width = max(max_data_width, r->data_width);
+ s->max_data_width = max(max_data_width, r->data_width);
+ else
+ s->max_data_width = max(max_data_width, r->dspri_data_width);

INIT_LIST_HEAD(&s->list);
list_add(&s->list, &resctrl_schema_all);
@@ -2322,6 +2334,7 @@ static int schemata_list_add(struct rdt_resource *r,

static int schemata_list_create(void)
{
+ enum resctrl_ctrl_type ctrl_type;
enum resctrl_res_level i;
struct rdt_resource *r;
int ret = 0;
@@ -2345,6 +2358,13 @@ static int schemata_list_create(void)
if (ret)
break;

+ for_each_extend_ctrl_type(ctrl_type) {
+ if (ctrl_type == 1 && r->priority_cap) {
+ ret = schemata_list_add(r, CDP_NONE, SCHEMA_DSPRI);
+ if (ret)
+ break;
+ }
+ }
}

return ret;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index d49aed80a05e..cb17c7704fd7 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -205,6 +205,7 @@ struct resctrl_membw {
* @domains: RCU list of all domains for this resource
* @name: Name to use in "schemata" file.
* @data_width: Character width of data when displaying
+ * @dspri_data_width Character width of dspri value when displaying
* @default_ctrl: Specifies default cache cbm or memory B/W percent.
* @format_str: Per resource format string to show domain value
* @evt_list: List of monitoring events
@@ -223,6 +224,7 @@ struct rdt_resource {
struct list_head domains;
char *name;
int data_width;
+ int dspri_data_width;
u32 default_ctrl;
const char *format_str;
struct list_head evt_list;
@@ -256,6 +258,7 @@ struct resctrl_schema {
enum resctrl_ctrl_type ctrl_type;
struct rdt_resource *res;
u32 num_closid;
+ int max_data_width;
};

/*
diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h
index b9268ec3ba71..b1a22053d7cd 100644
--- a/include/linux/resctrl_types.h
+++ b/include/linux/resctrl_types.h
@@ -57,6 +57,9 @@ enum resctrl_res_level {
RDT_NUM_RESOURCES,
};

+#define for_each_extend_ctrl_type(t) \
+ for (t = SCHEMA_DSPRI; t != SCHEMA_NUM_CTRL_TYPE; t++)
+
enum resctrl_ctrl_type {
SCHEMA_BASIC = 0,
SCHEMA_DSPRI,
--
2.25.1


2024-01-17 14:15:53

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 05/14] fs/resctrl: fetch configuration based on control type

Now that, we have support for different control types, divided into
the BASIC and PRIORITY controls types. Schemata list is pertained to
the SCHEMAT_BASIC control type that is used to set up/configure
CAT (Cache Allocation Technology) and MBA (Memory Bandwidth Allocation)
capabilities, and SCHEMAT_DSPRI used to configure downstream priority
partitioning. Let's add boilerplate changes to fetch the control
configuration based on different control types.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change, it's new patch.
---
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 3 ++-
drivers/platform/mpam/mpam_resctrl.c | 3 ++-
fs/resctrl/ctrlmondata.c | 6 ++++--
fs/resctrl/monitor.c | 3 ++-
fs/resctrl/rdtgroup.c | 19 +++++++++++++------
include/linux/resctrl.h | 3 ++-
6 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index 0d10107eab62..b34e86cfc111 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -116,7 +116,8 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
}

u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type type)
+ u32 closid, enum resctrl_conf_type type,
+ enum resctrl_conf_type ctrl_type)
{
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
u32 idx = resctrl_get_config_index(closid, type);
diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 02efec42bbe2..4c44d65e6047 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -848,7 +848,8 @@ void mpam_resctrl_exit(void)
}

u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type type)
+ u32 closid, enum resctrl_conf_type type,
+ enum resctrl_ctrl_type ctrl_type)
{
u32 partid;
struct mpam_config *cfg;
diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index 27d8bc25a4cb..451cbb7357fb 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -373,6 +373,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,

static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid)
{
+ enum resctrl_ctrl_type ctrl_type = schema->ctrl_type;
struct rdt_resource *r = schema->res;
struct rdt_domain *dom;
bool sep = false;
@@ -390,9 +391,10 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
ctrl_val = dom->mbps_val[closid];
else
ctrl_val = resctrl_arch_get_config(r, dom, closid,
- schema->conf_type);
+ schema->conf_type,
+ ctrl_type);

- seq_printf(s, r->format_str, dom->id, max_data_width,
+ seq_printf(s, r->format_str, dom->id, schema->max_data_width,
ctrl_val);
sep = true;
}
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 885b0ca177b0..6c0804273753 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -478,7 +478,8 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
delta_bw = pmbm_data->delta_bw;

/* MBA resource doesn't support CDP */
- cur_msr_val = resctrl_arch_get_config(r_mba, dom_mba, closid, CDP_NONE);
+ cur_msr_val = resctrl_arch_get_config(r_mba, dom_mba, closid, CDP_NONE,
+ SCHEMA_BASIC);

/*
* For Ctrl groups read data from child monitor groups.
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index d57eb2c7afa7..92d9bee210eb 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -1064,7 +1064,8 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
if (!closid_allocated(i))
continue;
ctrl_val = resctrl_arch_get_config(r, dom, i,
- s->conf_type);
+ s->conf_type,
+ s->ctrl_type);
mode = rdtgroup_mode_by_closid(i);
switch (mode) {
case RDT_MODE_SHAREABLE:
@@ -1281,7 +1282,7 @@ static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d

/* Check for overlap with other resource groups */
for (i = 0; i < closids_supported(); i++) {
- ctrl_b = resctrl_arch_get_config(r, d, i, type);
+ ctrl_b = resctrl_arch_get_config(r, d, i, type, SCHEMA_BASIC);
mode = rdtgroup_mode_by_closid(i);
if (closid_allocated(i) && i != closid &&
mode != RDT_MODE_PSEUDO_LOCKSETUP) {
@@ -1365,7 +1366,8 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)
has_cache = true;
list_for_each_entry(d, &r->domains, list) {
ctrl = resctrl_arch_get_config(r, d, closid,
- s->conf_type);
+ s->conf_type,
+ s->ctrl_type);
if (rdtgroup_cbm_overlaps(s, d, ctrl, closid, false)) {
rdt_last_cmd_puts("Schemata overlaps\n");
return false;
@@ -1499,6 +1501,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
struct seq_file *s, void *v)
{
struct resctrl_schema *schema;
+ enum resctrl_ctrl_type ctrl_type;
enum resctrl_conf_type type;
struct rdtgroup *rdtgrp;
struct rdt_resource *r;
@@ -1536,6 +1539,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
list_for_each_entry(schema, &resctrl_schema_all, list) {
r = schema->res;
type = schema->conf_type;
+ ctrl_type = schema->ctrl_type;
sep = false;
seq_printf(s, "%*s:", max_name_width, schema->name);
list_for_each_entry(d, &r->domains, list) {
@@ -1549,7 +1553,8 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
else
ctrl = resctrl_arch_get_config(r, d,
closid,
- type);
+ type,
+ ctrl_type);
if (r->rid == RDT_RESOURCE_MBA)
size = ctrl;
else
@@ -3013,11 +3018,13 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
*/
if (resctrl_arch_get_cdp_enabled(r->rid))
peer_ctl = resctrl_arch_get_config(r, d, i,
- peer_type);
+ peer_type,
+ s->ctrl_type);
else
peer_ctl = 0;
ctrl_val = resctrl_arch_get_config(r, d, i,
- s->conf_type);
+ s->conf_type,
+ s->ctrl_type);
used_b |= ctrl_val | peer_ctl;
if (mode == RDT_MODE_SHAREABLE)
cfg->new_ctrl |= ctrl_val | peer_ctl;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 93b3e3b21d5d..2c0dc01d070e 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -377,7 +377,8 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
u32 closid, enum resctrl_conf_type t, u32 cfg_val);

u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type type);
+ u32 closid, enum resctrl_conf_type type,
+ enum resctrl_ctrl_type ctrl_type);
int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d);
void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d);
int resctrl_online_cpu(unsigned int cpu);
--
2.25.1


2024-01-17 14:16:27

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 10/14] arm_mpam: resctrl: Facilitate writing downstream priority value

This change provides a way to write downstream priority value (passed from
schemata file) to arch specific resource control code. The priority value
is stored in mpam_config structure, and eventually gets programmed into
MPAMCFG_PRI register.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Schemata write is based on Control type.
---
drivers/platform/mpam/mpam_devices.c | 4 ----
drivers/platform/mpam/mpam_resctrl.c | 26 ++++++++++++++++----------
2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c
index 589ff1ef2b6b..3ef9e5d70afc 100644
--- a/drivers/platform/mpam/mpam_devices.c
+++ b/drivers/platform/mpam/mpam_devices.c
@@ -2329,10 +2329,6 @@ int mpam_apply_config(struct mpam_component *comp, u16 partid,

lockdep_assert_cpus_held();

- if (!memcmp(&comp->cfg[partid], cfg, sizeof(*cfg)))
- return 0;
-
- comp->cfg[partid] = *cfg;
arg.comp = comp;
arg.partid = partid;

diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 7a797f9bcaed..42602bffba3f 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -925,7 +925,7 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
{
int err;
u32 partid;
- struct mpam_config cfg;
+ struct mpam_config *cfg;
struct mpam_props *cprops;
struct mpam_resctrl_res *res;
struct mpam_resctrl_dom *dom;
@@ -940,24 +940,30 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
cprops = &res->class->props;

partid = resctrl_get_config_index(closid, t);
+ cfg = &dom->comp->cfg[partid];
if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r))
return -EINVAL;

switch (r->rid) {
case RDT_RESOURCE_L2:
case RDT_RESOURCE_L3:
+ if (type == SCHEMA_DSPRI) {
+ cfg->dspri = cfg_val;
+ mpam_set_feature(mpam_feat_dspri_part, cfg);
+ } else {
/* TODO: Scaling is not yet supported */
- cfg.cpbm = cfg_val;
- mpam_set_feature(mpam_feat_cpor_part, &cfg);
+ cfg->cpbm = cfg_val;
+ mpam_set_feature(mpam_feat_cpor_part, cfg);
+ }
break;
case RDT_RESOURCE_MBA:
if (mba_class_use_mbw_part(cprops)) {
- cfg.mbw_pbm = percent_to_mbw_pbm(cfg_val, cprops);
- mpam_set_feature(mpam_feat_mbw_part, &cfg);
+ cfg->mbw_pbm = percent_to_mbw_pbm(cfg_val, cprops);
+ mpam_set_feature(mpam_feat_mbw_part, cfg);
break;
} else if (mpam_has_feature(mpam_feat_mbw_max, cprops)) {
- cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops);
- mpam_set_feature(mpam_feat_mbw_max, &cfg);
+ cfg->mbw_max = percent_to_mbw_max(cfg_val, cprops);
+ mpam_set_feature(mpam_feat_mbw_max, cfg);
break;
}
fallthrough;
@@ -971,15 +977,15 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
*/
if (mpam_resctrl_hide_cdp(r->rid)) {
partid = resctrl_get_config_index(closid, CDP_CODE);
- err = mpam_apply_config(dom->comp, partid, &cfg);
+ err = mpam_apply_config(dom->comp, partid, cfg);
if (err)
return err;

partid = resctrl_get_config_index(closid, CDP_DATA);
- return mpam_apply_config(dom->comp, partid, &cfg);
+ return mpam_apply_config(dom->comp, partid, cfg);

} else {
- return mpam_apply_config(dom->comp, partid, &cfg);
+ return mpam_apply_config(dom->comp, partid, cfg);
}
}

--
2.25.1


2024-01-17 14:16:34

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 08/14] fs/resctrl: Extend schemata write for priority partition control

Currently, Users can pass the configurations for CPBM, and MBA through
schemata file. For instance, CPBM can be passed using:

echo L3:0=ffff > schemata

This change allows, users to pass a new configuration for downstream
priority. For instance, dspri value of "0xa" can be passed as:

echo L3DSPRI:0=a > schemata

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* As suggested by Fenghua Yu, Parse for DSPRI is called
from parse_line().
* Decluttering code from rdtgroup_schemata_write().
---
fs/resctrl/ctrlmondata.c | 59 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 3 deletions(-)

diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index 78f9fb1c52fa..f1f57bbfa094 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -30,6 +30,55 @@ typedef int (ctrlval_parser_t)(struct rdt_parse_data *data,
struct resctrl_schema *s,
struct rdt_domain *d);

+static bool dspri_validate(char *buf, unsigned long *data, struct rdt_resource *r)
+{
+
+ unsigned long dspri_val;
+ bool success = true;
+ int ret;
+
+ ret = kstrtoul(buf, 16, &dspri_val);
+ if (ret) {
+ pr_info("Non-hex character in the mask %s\n", buf);
+ success = false;
+ goto out;
+ }
+
+ if (dspri_val > r->default_dspri_ctrl) {
+ pr_info("dspri value %ld out of range [%d-%d]\n", dspri_val,
+ 0, r->default_dspri_ctrl);
+ success = false;
+ goto out;
+ }
+
+ *data = dspri_val;
+
+out:
+ return success;
+}
+
+static int parse_dspri(struct rdt_parse_data *data, struct resctrl_schema *s,
+ struct rdt_domain *d)
+{
+ struct resctrl_staged_config *cfg;
+ struct rdt_resource *r = s->res;
+ unsigned long pri_val;
+
+ cfg = &d->staged_config[s->conf_type];
+ if (cfg->have_new_ctrl) {
+ pr_info("Duplicate domain %d\n", d->id);
+ return -EINVAL;
+ }
+
+ if (!dspri_validate(data->buf, &pri_val, r))
+ return -EINVAL;
+
+ cfg->new_ctrl = pri_val;
+ cfg->have_new_ctrl = true;
+
+ return 0;
+}
+
/*
* Check whether MBA bandwidth percentage value is correct. The value is
* checked against the minimum and max bandwidth values specified by the
@@ -201,10 +250,14 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
return 0;
}

-static ctrlval_parser_t *get_parser(struct rdt_resource *res)
+static ctrlval_parser_t *get_parser(struct resctrl_schema *s)
{
- if (res->fflags & RFTYPE_RES_CACHE)
+ struct rdt_resource *res = s->res;
+
+ if (res->fflags & RFTYPE_RES_CACHE && !s->ctrl_type)
return &parse_cbm;
+ else if (s->ctrl_type == SCHEMA_DSPRI)
+ return &parse_dspri;
else
return &parse_bw;
}
@@ -218,7 +271,7 @@ static ctrlval_parser_t *get_parser(struct rdt_resource *res)
static int parse_line(char *line, struct resctrl_schema *s,
struct rdtgroup *rdtgrp)
{
- ctrlval_parser_t *parse_ctrlval = get_parser(s->res);
+ ctrlval_parser_t *parse_ctrlval = get_parser(s);
enum resctrl_conf_type t = s->conf_type;
struct resctrl_staged_config *cfg;
struct rdt_resource *r = s->res;
--
2.25.1


2024-01-17 14:16:55

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 06/14] arm_mpam: resctrl: Retrieve priority values from arch code

Downstream priority values can be read from the "schemata" file, which is
fetched from mpam_config structure.

This change does the necessary modifications in arch specific code to
facilitate reading priority values.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Reworked, To configure DSPRI partition control use
control type instead of dspri_show/store flags.
---
drivers/platform/mpam/mpam_internal.h | 1 +
drivers/platform/mpam/mpam_resctrl.c | 23 ++++++++++++++++++-----
2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h
index 30e32389d394..45552ae6548b 100644
--- a/drivers/platform/mpam/mpam_internal.h
+++ b/drivers/platform/mpam/mpam_internal.h
@@ -160,6 +160,7 @@ struct mpam_config {
u32 cpbm;
u32 mbw_pbm;
u16 mbw_max;
+ u16 dspri;
};

struct mpam_component
diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 4c44d65e6047..0de09e9deee5 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -860,8 +860,12 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,

lockdep_assert_cpus_held();

- if (!mpam_is_enabled())
- return r->default_ctrl;
+ if (!mpam_is_enabled()) {
+ if (ctrl_type == SCHEMA_DSPRI)
+ return r->default_dspri_ctrl;
+ else
+ return r->default_ctrl;
+ }

res = container_of(r, struct mpam_resctrl_res, resctrl_res);
dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom);
@@ -873,7 +877,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
switch (r->rid) {
case RDT_RESOURCE_L2:
case RDT_RESOURCE_L3:
- configured_by = mpam_feat_cpor_part;
+ if (ctrl_type == SCHEMA_DSPRI)
+ configured_by = mpam_feat_dspri_part;
+ else
+ configured_by = mpam_feat_cpor_part;
break;
case RDT_RESOURCE_MBA:
if (mba_class_use_mbw_part(cprops)) {
@@ -889,13 +896,19 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
}

if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) ||
- !mpam_has_feature(configured_by, cfg))
- return r->default_ctrl;
+ !mpam_has_feature(configured_by, cfg)) {
+ if (ctrl_type == SCHEMA_DSPRI)
+ return r->default_dspri_ctrl;
+ else
+ return r->default_ctrl;
+ }

switch (configured_by) {
case mpam_feat_cpor_part:
/* TODO: Scaling is not yet supported */
return cfg->cpbm;
+ case mpam_feat_dspri_part:
+ return cfg->dspri;
case mpam_feat_mbw_part:
/* TODO: Scaling is not yet supported */
return mbw_pbm_to_percent(cfg->mbw_pbm, cprops);
--
2.25.1


2024-01-17 14:17:03

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 09/14] fs/resctrl: set configuration based on Control type

Now that, we have support for different control types, divided into
the BASIC and PRIORITY controls types. Schemata list is pertained to
the SCHEMAT_BASIC control type that is used to set up/configure
CAT (Cache Allocation Technology) and MBA (Memory Bandwidth Allocation)
capabilities, and SCHEMAT_DSPRI used to configure downstream priority
partitioning. Let's add boilerplate changes to set the control
configuration based on different control types.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change, it's new patch.
---
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 6 ++++--
drivers/platform/mpam/mpam_resctrl.c | 9 ++++++---
fs/resctrl/ctrlmondata.c | 3 ++-
fs/resctrl/monitor.c | 3 ++-
fs/resctrl/rdtgroup.c | 3 ++-
include/linux/resctrl.h | 6 ++++--
6 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index b34e86cfc111..4423d8979b5e 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -39,7 +39,8 @@ static bool apply_config(struct rdt_hw_domain *hw_dom,
}

int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type t, u32 cfg_val)
+ u32 closid, enum resctrl_conf_type t, u32 cfg_val,
+ enum resctrl_ctrl_type type)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
@@ -59,7 +60,8 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
return 0;
}

-int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
+int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid,
+ enum resctrl_ctrl_type type)
{
struct resctrl_staged_config *cfg;
struct rdt_hw_domain *hw_dom;
diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 0de09e9deee5..7a797f9bcaed 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -920,7 +920,8 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
}

int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type t, u32 cfg_val)
+ u32 closid, enum resctrl_conf_type t, u32 cfg_val,
+ enum resctrl_ctrl_type type)
{
int err;
u32 partid;
@@ -983,7 +984,8 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
}

/* TODO: this is IPI heavy */
-int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
+int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid,
+ enum resctrl_ctrl_type type)
{
int err = 0;
struct rdt_domain *d;
@@ -1000,7 +1002,8 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
continue;

err = resctrl_arch_update_one(r, d, closid, t,
- cfg->new_ctrl);
+ cfg->new_ctrl,
+ type);
if (err)
return err;
}
diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index f1f57bbfa094..005a91192847 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -405,7 +405,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
continue;

if (!strcmp(resname, s->name)) {
- ret = resctrl_arch_update_domains(r, rdtgrp->closid);
+ ret = resctrl_arch_update_domains(r, rdtgrp->closid,
+ s->ctrl_type);
if (ret)
goto out;
}
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 6c0804273753..5eccb38cb7d7 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -514,7 +514,8 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
return;
}

- resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, new_msr_val);
+ resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, new_msr_val,
+ SCHEMA_BASIC);

/*
* Delta values are updated dynamically package wise for each
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 92d9bee210eb..d71fac0ae4d4 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -3136,7 +3136,8 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
return ret;
}

- ret = resctrl_arch_update_domains(r, rdtgrp->closid);
+ ret = resctrl_arch_update_domains(r, rdtgrp->closid,
+ s->ctrl_type);
if (ret < 0) {
rdt_last_cmd_puts("Failed to initialize allocations\n");
return ret;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 2c0dc01d070e..f28d4ff737dc 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -334,7 +334,8 @@ int resctrl_rdtgroup_show(struct seq_file *seq, u32 closid, u32 rmid);
u32 resctrl_arch_get_num_closid(struct rdt_resource *r);

struct rdt_domain *resctrl_arch_find_domain(struct rdt_resource *r, int id);
-int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
+int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid,
+ enum resctrl_ctrl_type type);

/* For use by arch code that needs to remap resctrl's smaller CDP closid */
static inline u32 resctrl_get_config_index(u32 closid,
@@ -374,7 +375,8 @@ resctrl_get_domain_from_cpu(int cpu, struct rdt_resource *r)
* Must be called on one of the domain's CPUs.
*/
int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
- u32 closid, enum resctrl_conf_type t, u32 cfg_val);
+ u32 closid, enum resctrl_conf_type t, u32 cfg_val,
+ enum resctrl_ctrl_type ctrl_type);

u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
u32 closid, enum resctrl_conf_type type,
--
2.25.1


2024-01-17 14:17:28

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 11/14] arm_mpam: Fix Downstream and internal priority mask

MPAMF_PRI_IDR_NS[DSPRI_WD] determines the number of implemented bits in
the downstream priority field (MPAMCFG_PRI_NS). For instance, if the value
of DSPRI_WD is 4, then the maximum value for dspri is 0xf, and mask should
be GENMASK(3,0).

But with current implementation, it turned out to be GENMASK(4,0) .i.e.
0x1f instead of 0xf.

u16 dspri = GENMASK(rprops->dspri_wd, 0);

Let's fix it (for both downstream, and internal), by subtracting 1 from
DSPRI_WD, and INTPRI_WD value.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Include fix for INTPRI as well.
---
drivers/platform/mpam/mpam_devices.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c
index 3ef9e5d70afc..9953f2050d35 100644
--- a/drivers/platform/mpam/mpam_devices.c
+++ b/drivers/platform/mpam/mpam_devices.c
@@ -1099,8 +1099,8 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
struct mpam_msc *msc = ris->msc;
u16 bwa_fract = MPAMCFG_MBW_MAX_MAX;
struct mpam_props *rprops = &ris->props;
- u16 dspri = GENMASK(rprops->dspri_wd, 0);
- u16 intpri = GENMASK(rprops->intpri_wd, 0);
+ u16 dspri = GENMASK((rprops->dspri_wd - 1), 0);
+ u16 intpri = GENMASK((rprops->intpri_wd - 1), 0);

lockdep_assert_held(&msc->lock);

--
2.25.1


2024-01-17 14:17:28

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 07/14] fs/resctrl: Schemata write only for intended resource

At present, schemata write (for Cache Portion Bit Map or Memory Bandwidth
Allocation) goes through list of all the resources (supported by schemata),
and regardless of write for one resource, it attempts to write for all other
resources.

As an example, When the intended write is for only MBA resource, it
attempts (by calling resctrl_arch_update_domains) to write for CPBM
as well. Fix it, by doing schemata write based on input schemata supplied
from user.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change, it's new patch.
---
fs/resctrl/ctrlmondata.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index 451cbb7357fb..78f9fb1c52fa 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -351,9 +351,11 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
if (is_mba_sc(r))
continue;

- ret = resctrl_arch_update_domains(r, rdtgrp->closid);
- if (ret)
- goto out;
+ if (!strcmp(resname, s->name)) {
+ ret = resctrl_arch_update_domains(r, rdtgrp->closid);
+ if (ret)
+ goto out;
+ }
}

if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
--
2.25.1


2024-01-17 14:17:58

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

At the moment, configuring multiple resource instances (mapped to same
control) under a resource class is not supported. For instance, on MARVELL
SoC MPAMF_IDR_NS[RIS_MAX] (under LLC MSC) is 0x2, and there are three
different resource at index 0,1,2. These are enumerated in
TAD_CMN_MPAM_RIS_E:

0: MSC
1: LTG
2: DTG

LLC MSC resource at index 0 has the Priority partitioning features.
If MPAMCFG_PART_SEL_NS[RIS] is set to 0 (MSC), then MPAMF_IDR_NS[HAS_PRI_PART]
is set to 1, leaving HAS_CPOR_PART bit to 0. CPOR and PRI_PART are
mutually exclusive resources as far configuration is concerned.

With this change, multiple resource instances that maps to different
control, say LTG for CPOR, and MSC for PRI_PART is handled properly.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Trimmed down the commit message.
* Tried to handle the corner case as suggested by Jonathan
by calling the __resource_props_mismatch even when different
controls are enumerated at different RIS index.
---
drivers/platform/mpam/mpam_devices.c | 36 ++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c
index 388d57281fd8..df7ac2c8bcb3 100644
--- a/drivers/platform/mpam/mpam_devices.c
+++ b/drivers/platform/mpam/mpam_devices.c
@@ -1788,11 +1788,15 @@ __resource_props_mismatch(struct mpam_msc_ris *ris, struct mpam_class *class)

lockdep_assert_held(&mpam_list_lock); /* we modify class */

- /* Clear missing features */
- cprops->features &= rprops->features;
+ /* Clear missing features, we don't want to clear features,
+ * when different controls are implemented at different RIS
+ * index.
+ */
+ if (class->props.features == ris->props.features)
+ cprops->features &= rprops->features;

/* Clear incompatible features */
- if (cprops->cpbm_wd != rprops->cpbm_wd)
+ if (cprops->cpbm_wd != rprops->cpbm_wd && rprops->cpbm_wd)
mpam_clear_feature(mpam_feat_cpor_part, &cprops->features);
if (cprops->mbw_pbm_bits != rprops->mbw_pbm_bits)
mpam_clear_feature(mpam_feat_mbw_part, &cprops->features);
@@ -1802,14 +1806,14 @@ __resource_props_mismatch(struct mpam_msc_ris *ris, struct mpam_class *class)
cprops->bwa_wd = min(cprops->bwa_wd, rprops->bwa_wd);

/* For num properties, take the minimum */
- if (cprops->num_csu_mon != rprops->num_csu_mon)
+ if (cprops->num_csu_mon != rprops->num_csu_mon && rprops->num_csu_mon)
cprops->num_csu_mon = min(cprops->num_csu_mon, rprops->num_csu_mon);
if (cprops->num_mbwu_mon != rprops->num_mbwu_mon)
cprops->num_mbwu_mon = min(cprops->num_mbwu_mon, rprops->num_mbwu_mon);

if (cprops->intpri_wd != rprops->intpri_wd)
cprops->intpri_wd = min(cprops->intpri_wd, rprops->intpri_wd);
- if (cprops->dspri_wd != rprops->dspri_wd)
+ if (cprops->dspri_wd != rprops->dspri_wd && rprops->dspri_wd)
cprops->dspri_wd = min(cprops->dspri_wd, rprops->dspri_wd);

/* {int,ds}pri may not have differing 0-low behaviour */
@@ -1845,6 +1849,20 @@ static void mpam_enable_init_class_features(struct mpam_class *class)
class->props = ris->props;
}

+/* Club different resource properties under a class that resctrl uses,
+ * for instance, L3 cache that supports both CPOR, and DSPRI need to have
+ * knowledge of both cpbm_wd and dspri_wd. This is needed when two controls
+ * are enumerated under differnt RIS Index.
+ */
+static void mpam_enable_club_class_features(struct mpam_class *class,
+ struct mpam_msc_ris *ris)
+{
+ class->props.features |= ris->props.features;
+ class->props.cpbm_wd |= ris->props.cpbm_wd;
+ class->props.dspri_wd |= ris->props.dspri_wd;
+ class->props.num_csu_mon |= ris->props.num_csu_mon;
+}
+
/* Merge all the common resource features into class. */
static void mpam_enable_merge_features(void)
{
@@ -1860,6 +1878,14 @@ static void mpam_enable_merge_features(void)
list_for_each_entry(comp, &class->components, class_list) {
list_for_each_entry(ris, &comp->ris, comp_list) {
__resource_props_mismatch(ris, class);
+ /*
+ * There can be multiple resources under a class which is
+ * mapped to different controls, For instance L3 cache
+ * can have both CPOR and DSPRI implemented with different
+ * RIS.
+ */
+ if (class->props.features != ris->props.features)
+ mpam_enable_club_class_features(class, ris);

class->nrdy_usec = max(class->nrdy_usec,
ris->msc->nrdy_usec);
--
2.25.1


2024-01-17 14:18:11

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 12/14] arm_mpam: Program Downstream priority value

Now that Downstream priorities values can be passed from resource control
schemata file, let's program it into memory mapped Priority Partition
Configuration Register.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* Priority value is inverted based on DSPRI_0_IS_LOW value.
---
drivers/platform/mpam/mpam_devices.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c
index 9953f2050d35..388d57281fd8 100644
--- a/drivers/platform/mpam/mpam_devices.c
+++ b/drivers/platform/mpam/mpam_devices.c
@@ -1101,6 +1101,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
struct mpam_props *rprops = &ris->props;
u16 dspri = GENMASK((rprops->dspri_wd - 1), 0);
u16 intpri = GENMASK((rprops->intpri_wd - 1), 0);
+ u8 dspri_part_0_low, dspri_rprops, dspri_cfg;

lockdep_assert_held(&msc->lock);

@@ -1143,18 +1144,33 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
if (mpam_has_feature(mpam_feat_ccap_part, rprops))
mpam_write_partsel_reg(msc, CMAX, cmax);

- if (mpam_has_feature(mpam_feat_intpri_part, rprops) ||
- mpam_has_feature(mpam_feat_dspri_part, rprops)) {
+ if (mpam_has_feature(mpam_feat_intpri_part, rprops)) {
/* aces high? */
if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops))
intpri = 0;
- if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops))
- dspri = 0;

if (mpam_has_feature(mpam_feat_intpri_part, rprops))
pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, intpri);
- if (mpam_has_feature(mpam_feat_dspri_part, rprops))
- pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri);
+
+ mpam_write_partsel_reg(msc, PRI, pri_val);
+ }
+
+ dspri_rprops = mpam_has_feature(mpam_feat_dspri_part,
+ rprops);
+ dspri_part_0_low = mpam_has_feature(mpam_feat_dspri_part_0_low,
+ rprops);
+ if (dspri_rprops) {
+ dspri_cfg = mpam_has_feature(mpam_feat_dspri_part,
+ cfg);
+ if (dspri_cfg) {
+ pri_val |= (!dspri_part_0_low)
+ ? FIELD_PREP(MPAMCFG_PRI_DSPRI, cfg->dspri ^ dspri)
+ : FIELD_PREP(MPAMCFG_PRI_DSPRI, cfg->dspri & dspri);
+ } else {
+ pri_val |= (!dspri_part_0_low)
+ ? FIELD_PREP(MPAMCFG_PRI_DSPRI, 0)
+ : FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri);
+ }

mpam_write_partsel_reg(msc, PRI, pri_val);
}
--
2.25.1


2024-01-17 14:18:27

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 14/14] arm64/mpam: resctrl: export DSPRI value to info directory

Now that, we have support for priority partitioning, let's export
Downstream priority value (maximum value that user can supply) to
info directory. This value is visible under resource directory
to which this control (Downstream priority partition ) is applied.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change, it's new patch.
---
fs/resctrl/rdtgroup.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index d71fac0ae4d4..8c3df4bb8ee9 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -1118,6 +1118,16 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
return 0;
}

+static int rdt_max_dspri_show(struct kernfs_open_file *of,
+ struct seq_file *seq, void *v)
+{
+ struct resctrl_schema *s = of->kn->parent->priv;
+ struct rdt_resource *r = s->res;
+
+ seq_printf(seq, "%u\n", r->default_dspri_ctrl);
+ return 0;
+}
+
static int rdt_min_bw_show(struct kernfs_open_file *of,
struct seq_file *seq, void *v)
{
@@ -1713,6 +1723,13 @@ static struct rftype res_common_files[] = {
.seq_show = rdt_bit_usage_show,
.fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
},
+ {
+ .name = "max_dspri",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdt_max_dspri_show,
+ .fflags = RF_CTRL_INFO | RFTYPE_RES_CACHE,
+ },
{
.name = "min_bandwidth",
.mode = 0444,
@@ -2009,6 +2026,9 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)

/* loop over enabled controls, these are all alloc_capable */
list_for_each_entry(s, &resctrl_schema_all, list) {
+ if (s->ctrl_type == SCHEMA_DSPRI)
+ continue;
+
r = s->res;
fflags = r->fflags | RF_CTRL_INFO;
ret = rdtgroup_mkdir_info_resdir(s, s->name, fflags);
--
2.25.1


2024-01-17 14:18:41

by Amit Singh Tomar

[permalink] [raw]
Subject: [PATCH v1 02/14] arm_mpam: resctrl: Detect priority partitioning capability

ARM MPAM supports different control that can be applied to different
resources in the system, for instance priority partitioning control
where priority value is generated from one MSC, propagates over
interconnect to other MSC (known as downstream priority), or can be
applied within an MSC for internal operations.

This change lets the resctrl know the about MSC's priority partitioning
capability.

Signed-off-by: Amit Singh Tomar <[email protected]>
---
Changes since RFC:
* No change.
---
drivers/platform/mpam/mpam_resctrl.c | 14 ++++++++++++++
include/linux/resctrl.h | 4 ++++
2 files changed, 18 insertions(+)

diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 1dbfb6f6dd34..09618d9ceb1d 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -435,6 +435,16 @@ static bool cache_has_usable_cpor(struct mpam_class *class)
return (class->props.cpbm_wd <= RESCTRL_MAX_CBM);
}

+static bool cache_has_usable_priority_part(struct mpam_class *class)
+{
+ struct mpam_props *cprops = &class->props;
+
+ if (!mpam_has_feature(mpam_feat_dspri_part, cprops))
+ return false;
+
+ return (class->props.dspri_wd <= RESCTRL_MAX_DSPRI);
+}
+
static bool cache_has_usable_csu(struct mpam_class *class)
{
struct mpam_props *cprops;
@@ -691,6 +701,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
res->resctrl_res.rid == RDT_RESOURCE_L3) {
bool has_csu = cache_has_usable_csu(class);
bool has_mbwu = class_has_usable_mbwu(class);
+ bool has_ppart = cache_has_usable_priority_part(class);

/* TODO: Scaling is not yet supported */
r->cache.cbm_len = class->props.cpbm_wd;
@@ -718,6 +729,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
exposed_alloc_capable = true;
}

+ if (has_ppart)
+ r->priority_cap = true;
+
/*
* MBWU counters may be 'local' or 'total' depending on where
* they are in the topology. If The counter is on the L3, its
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 125c4b0c2ff7..d49aed80a05e 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -38,6 +38,8 @@ int proc_resctrl_show(struct seq_file *m,
*/
#define RESCTRL_MAX_CBM 32

+#define RESCTRL_MAX_DSPRI 63
+
/* The format for packing fields into the u64 'id' exposed to user-space */
#define RESCTRL_ID_CLOSID GENMASK_ULL(31, 0)
#define RESCTRL_ID_RMID GENMASK_ULL(63, 32)
@@ -195,6 +197,7 @@ struct resctrl_membw {
* @rid: The index of the resource
* @alloc_capable: Is allocation available on this machine
* @mon_capable: Is monitor feature available on this machine
+ * @priority_capable: Is priority partitioning feature available on this machine
* @num_rmid: Number of RMIDs available
* @cache_level: Which cache level defines scope of this resource
* @cache: Cache allocation related data
@@ -212,6 +215,7 @@ struct rdt_resource {
int rid;
bool alloc_capable;
bool mon_capable;
+ bool priority_cap;
int num_rmid;
int cache_level;
struct resctrl_cache cache;
--
2.25.1


2024-01-17 18:03:21

by Peter Newman

[permalink] [raw]
Subject: Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

Hi Amit,

On Wed, Jan 17, 2024 at 6:15 AM Amit Singh Tomar <[email protected]> wrote:

>
> +/* Club different resource properties under a class that resctrl uses,
> + * for instance, L3 cache that supports both CPOR, and DSPRI need to have
> + * knowledge of both cpbm_wd and dspri_wd. This is needed when two controls
> + * are enumerated under differnt RIS Index.
> + */
> +static void mpam_enable_club_class_features(struct mpam_class *class,
> + struct mpam_msc_ris *ris)

It looks like "club" is used as a synonym to "class" here to evade the
bigger issue that mpam_classes are not defined correctly as DSPRI
resources should not be in the same mpam_class as the L3 CPOR and CSU
features.

This hardware makes it clear that the definition of mpam_class as all
resources in a (level x {memory,cache}) needs to be revised.

-Peter

2024-01-17 19:21:42

by Peter Newman

[permalink] [raw]
Subject: Re: [PATCH v1 01/14] fs/resctrl: group the resource control types for schemata list

Hi Amit,

On Wed, Jan 17, 2024 at 6:14 AM Amit Singh Tomar <[email protected]> wrote:
> diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
> index 3ad308e9e226..125c4b0c2ff7 100644
> --- a/include/linux/resctrl.h
> +++ b/include/linux/resctrl.h
> @@ -249,6 +249,7 @@ struct resctrl_schema {
> struct list_head list;
> char name[8];
> enum resctrl_conf_type conf_type;
> + enum resctrl_ctrl_type ctrl_type;

I don't see a difference between a conf_type and a ctrl_type other
than conf_type being used for CDP and ctrl_type being used for DSPRI.

> struct rdt_resource *res;
> u32 num_closid;
> };
> diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h
> index 3897de9c4ecb..b9268ec3ba71 100644
> --- a/include/linux/resctrl_types.h
> +++ b/include/linux/resctrl_types.h
> @@ -57,6 +57,12 @@ enum resctrl_res_level {
> RDT_NUM_RESOURCES,
> };
>
> +enum resctrl_ctrl_type {
> + SCHEMA_BASIC = 0,
> + SCHEMA_DSPRI,
> + SCHEMA_NUM_CTRL_TYPE
> +};

Rather than enumerate every control type on all implementations, I
would prefer the approach taken in the MPAM resctrl_arch_rmid_read(),
where the MPAM driver would embed the resctrl_schema into a private
structure it defines and use container_of() in
resctrl_arch_update_domains(), which should take a resctrl_schema
parameter instead of an rdt_resource. Like resctrl_arch_rmid_read(),
the containing structure would direct the values to the appropriate
hardware.

I would like to see the MPAM driver owning the enumeration of this
feature and the common FS code just understanding the control as a
value that is passed back to the driver if its value is within a
stated acceptable range.

I think there's still a lot of work that needs to be done in the
overall design of resctrl to provide general support for controls and
monitors which do not exist in RDT and these patches provide useful
information to help us understand the issues.

Thanks!
-Peter

2024-01-17 23:59:24

by Reinette Chatre

[permalink] [raw]
Subject: Re: [PATCH v1 00/14] ARM: MPAM: add support for priority partitioning control

Hi Amit,

On 1/17/2024 6:13 AM, Amit Singh Tomar wrote:
> Also, these patches[3] are still based on older MPAM tree[3] from James, as facing some
> trouble setting up the resource control with latest snapshots.

Is this related to the issue you mention in [1]? James did respond
asking for the splat you are encountering. Could you please follow
up with that? If it is some other issue, could you please share the
details in response to the most recent MPAM submission [2]? If there
are known issues with this work it would be better to resolve before
merged.

Thank you very much.

Reinette

[1] https://lore.kernel.org/all/MW4PR18MB5084AC18E19386E5B83C0F0EC6A0A@MW4PR18MB5084.namprd18.prod.outlook.com/
[2] https://lore.kernel.org/lkml/[email protected]/

2024-01-19 13:04:30

by Amit Singh Tomar

[permalink] [raw]
Subject: RE: [EXT] Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

Hi Peter,

Thanks for having a look.

-----Original Message-----
From: Peter Newman <[email protected]>
Sent: Wednesday, January 17, 2024 11:33 PM
To: Amit Singh Tomar <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; George Cherian <[email protected]>; [email protected]; [email protected]; [email protected]
Subject: [EXT] Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

External Email

----------------------------------------------------------------------
Hi Amit,

On Wed, Jan 17, 2024 at 6:15 AM Amit Singh Tomar <[email protected]> wrote:

>
> +/* Club different resource properties under a class that resctrl
> +uses,
> + * for instance, L3 cache that supports both CPOR, and DSPRI need to
> +have
> + * knowledge of both cpbm_wd and dspri_wd. This is needed when two
> +controls
> + * are enumerated under differnt RIS Index.
> + */
> +static void mpam_enable_club_class_features(struct mpam_class *class,
> + struct mpam_msc_ris *ris)

It looks like "club" is used as a synonym to "class" here to evade the bigger issue that mpam_classes are not defined correctly as DSPRI resources should not be in the same mpam_class as the L3 CPOR and CSU features.

This hardware makes it clear that the definition of mpam_class as all resources in a (level x {memory,cache}) needs to be revised.

On Marvell platform, DSPRI control register (MPAMCFG_PRI_NS), and Identification Register (MPAMF_PRI_IDR_NS) are implemented within the LLC MPAM block (the address range contains control and identification registers for CPOR, and DSPRI), and therefore we treat DSPRI as one of the L3 resource. However, suppose we approach it as totally different standalone resource type (PRI) other than Cache storage resource type (CPOR, and CCAP), and define a new MPAM class type for it, there is no standard way to discover this new resource type (PRI) from ACPI tables.

I'm concerned about accessing DSPRI related registers, if we are going to tide it to new MPAM class (as we discover whole L3 MPAM block using firmware tables, and tide it's resources to L3 MPAM class).

Thanks
-Amit

2024-01-19 22:05:38

by Peter Newman

[permalink] [raw]
Subject: Re: [EXT] Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

[CC Tony Luck]

Hi Amit,

On Fri, Jan 19, 2024 at 5:01 AM Amit Singh Tomar <[email protected]> wrote:
>
> Hi Peter,
>
> Thanks for having a look.
>
> -----Original Message-----
> From: Peter Newman <[email protected]>
> Sent: Wednesday, January 17, 2024 11:33 PM
> To: Amit Singh Tomar <[email protected]>
> Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; George Cherian <[email protected]>; [email protected]; [email protected]; [email protected]
> Subject: [EXT] Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls
>
> External Email
>
> ----------------------------------------------------------------------
> Hi Amit,
>
> On Wed, Jan 17, 2024 at 6:15 AM Amit Singh Tomar <[email protected]> wrote:
>
> >
> > +/* Club different resource properties under a class that resctrl
> > +uses,
> > + * for instance, L3 cache that supports both CPOR, and DSPRI need to
> > +have
> > + * knowledge of both cpbm_wd and dspri_wd. This is needed when two
> > +controls
> > + * are enumerated under differnt RIS Index.
> > + */
> > +static void mpam_enable_club_class_features(struct mpam_class *class,
> > + struct mpam_msc_ris *ris)
>
> It looks like "club" is used as a synonym to "class" here to evade the bigger issue that mpam_classes are not defined correctly as DSPRI resources should not be in the same mpam_class as the L3 CPOR and CSU features.
>
> This hardware makes it clear that the definition of mpam_class as all resources in a (level x {memory,cache}) needs to be revised.
>
> On Marvell platform, DSPRI control register (MPAMCFG_PRI_NS), and Identification Register (MPAMF_PRI_IDR_NS) are implemented within the LLC MPAM block (the address range contains control and identification registers for CPOR, and DSPRI), and therefore we treat DSPRI as one of the L3 resource. However, suppose we approach it as totally different standalone resource type (PRI) other than Cache storage resource type (CPOR, and CCAP), and define a new MPAM class type for it, there is no standard way to discover this new resource type (PRI) from ACPI tables.
>
> I'm concerned about accessing DSPRI related registers, if we are going to tide it to new MPAM class (as we discover whole L3 MPAM block using firmware tables, and tide it's resources to L3 MPAM class).

This is becoming more of a discussion of MPAM (and resctrl) in
general, so I hope James can participate. Also I should point out that
when discussing MPAM, "resource" refers to a non-RIS MSC or a single
RIS-index on a RIS-enabled MSC, while the "mpam_class" structure in
the code is the counterpart to what RDT (and resctrl) call a resource.

From my reading of the code, the consequence of (RIS) resources being
in the same mpam_class is that they can be programmed uniformly
through a single schema line in the schemata file, so
__resource_props_mismatch() goes to work on eliminating any resources
(and extra control granularity) which are not programmed exactly the
same way. This function seems more geared toward big.LITTLE systems
where the cache controls on one cluster are dissimilar from those on
the peer cluster and would need to be normalized (James, can you
confirm?). But in this situation, it seems like a better idea to
present a separate schema for one cluster's controls from the others.
For example, "L2P" and "L2E", with non-overlapping domains.

In the case of an MSC implementing RIS, the controls are independent
by definition, so I can't see why the work done in
__resource_props_mismatch() would be applicable.

-Peter

2024-05-08 14:04:24

by Amit Singh Tomar

[permalink] [raw]
Subject: Re: [PATCH v1 13/14] arm_mpam: Handle resource instances mapped to different controls

Hi Peter,

>>
>> It looks like "club" is used as a synonym to "class" here to evade the bigger issue that mpam_classes are not defined correctly as DSPRI resources should not be in the same mpam_class as the L3 CPOR and CSU features.
>>
>> This hardware makes it clear that the definition of mpam_class as all resources in a (level x {memory,cache}) needs to be revised.
>>
>> On Marvell platform, DSPRI control register (MPAMCFG_PRI_NS), and Identification Register (MPAMF_PRI_IDR_NS) are implemented within the LLC MPAM block (the address range contains control and identification registers for CPOR, and DSPRI), and therefore we treat DSPRI as one of the L3 resource. However, suppose we approach it as totally different standalone resource type (PRI) other than Cache storage resource type (CPOR, and CCAP), and define a new MPAM class type for it, there is no standard way to discover this new resource type (PRI) from ACPI tables.
>>
>> I'm concerned about accessing DSPRI related registers, if we are going to tide it to new MPAM class (as we discover whole L3 MPAM block using firmware tables, and tide it's resources to L3 MPAM class).
>
> This is becoming more of a discussion of MPAM (and resctrl) in
> general, so I hope James can participate. Also I should point out that
> when discussing MPAM, "resource" refers to a non-RIS MSC or a single
> RIS-index on a RIS-enabled MSC, while the "mpam_class" structure in
> the code is the counterpart to what RDT (and resctrl) call a resource.
>
> From my reading of the code, the consequence of (RIS) resources being
> in the same mpam_class is that they can be programmed uniformly
> through a single schema line in the schemata file, so
> __resource_props_mismatch() goes to work on eliminating any resources
> (and extra control granularity) which are not programmed exactly the
> same way. This function seems more geared toward big.LITTLE systems
> where the cache controls on one cluster are dissimilar from those on
> the peer cluster and would need to be normalized (James, can you
> confirm?). But in this situation, it seems like a better idea to
> present a separate schema for one cluster's controls from the others.
> For example, "L2P" and "L2E", with non-overlapping domains.
>
> In the case of an MSC implementing RIS, the controls are independent
> by definition,
This greatly relies on the implementation.

For an MSC, identical control may be situated at two separate indexes,
each with different attributes. For instance, let's take an example
of MARVELL implementation, There are three different resources at index
0,1,2. These are enumerated in TAD_CMN_MPAM_RIS_E:

0: MSC
1: LTG
2: DTG

LLC MSC, resource at index 1, and 2 possesses cache portion partitioning
feature, i.e., If MPAMCFG_PART_SEL_NS[RIS] is set to 1 (LTG) or to 2
(DTG), then MPAMF_IDR_NS[HAS_CPOR_PART] is set to 1. LTG resource has 16
portion bitmap, and DTG has 18 portion bitmap (mapped to same CPOR
control), and only one can be configured.

so I can't see why the work done in
> __resource_props_mismatch() would be applicable.
>
IMHO, __resource_props_mismatch would be needed for such cases.

Thanks
-Amit