[PATCH 5/8] x86/intel_rct/mba: Add MBA structures and initialize MBA

From: Vikas Shivappa
Date: Tue Jan 10 2017 - 14:35:28 EST


The MBA feature details are obtained via executing CPUID with EAX=10H
ECX= 3 and initialize the MBA structures from this info.

Add a new rdt resource 'MBA' to the global list of RDT resources. Add
extensions to the generic RDT resource structure to store the MBA
specific feature details. Parameters specific to delay values and delay
granularity are added to the RDT resource and domain structure.

Signed-off-by: Vikas Shivappa <vikas.shivappa@xxxxxxxxxxxxxxx>
---
arch/x86/include/asm/intel_rdt.h | 10 +++++
arch/x86/kernel/cpu/intel_rdt.c | 70 ++++++++++++++++++++++++++------
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +-
3 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h
index 35e76b4..49ae832 100644
--- a/arch/x86/include/asm/intel_rdt.h
+++ b/arch/x86/include/asm/intel_rdt.h
@@ -11,6 +11,9 @@
#define IA32_L3_QOS_CFG 0xc81
#define IA32_L3_CBM_BASE 0xc90
#define IA32_L2_CBM_BASE 0xd10
+#define IA32_MBE_THRTL_BASE 0xd50
+#define MAX_MBA_THRTL 100u
+#define MBE_IS_LINEAR 0x4

#define L3_QOS_CDP_ENABLE 0x01ULL

@@ -74,6 +77,9 @@ struct rftype {
* @no_ctrl: Specifies max cache cbm or min mem b/w delay.
* @min_cbm_bits: Minimum number of consecutive bits to be set
* in a cache bit mask
+ * @max_delay: Max throttle delay
+ * @delay_gran: Throttle delay granularity
+ * @delay_linear: true if delay is in linear scale
* @domains: All domains for this resource
* @num_domains: Number of domains active
* @msr_base: Base MSR address for CBMs
@@ -92,6 +98,9 @@ struct rdt_resource {
int cbm_len;
int min_cbm_bits;
u32 no_ctrl;
+ u32 max_delay;
+ u32 delay_gran;
+ u32 delay_linear;
struct list_head domains;
int num_domains;
int msr_base;
@@ -141,6 +150,7 @@ enum {
RDT_RESOURCE_L3DATA,
RDT_RESOURCE_L3CODE,
RDT_RESOURCE_L2,
+ RDT_RESOURCE_MBA,

/* Must be the last */
RDT_NUM_RESOURCES,
diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c
index fced83c..6736e1d 100644
--- a/arch/x86/kernel/cpu/intel_rdt.c
+++ b/arch/x86/kernel/cpu/intel_rdt.c
@@ -76,6 +76,14 @@ struct rdt_resource rdt_resources_all[] = {
.cbm_idx_multi = 1,
.cbm_idx_offset = 0
},
+ {
+ .name = "MB",
+ .domains = domain_init(RDT_RESOURCE_MBA),
+ .msr_base = IA32_MBE_THRTL_BASE,
+ .cache_level = 3,
+ .cbm_idx_multi = 1,
+ .cbm_idx_offset = 0
+ },
};

static int cbm_idx(struct rdt_resource *r, int closid)
@@ -130,6 +138,26 @@ static inline bool cache_alloc_hsw_probe(void)
return false;
}

+static void rdt_get_mem_config(struct rdt_resource *r)
+{
+ union cpuid_0x10_3_eax eax;
+ union cpuid_0x10_x_edx edx;
+ u32 ebx, ecx;
+
+ cpuid_count(0x00000010, 3, &eax.full, &ebx, &ecx, &edx.full);
+ r->num_closid = edx.split.cos_max + 1;
+ r->max_delay = eax.split.max_delay + 1;
+ r->no_ctrl = 0;
+ if (ecx & MBE_IS_LINEAR)
+ r->delay_linear = true;
+
+ if (r->delay_linear)
+ r->delay_gran = MAX_MBA_THRTL - r->max_delay;
+
+ r->capable = true;
+ r->enabled = true;
+}
+
static void rdt_get_cache_config(int idx, struct rdt_resource *r)
{
union cpuid_0x10_1_eax eax;
@@ -185,6 +213,7 @@ static inline bool get_rdt_resources(void)
}

if (boot_cpu_has(X86_FEATURE_MBA)) {
+ rdt_get_mem_config(&rdt_resources_all[RDT_RESOURCE_MBA]);
ret = true;
}

@@ -262,6 +291,32 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
return NULL;
}

+static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
+{
+ int i;
+
+ d->ctrl_val = kmalloc_array(r->num_closid,
+ sizeof(*d->ctrl_val), GFP_KERNEL);
+ if (!d->ctrl_val) {
+ kfree(d);
+ return -ENOMEM;
+ }
+
+ /*
+ * Initialize the Control MSRs to having no control.
+ * For Cache Allocation: Set all bits in cbm
+ * For Memory Allocation: Set throttle_by to zero.
+ */
+ for (i = 0; i < r->num_closid; i++) {
+ int idx = cbm_idx(r, i);
+
+ d->ctrl_val[i] = r->no_ctrl;
+ wrmsrl(r->msr_base + idx, d->ctrl_val[i]);
+ }
+
+ return 0;
+}
+
/*
* domain_add_cpu - Add a cpu to a resource's domain list.
*
@@ -277,7 +332,7 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
*/
static void domain_add_cpu(int cpu, struct rdt_resource *r)
{
- int i, id = get_cache_id(cpu, r->cache_level);
+ int id = get_cache_id(cpu, r->cache_level), ret;
struct list_head *add_pos = NULL;
struct rdt_domain *d;

@@ -298,18 +353,9 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)

d->id = id;

- d->ctrl_val = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL);
- if (!d->ctrl_val) {
- kfree(d);
+ ret = domain_setup_ctrlval(r, d);
+ if (ret)
return;
- }
-
- for (i = 0; i < r->num_closid; i++) {
- int idx = cbm_idx(r, i);
-
- d->ctrl_val[i] = r->no_ctrl;
- wrmsrl(r->msr_base + idx, d->ctrl_val[i]);
- }

cpumask_set_cpu(cpu, &d->cpu_mask);
list_add_tail(&d->list, add_pos);
diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
index edc6195..53f1917 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -503,7 +503,7 @@ static int rdt_no_ctrl_show(struct kernfs_open_file *of,
{
struct rdt_resource *r = of->kn->parent->priv;

- seq_printf(seq, "%x\n", r->no_ctrl);
+ seq_printf(seq, "0x%x\n", r->no_ctrl);

return 0;
}
--
1.9.1