[PATCH 7/8] x86/intel_rdt: Prep to add schemata file for MBA

From: Vikas Shivappa
Date: Fri Apr 07 2017 - 20:35:02 EST


User updates RDT resource controls by updating the schemata file. OS
then parses these updates and updates the corresponding QOS_MSRs.
However the parsing and MSR update functions are specific to cache
resource type and do not support memory resource type.

Define resource specific function pointers to dynamically choose such
functions in order to prepare to add MBA support.

Signed-off-by: Vikas Shivappa <vikas.shivappa@xxxxxxxxxxxxxxx>
---
arch/x86/include/asm/intel_rdt.h | 7 +++++++
arch/x86/kernel/cpu/intel_rdt.c | 16 ++++++++++------
arch/x86/kernel/cpu/intel_rdt_schemata.c | 23 +++++++++++++----------
3 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h
index 32de56a..63fa034 100644
--- a/arch/x86/include/asm/intel_rdt.h
+++ b/arch/x86/include/asm/intel_rdt.h
@@ -107,6 +107,9 @@ struct msr_param {
* @num_closid: Number of CLOSIDs available
* @default_ctrl: Specifies default cache cbm or mem b/w percent.
* @data_width: Character width of data when displaying
+ * @format_str: Per resource format string to show domain value
+ * @parse_ctrlval: Per resource function pointer to parse
+ * the ctrl values
* @msr_update: Function pointer to update QOS MSRs
* @info_files: resctrl info files for the resource
* @nr_info_files: Number of info files
@@ -136,6 +139,9 @@ struct rdt_resource {
int num_closid;
u32 default_ctrl;
int data_width;
+ const char *format_str;
+ int (*parse_ctrlval) (char *buf, struct rdt_resource *r,
+ struct rdt_domain *d);
void (*msr_update) (struct rdt_domain *d, struct msr_param *m,
struct rdt_resource *r);
struct rftype *info_files;
@@ -162,6 +168,7 @@ struct rdt_resource {

void rdt_get_cache_infofile(struct rdt_resource *r);
void rdt_get_mba_infofile(struct rdt_resource *r);
+int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d);

extern struct mutex rdtgroup_mutex;

diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c
index a4f56d9..695870a 100644
--- a/arch/x86/kernel/cpu/intel_rdt.c
+++ b/arch/x86/kernel/cpu/intel_rdt.c
@@ -58,7 +58,9 @@ struct rdt_resource rdt_resources_all[] = {
.name = "L3",
.domains = domain_init(RDT_RESOURCE_L3),
.msr_base = IA32_L3_CBM_BASE,
+ .parse_ctrlval = parse_cbm,
.msr_update = cat_wrmsr,
+ .format_str = "%d=%0*x",
.min_cbm_bits = 1,
.cache_level = 3,
.cbm_idx_multi = 1,
@@ -68,7 +70,9 @@ struct rdt_resource rdt_resources_all[] = {
.name = "L3DATA",
.domains = domain_init(RDT_RESOURCE_L3DATA),
.msr_base = IA32_L3_CBM_BASE,
+ .parse_ctrlval = parse_cbm,
.msr_update = cat_wrmsr,
+ .format_str = "%d=%0*x",
.min_cbm_bits = 1,
.cache_level = 3,
.cbm_idx_multi = 2,
@@ -78,7 +82,9 @@ struct rdt_resource rdt_resources_all[] = {
.name = "L3CODE",
.domains = domain_init(RDT_RESOURCE_L3CODE),
.msr_base = IA32_L3_CBM_BASE,
+ .parse_ctrlval = parse_cbm,
.msr_update = cat_wrmsr,
+ .format_str = "%d=%0*x",
.min_cbm_bits = 1,
.cache_level = 3,
.cbm_idx_multi = 2,
@@ -88,7 +94,9 @@ struct rdt_resource rdt_resources_all[] = {
.name = "L2",
.domains = domain_init(RDT_RESOURCE_L2),
.msr_base = IA32_L2_CBM_BASE,
+ .parse_ctrlval = parse_cbm,
.msr_update = cat_wrmsr,
+ .format_str = "%d=%0*x",
.min_cbm_bits = 1,
.cache_level = 2,
.cbm_idx_multi = 1,
@@ -349,7 +357,7 @@ void rdt_ctrl_update(void *arg)
{
struct msr_param *m = (struct msr_param *)arg;
struct rdt_resource *r = m->res;
- int i, cpu = smp_processor_id();
+ int cpu = smp_processor_id();
struct rdt_domain *d;

list_for_each_entry(d, &r->domains, list) {
@@ -363,11 +371,7 @@ void rdt_ctrl_update(void *arg)
return;

found:
- for (i = m->low; i < m->high; i++) {
- int idx = cbm_idx(r, i);
-
- wrmsrl(r->msr_base + idx, d->ctrl_val[i]);
- }
+ r->msr_update(d, m, r);
}

/*
diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c
index 7695179..03f9a70 100644
--- a/arch/x86/kernel/cpu/intel_rdt_schemata.c
+++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c
@@ -34,9 +34,14 @@
* are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.).
* Additionally Haswell requires at least two bits set.
*/
-static bool cbm_validate(unsigned long var, struct rdt_resource *r)
+static bool cbm_validate(char *buf, unsigned long *data, struct rdt_resource *r)
{
- unsigned long first_bit, zero_bit;
+ unsigned long first_bit, zero_bit, var;
+ int ret;
+
+ ret = kstrtoul(buf, 16, &var);
+ if (ret)
+ return false;

if (var == 0 || var > r->default_ctrl)
return false;
@@ -49,6 +54,8 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r)

if ((zero_bit - first_bit) < r->min_cbm_bits)
return false;
+
+ *data = var;
return true;
}

@@ -56,18 +63,14 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r)
* Read one cache bit mask (hex). Check that it is valid for the current
* resource type.
*/
-static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d)
+int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d)
{
unsigned long data;
- int ret;

if (d->have_new_ctrl)
return -EINVAL;

- ret = kstrtoul(buf, 16, &data);
- if (ret)
- return ret;
- if (!cbm_validate(data, r))
+ if(!cbm_validate(buf, &data, r))
return -EINVAL;
d->new_ctrl = data;
d->have_new_ctrl = true;
@@ -96,7 +99,7 @@ static int parse_line(char *line, struct rdt_resource *r)
return -EINVAL;
list_for_each_entry(d, &r->domains, list) {
if (d->id == dom_id) {
- if (parse_cbm(dom, r, d))
+ if (r->parse_ctrlval(dom, r, d))
return -EINVAL;
goto next;
}
@@ -207,7 +210,7 @@ static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid)
list_for_each_entry(dom, &r->domains, list) {
if (sep)
seq_puts(s, ";");
- seq_printf(s, "%d=%0*x", dom->id, max_data_width,
+ seq_printf(s, r->format_str, dom->id, max_data_width,
dom->ctrl_val[closid]);
sep = true;
}
--
1.9.1