Linus,

please pull the latest x86-cache-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-cache-for-linus

A set of patches which add support for L2 cache partitioning to the Intel
RDT facility.

Thanks,

        tglx

------------------>
Fenghua Yu (6):
      x86/intel_rdt: Update documentation
      x86/intel_rdt: Add L2CDP support in documentation
      x86/intel_rdt: Enumerate L2 Code and Data Prioritization (CDP) feature
      x86/intel_rdt: Add two new resources for L2 Code and Data Prioritization 
(CDP)
      x86/intel_rdt: Enable L2 CDP in MSR IA32_L2_QOS_CFG
      x86/intel_rdt: Add command line parameter to control L2_CDP


 Documentation/admin-guide/kernel-parameters.txt |   3 +-
 Documentation/x86/intel_rdt_ui.txt              |  13 ++-
 arch/x86/include/asm/cpufeatures.h              |   1 +
 arch/x86/kernel/cpu/intel_rdt.c                 |  68 ++++++++++++--
 arch/x86/kernel/cpu/intel_rdt.h                 |   5 +
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c        | 117 ++++++++++++++++++------
 arch/x86/kernel/cpu/scattered.c                 |   1 +
 7 files changed, 169 insertions(+), 39 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index 46b26bfee27b..fde058ca8419 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3682,7 +3682,8 @@
 
        rdt=            [HW,X86,RDT]
                        Turn on/off individual RDT features. List is:
-                       cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, mba.
+                       cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
+                       mba.
                        E.g. to turn on cmt and turn off mba use:
                                rdt=cmt,!mba
 
diff --git a/Documentation/x86/intel_rdt_ui.txt 
b/Documentation/x86/intel_rdt_ui.txt
index 6851854cf69d..756fd76b78a6 100644
--- a/Documentation/x86/intel_rdt_ui.txt
+++ b/Documentation/x86/intel_rdt_ui.txt
@@ -7,15 +7,24 @@ Tony Luck <tony.l...@intel.com>
 Vikas Shivappa <vikas.shiva...@intel.com>
 
 This feature is enabled by the CONFIG_INTEL_RDT Kconfig and the
-X86 /proc/cpuinfo flag bits "rdt", "cqm", "cat_l3" and "cdp_l3".
+X86 /proc/cpuinfo flag bits:
+RDT (Resource Director Technology) Allocation - "rdt_a"
+CAT (Cache Allocation Technology) - "cat_l3", "cat_l2"
+CDP (Code and Data Prioritization ) - "cdp_l3", "cdp_l2"
+CQM (Cache QoS Monitoring) - "cqm_llc", "cqm_occup_llc"
+MBM (Memory Bandwidth Monitoring) - "cqm_mbm_total", "cqm_mbm_local"
+MBA (Memory Bandwidth Allocation) - "mba"
 
 To use the feature mount the file system:
 
- # mount -t resctrl resctrl [-o cdp] /sys/fs/resctrl
+ # mount -t resctrl resctrl [-o cdp[,cdpl2]] /sys/fs/resctrl
 
 mount options are:
 
 "cdp": Enable code/data prioritization in L3 cache allocations.
+"cdpl2": Enable code/data prioritization in L2 cache allocations.
+
+L2 and L3 CDP are controlled seperately.
 
 RDT features are orthogonal. A particular system may support only
 monitoring, only control, or both monitoring and control.
diff --git a/arch/x86/include/asm/cpufeatures.h 
b/arch/x86/include/asm/cpufeatures.h
index 25b9375c1484..67bbfaa1448b 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -206,6 +206,7 @@
 #define X86_FEATURE_RETPOLINE          ( 7*32+12) /* Generic Retpoline 
mitigation for Spectre variant 2 */
 #define X86_FEATURE_RETPOLINE_AMD      ( 7*32+13) /* AMD Retpoline mitigation 
for Spectre variant 2 */
 #define X86_FEATURE_INTEL_PPIN         ( 7*32+14) /* Intel Processor Inventory 
