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 <[email protected]>
---
 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

Reply via email to