mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 16:01:14 +07:00
Merge branch 'x86-cache-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/cache updates from Thomas Gleixner: "A set of patches which add support for L2 cache partitioning to the Intel RDT facility" * 'x86-cache-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/intel_rdt: Add command line parameter to control L2_CDP x86/intel_rdt: Enable L2 CDP in MSR IA32_L2_QOS_CFG x86/intel_rdt: Add two new resources for L2 Code and Data Prioritization (CDP) x86/intel_rdt: Enumerate L2 Code and Data Prioritization (CDP) feature x86/intel_rdt: Add L2CDP support in documentation x86/intel_rdt: Update documentation
This commit is contained in:
commit
f0b13428c9
@ -3684,7 +3684,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
|
||||
|
||||
|
@ -7,15 +7,24 @@ Tony Luck <tony.luck@intel.com>
|
||||
Vikas Shivappa <vikas.shivappa@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.
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 },
|
||||
|
Loading…
Reference in New Issue
Block a user