Number */
+#define X86_FEATURE_CDP_L2             ( 7*32+15) /* Code and Data 
Prioritization L2 */
 #define X86_FEATURE_AVX512_4VNNIW      ( 7*32+16) /* AVX-512 Neural Network 
Instructions */
 #define X86_FEATURE_AVX512_4FMAPS      ( 7*32+17) /* AVX-512 Multiply 
Accumulation Single precision */
 
diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c
index 99442370de40..410629f10ad3 100644
--- a/arch/x86/kernel/cpu/intel_rdt.c
+++ b/arch/x86/kernel/cpu/intel_rdt.c
@@ -135,6 +135,40 @@ struct rdt_resource rdt_resources_all[] = {
                .format_str             = "%d=%0*x",
                .fflags                 = RFTYPE_RES_CACHE,
        },
+       [RDT_RESOURCE_L2DATA] =
+       {
+               .rid                    = RDT_RESOURCE_L2DATA,
+               .name                   = "L2DATA",
+               .domains                = domain_init(RDT_RESOURCE_L2DATA),
+               .msr_base               = IA32_L2_CBM_BASE,
+               .msr_update             = cat_wrmsr,
+               .cache_level            = 2,
+               .cache = {
+                       .min_cbm_bits   = 1,
+                       .cbm_idx_mult   = 2,
+                       .cbm_idx_offset = 0,
+               },
+               .parse_ctrlval          = parse_cbm,
+               .format_str             = "%d=%0*x",
+               .fflags                 = RFTYPE_RES_CACHE,
+       },
+       [RDT_RESOURCE_L2CODE] =
+       {
+               .rid                    = RDT_RESOURCE_L2CODE,
+               .name                   = "L2CODE",
+               .domains                = domain_init(RDT_RESOURCE_L2CODE),
+               .msr_base               = IA32_L2_CBM_BASE,
+               .msr_update             = cat_wrmsr,
+               .cache_level            = 2,
+               .cache = {
+                       .min_cbm_bits   = 1,
+                       .cbm_idx_mult   = 2,
+                       .cbm_idx_offset = 1,
+               },
+               .parse_ctrlval          = parse_cbm,
+               .format_str             = "%d=%0*x",
+               .fflags                 = RFTYPE_RES_CACHE,
+       },
        [RDT_RESOURCE_MBA] =
        {
                .rid                    = RDT_RESOURCE_MBA,
@@ -259,15 +293,15 @@ static void rdt_get_cache_alloc_cfg(int idx, struct 
rdt_resource *r)
        r->alloc_enabled = true;
 }
 
-static void rdt_get_cdp_l3_config(int type)
+static void rdt_get_cdp_config(int level, int type)
 {
-       struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
+       struct rdt_resource *r_l = &rdt_resources_all[level];
        struct rdt_resource *r = &rdt_resources_all[type];
 
-       r->num_closid = r_l3->num_closid / 2;
-       r->cache.cbm_len = r_l3->cache.cbm_len;
-       r->default_ctrl = r_l3->default_ctrl;
-       r->cache.shareable_bits = r_l3->cache.shareable_bits;
+       r->num_closid = r_l->num_closid / 2;
+       r->cache.cbm_len = r_l->cache.cbm_len;
+       r->default_ctrl = r_l->default_ctrl;
+       r->cache.shareable_bits = r_l->cache.shareable_bits;
        r->data_width = (r->cache.cbm_len + 3) / 4;
        r->alloc_capable = true;
        /*
@@ -277,6 +311,18 @@ static void rdt_get_cdp_l3_config(int type)
        r->alloc_enabled = false;
 }
 
+static void rdt_get_cdp_l3_config(void)
+{
+       rdt_get_cdp_config(RDT_RESOURCE_L3, RDT_RESOURCE_L3DATA);
+       rdt_get_cdp_config(RDT_RESOURCE_L3, RDT_RESOURCE_L3CODE);
+}
+
+static void rdt_get_cdp_l2_config(void)
+{
+       rdt_get_cdp_config(RDT_RESOURCE_L2, RDT_RESOURCE_L2DATA);
+       rdt_get_cdp_config(RDT_RESOURCE_L2, RDT_RESOURCE_L2CODE);
+}
+
 static int get_cache_id(int cpu, int level)
 {
        struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
@@ -645,6 +691,7 @@ enum {
        RDT_FLAG_L3_CAT,
        RDT_FLAG_L3_CDP,
        RDT_FLAG_L2_CAT,
+       RDT_FLAG_L2_CDP,
        RDT_FLAG_MBA,
 };
 
@@ -667,6 +714,7 @@ static struct rdt_options rdt_options[]  __initdata = {
        RDT_OPT(RDT_FLAG_L3_CAT,    "l3cat",    X86_FEATURE_CAT_L3),
        RDT_OPT(RDT_FLAG_L3_CDP,    "l3cdp",    X86_FEATURE_CDP_L3),
        RDT_OPT(RDT_FLAG_L2_CAT,    "l2cat",    X86_FEATURE_CAT_L2),
+       RDT_OPT(RDT_FLAG_L2_CDP,    "l2cdp",    X86_FEATURE_CDP_L2),
        RDT_OPT(RDT_FLAG_MBA,       "mba",      X86_FEATURE_MBA),
 };
 #define NUM_RDT_OPTIONS ARRAY_SIZE(rdt_options)
@@ -729,15 +777,15 @@ static __init bool get_rdt_alloc_resources(void)
 
        if (rdt_cpu_has(X86_FEATURE_CAT_L3)) {
                rdt_get_cache_alloc_cfg(1, &rdt_resources_all[RDT_RESOURCE_L3]);
-               if (rdt_cpu_has(X86_FEATURE_CDP_L3)) {
-                       rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA);
-                       rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE);
-               }
+               if (rdt_cpu_has(X86_FEATURE_CDP_L3))
+                       rdt_get_cdp_l3_config();
                ret = true;
        }
        if (rdt_cpu_has(X86_FEATURE_CAT_L2)) {
                /* CPUID 0x10.2 fields are same format at 0x10.1 */
                rdt_get_cache_alloc_cfg(2, &rdt_resources_all[RDT_RESOURCE_L2]);
+               if (rdt_cpu_has(X86_FEATURE_CDP_L2))
+                       rdt_get_cdp_l2_config();
                ret = true;
        }
 
diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h
index 3397244984f5..3fd7a70ee04a 100644
--- a/arch/x86/kernel/cpu/intel_rdt.h
+++ b/arch/x86/kernel/cpu/intel_rdt.h
@@ -7,12 +7,15 @@
 #include <linux/jump_label.h>
 
 #define IA32_L3_QOS_CFG                0xc81
+#define IA32_L2_QOS_CFG                0xc82
 #define IA32_L3_CBM_BASE       0xc90
 #define IA32_L2_CBM_BASE       0xd10
 #define IA32_MBA_THRTL_BASE    0xd50
 
 #define L3_QOS_CDP_ENABLE      0x01ULL
 
+#define L2_QOS_CDP_ENABLE      0x01ULL
+
 /*
  * Event IDs are used to program IA32_QM_EVTSEL before reading event
  * counter from IA32_QM_CTR
@@ -357,6 +360,8 @@ enum {
        RDT_RESOURCE_L3DATA,
        RDT_RESOURCE_L3CODE,
        RDT_RESOURCE_L2,
+       RDT_RESOURCE_L2DATA,
+       RDT_RESOURCE_L2CODE,
        RDT_RESOURCE_MBA,
 
        /* Must be the last */
diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c 
b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
index 64c5ff97ee0d..bdab7d2f51af 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -990,6 +990,7 @@ mongroup_create_dir(struct kernfs_node *parent_kn, struct 
rdtgroup *prgrp,
        kernfs_remove(kn);
        return ret;
 }
+
 static void l3_qos_cfg_update(void *arg)
 {
        bool *enable = arg;
@@ -997,8 +998,17 @@ static void l3_qos_cfg_update(void *arg)
        wrmsrl(IA32_L3_QOS_CFG, *enable ? L3_QOS_CDP_ENABLE : 0ULL);
 }
 
-static int set_l3_qos_cfg(struct rdt_resource *r, bool enable)
+static void l2_qos_cfg_update(void *arg)
 {
+       bool *enable = arg;
+
+       wrmsrl(IA32_L2_QOS_CFG, *enable ? L2_QOS_CDP_ENABLE : 0ULL);
+}
+
+static int set_cache_qos_cfg(int level, bool enable)
+{
+       void (*update)(void *arg);
+       struct rdt_resource *r_l;
        cpumask_var_t cpu_mask;
        struct rdt_domain *d;
        int cpu;
@@ -1006,16 +1016,24 @@ static int set_l3_qos_cfg(struct rdt_resource *r, bool 
enable)
        if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
                return -ENOMEM;
 
-       list_for_each_entry(d, &r->domains, list) {
+       if (level == RDT_RESOURCE_L3)
+               update = l3_qos_cfg_update;
+       else if (level == RDT_RESOURCE_L2)
+               update = l2_qos_cfg_update;
+       else
+               return -EINVAL;
+
+       r_l = &rdt_resources_all[level];
+       list_for_each_entry(d, &r_l->domains, list) {
                /* Pick one CPU from each domain instance to update MSR */
                cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
        }
        cpu = get_cpu();
        /* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */
        if (cpumask_test_cpu(cpu, cpu_mask))
-               l3_qos_cfg_update(&enable);
+               update(&enable);
        /* Update QOS_CFG MSR on all other cpus in cpu_mask. */
-       smp_call_function_many(cpu_mask, l3_qos_cfg_update, &enable, 1);
+       smp_call_function_many(cpu_mask, update, &enable, 1);
        put_cpu();
 
        free_cpumask_var(cpu_mask);
@@ -1023,52 +1041,99 @@ static int set_l3_qos_cfg(struct rdt_resource *r, bool 
enable)
        return 0;
 }
 
-static int cdp_enable(void)
+static int cdp_enable(int level, int data_type, int code_type)
 {
-       struct rdt_resource *r_l3data = &rdt_resources_all[RDT_RESOURCE_L3DATA];
-       struct rdt_resource *r_l3code = &rdt_resources_all[RDT_RESOURCE_L3CODE];
-       struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
+       struct rdt_resource *r_ldata = &rdt_resources_all[data_type];
+       struct rdt_resource *r_lcode = &rdt_resources_all[code_type];
+       struct rdt_resource *r_l = &rdt_resources_all[level];
        int ret;
 
-       if (!r_l3->alloc_capable || !r_l3data->alloc_capable ||
-           !r_l3code->alloc_capable)
+       if (!r_l->alloc_capable || !r_ldata->alloc_capable ||
+           !r_lcode->alloc_capable)
                return -EINVAL;
 
-       ret = set_l3_qos_cfg(r_l3, true);
+       ret = set_cache_qos_cfg(level, true);
        if (!ret) {
-               r_l3->alloc_enabled = false;
-               r_l3data->alloc_enabled = true;
-               r_l3code->alloc_enabled = true;
+               r_l->alloc_enabled = false;
+               r_ldata->alloc_enabled = true;
+               r_lcode->alloc_enabled = true;
        }
        return ret;
 }
 
-static void cdp_disable(void)
+static int cdpl3_enable(void)
 {
-       struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
+       return cdp_enable(RDT_RESOURCE_L3, RDT_RESOURCE_L3DATA,
+                         RDT_RESOURCE_L3CODE);
+}
+
+static int cdpl2_enable(void)
+{
+       return cdp_enable(RDT_RESOURCE_L2, RDT_RESOURCE_L2DATA,
+                         RDT_RESOURCE_L2CODE);
+}
+
+static void cdp_disable(int level, int data_type, int code_type)
+{
+       struct rdt_resource *r = &rdt_resources_all[level];
 
        r->alloc_enabled = r->alloc_capable;
 
-       if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled) {
-               rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled = false;
-               rdt_resources_all[RDT_RESOURCE_L3CODE].alloc_enabled = false;
-               set_l3_qos_cfg(r, false);
+       if (rdt_resources_all[data_type].alloc_enabled) {
+               rdt_resources_all[data_type].alloc_enabled = false;
+               rdt_resources_all[code_type].alloc_enabled = false;
+               set_cache_qos_cfg(level, false);
        }
 }
 
+static void cdpl3_disable(void)
+{
+       cdp_disable(RDT_RESOURCE_L3, RDT_RESOURCE_L3DATA, RDT_RESOURCE_L3CODE);
+}
+
+static void cdpl2_disable(void)
+{
+       cdp_disable(RDT_RESOURCE_L2, RDT_RESOURCE_L2DATA, RDT_RESOURCE_L2CODE);
+}
+
+static void cdp_disable_all(void)
+{
+       if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled)
+               cdpl3_disable();
+       if (rdt_resources_all[RDT_RESOURCE_L2DATA].alloc_enabled)
+               cdpl2_disable();
+}
+
 static int parse_rdtgroupfs_options(char *data)
 {
        char *token, *o = data;
        int ret = 0;
 
        while ((token = strsep(&o, ",")) != NULL) {
-               if (!*token)
-                       return -EINVAL;
+               if (!*token) {
+                       ret = -EINVAL;
+                       goto out;
+               }
 
-               if (!strcmp(token, "cdp"))
-                       ret = cdp_enable();
+               if (!strcmp(token, "cdp")) {
+                       ret = cdpl3_enable();
+                       if (ret)
+                               goto out;
+               } else if (!strcmp(token, "cdpl2")) {
+                       ret = cdpl2_enable();
+                       if (ret)
+                               goto out;
+               } else {
+                       ret = -EINVAL;
+                       goto out;
+               }
        }
 
+       return 0;
+
+out:
+       pr_err("Invalid mount option \"%s\"\n", token);
+
        return ret;
 }
 
@@ -1223,7 +1288,7 @@ static struct dentry *rdt_mount(struct file_system_type 
*fs_type,
 out_info:
        kernfs_remove(kn_info);
 out_cdp:
-       cdp_disable();
+       cdp_disable_all();
 out:
        rdt_last_cmd_clear();
        mutex_unlock(&rdtgroup_mutex);
@@ -1383,7 +1448,7 @@ static void rdt_kill_sb(struct super_block *sb)
        /*Put everything back to default values. */
        for_each_alloc_enabled_rdt_resource(r)
                reset_all_ctrls(r);
-       cdp_disable();
+       cdp_disable_all();
        rmdir_all_sub();
        static_branch_disable_cpuslocked(&rdt_alloc_enable_key);
        static_branch_disable_cpuslocked(&rdt_mon_enable_key);
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index d0e69769abfd..df4d8f7595a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -26,6 +26,7 @@ static const struct cpuid_bit cpuid_bits[] = {
        { X86_FEATURE_CAT_L3,           CPUID_EBX,  1, 0x00000010, 0 },
        { X86_FEATURE_CAT_L2,           CPUID_EBX,  2, 0x00000010, 0 },
        { X86_FEATURE_CDP_L3,           CPUID_ECX,  2, 0x00000010, 1 },
+       { X86_FEATURE_CDP_L2,           CPUID_ECX,  2, 0x00000010, 2 },
        { X86_FEATURE_MBA,              CPUID_EBX,  3, 0x00000010, 0 },
        { X86_FEATURE_HW_PSTATE,        CPUID_EDX,  7, 0x80000007, 0 },
        { X86_FEATURE_CPB,              CPUID_EDX,  9, 0x80000007, 0 },

Reply via email to