提交 19cab98f 编写于 作者: X Xie XiuQi

arm64/mpam: use mpam_{read/write}_sysreg_s for debug

hulk inclusion
category: feature
bugzilla: 5510
CVE: NA
Signed-off-by: NXie XiuQi <xiexiuqi@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 2aed72c6
...@@ -165,11 +165,15 @@ struct rdt_domain { ...@@ -165,11 +165,15 @@ struct rdt_domain {
struct list_head list; struct list_head list;
int id; int id;
struct cpumask cpu_mask; struct cpumask cpu_mask;
void __iomem *base;
/* arch specific fields */ /* arch specific fields */
u32 *ctrl_val; u32 *ctrl_val;
u32 new_ctrl; u32 new_ctrl;
bool have_new_ctrl; bool have_new_ctrl;
/* for debug */
char *cpus_list;
}; };
extern struct mutex resctrl_group_mutex; extern struct mutex resctrl_group_mutex;
...@@ -179,12 +183,9 @@ extern struct resctrl_resource resctrl_resources_all[]; ...@@ -179,12 +183,9 @@ extern struct resctrl_resource resctrl_resources_all[];
int __init resctrl_group_init(void); int __init resctrl_group_init(void);
enum { enum {
MPAM_RESOURCE_L3, MPAM_RESOURCE_SMMU,
MPAM_RESOURCE_L3DATA, MPAM_RESOURCE_CACHE,
MPAM_RESOURCE_L3CODE, MPAM_RESOURCE_MC,
MPAM_RESOURCE_L2,
MPAM_RESOURCE_L2DATA,
MPAM_RESOURCE_L2CODE,
/* Must be the last */ /* Must be the last */
MPAM_NUM_RESOURCES, MPAM_NUM_RESOURCES,
...@@ -213,8 +214,6 @@ int parse_rdtgroupfs_options(char *data); ...@@ -213,8 +214,6 @@ int parse_rdtgroupfs_options(char *data);
static inline int __resctrl_group_show_options(struct seq_file *seq) static inline int __resctrl_group_show_options(struct seq_file *seq)
{ {
if (resctrl_resources_all[MPAM_RESOURCE_L3DATA].alloc_enabled)
seq_puts(seq, ",cdp");
return 0; return 0;
} }
...@@ -222,24 +221,89 @@ void post_resctrl_mount(void); ...@@ -222,24 +221,89 @@ void post_resctrl_mount(void);
#define MPAM_SYS_REG_DEBUG #define MPAM_SYS_REG_DEBUG
static inline u32 mpam_read_sysreg_s(void *reg, char *name)
{
#ifdef MPAM_SYS_REG_DEBUG #ifdef MPAM_SYS_REG_DEBUG
pr_info("read_sysreg_s: %s (addr %p)\n", name, reg); static inline u64 mpam_read_sysreg_s(u64 reg, char *name)
{
pr_info("cpu %2d: read_sysreg_s: %s (addr %016llx)\n", smp_processor_id(), name, reg);
return 0; return 0;
}
#else #else
return read_sysreg_s(reg); #define mpam_read_sysreg_s(reg, name) read_sysreg_s(reg)
#endif #endif
}
static inline u32 mpam_write_sysreg_s(u32 v, void *reg, char *name)
{
#ifdef MPAM_SYS_REG_DEBUG #ifdef MPAM_SYS_REG_DEBUG
pr_info("write_sysreg_s: %s (addr %p), value %x\n", name, reg, v); static inline u64 mpam_write_sysreg_s(u64 v, u64 reg, char *name)
{
pr_info("cpu %2d: write_sysreg_s: %s (addr %016llx), value %016llx\n", smp_processor_id(), name, reg, v);
return 0; return 0;
}
#else #else
return write_sysreg_s(v, reg); #define mpam_write_sysreg_s(v, r, n) write_sysreg_s(v, r)
#endif #endif
#ifdef MPAM_SYS_REG_DEBUG
static inline u32 mpam_readl(const volatile void __iomem *addr)
{
return pr_info("readl: %p\n", addr);
}
#else
#define mpam_readl(addr) readl(addr)
#endif
#ifdef MPAM_SYS_REG_DEBUG
static inline u32 mpam_writel(u64 v, const volatile void __iomem *addr)
{
return pr_info("writel: %016llx to %p\n", v, addr);
} }
#else
#define mpam_writel(v, addr) writel(v, addr)
#endif
/**
* struct msr_param - set a range of MSRs from a domain
* @res: The resource to use
* @value: value
*/
struct msr_param {
struct resctrl_resource *res;
u64 value;
};
/**
* struct resctrl_resource - attributes of an RDT resource
* @rid: The index of the resource
* @alloc_enabled: Is allocation enabled on this machine
* @mon_enabled: Is monitoring enabled for this feature
* @alloc_capable: Is allocation available on this machine
* @mon_capable: Is monitor feature available on this machine
* @name: Name to use in "schemata" file
* @num_closid: Number of CLOSIDs available
* @cache_level: Which cache level defines scope of this resource
* @default_ctrl: Specifies default cache cbm or memory B/W percent.
* @msr_base: Base MSR address for CBMs
* @msr_update: Function pointer to update QOS MSRs
* @data_width: Character width of data when displaying
* @domains: All domains for this resource
* @cache: Cache allocation related data
* @format_str: Per resource format string to show domain value
* @parse_ctrlval: Per resource function pointer to parse control values
* @evt_list: List of monitoring events
* @num_rmid: Number of RMIDs available
* @mon_scale: cqm counter * mon_scale = occupancy in bytes
* @fflags: flags to choose base and info files
*/
struct raw_resctrl_resource {
int num_partid;
u32 default_ctrl;
void (*msr_update) (struct rdt_domain *d, int partid);
int data_width;
const char *format_str;
int (*parse_ctrlval) (char *buf, struct raw_resctrl_resource *r,
struct rdt_domain *d);
int num_pmg;
};
int parse_cbm(char *buf, struct raw_resctrl_resource *r, struct rdt_domain *d);
#endif /* _ASM_ARM64_MPAM_H */ #endif /* _ASM_ARM64_MPAM_H */
/* mpam resource: like L3, memory */
#ifndef _ASM_ARM64_MPAM_RESOURCE_H
#define _ASM_ARM64_MPAM_RESOURCE_H
#include <linux/bitops.h>
#define MPAMF_IDR 0x0000
#define MPAMF_SIDR 0x0008
#define MPAMF_MSMON_IDR 0x0080
#define MPAMF_IMPL_IDR 0x0028
#define MPAMF_CPOR_IDR 0x0030
#define MPAMF_CCAP_IDR 0x0038
#define MPAMF_MBW_IDR 0x0040
#define MPAMF_PRI_IDR 0x0048
#define MPAMF_CSUMON_IDR 0x0088
#define MPAMF_MBWUMON_IDR 0x0090
#define MPAMF_PARTID_NRW_IDR 0x0050
#define MPAMF_IIDR 0x0018
#define MPAMF_AIDR 0x0020
#define MPAMCFG_PART_SEL 0x0100
#define MPAMCFG_CPBM 0x1000
#define MPAMCFG_CMAX 0x0108
#define MPAMCFG_MBW_MIN 0x0200
#define MPAMCFG_MBW_MAX 0x0208
#define MPAMCFG_MBW_WINWD 0x0220
#define MPAMCFG_MBW_PBM 0x2000
#define MPAMCFG_PRI 0x0400
#define MPAMCFG_MBW_PROP 0x0500
#define MPAMCFG_INTPARTID 0x0600
#define MSMON_CFG_MON_SEL 0x0800
#define MSMON_CFG_CSU_FLT 0x0810
#define MSMON_CFG_CSU_CTL 0x0818
#define MSMON_CFG_MBWU_FLT 0x0820
#define MSMON_CFG_MBWU_CTL 0x0828
#define MSMON_CSU 0x0840
#define MSMON_CSU_CAPTURE 0x0848
#define MSMON_MBWU 0x0860
#define MSMON_MBWU_CAPTURE 0x0868
#define MSMON_CAPT_EVNT 0x0808
#define MPAMF_ESR 0x00F8
#define MPAMF_ECR 0x00F0
#define HAS_CCAP_PART BIT(24)
#define HAS_CPOR_PART BIT(25)
#define HAS_MBW_PART BIT(26)
#define HAS_PRI_PART BIT(27)
#define HAS_IMPL_IDR BIT(29)
#define HAS_MSMON BIT(30)
/* MPAMF_IDR */
/* TODO */
#define CPBM_WD_MASK 0xFFFF
#define CPBM_MASK 0x7FFF
#define BWA_WD 6 /* hard code for P680 */
#define MBW_MAX_MASK 0xFC00
#define MBW_MAX_HARDLIM BIT(31)
#define MBW_MAX_SET(v) (MBW_MAX_HARDLIM|((v) << (15 - BWA_WD))) /* [FIXME] hard code for hardlim */
/*
* emulate the mpam nodes
* These should be reported by ACPI MPAM Table.
*/
struct mpam_node {
/* MPAM node header */
u8 type; /* MPAM_SMMU, MPAM_CACHE, MPAM_MC */
u64 addr;
void __iomem *base;
struct cpumask cpu_mask;
u64 default_ctrl;
/* for debug */
char *cpus_list;
char *name;
};
int mpam_nodes_init(void);
#endif /* _ASM_ARM64_MPAM_RESOURCE_H */
...@@ -72,22 +72,22 @@ static void __mpam_sched_in(void) ...@@ -72,22 +72,22 @@ static void __mpam_sched_in(void)
state->cur_rmid = pmg; state->cur_rmid = pmg;
/* set in EL0 */ /* set in EL0 */
reg = read_sysreg_s(SYS_MPAM0_EL1); reg = mpam_read_sysreg_s(SYS_MPAM0_EL1, "SYS_MPAM0_EL1");
reg = reg & (~PARTID_MASK) & partid; reg = reg & (~PARTID_MASK) & partid;
reg = reg & (~PMG_MASK) & pmg; reg = reg & (~PMG_MASK) & pmg;
write_sysreg_s(reg, SYS_MPAM0_EL1); mpam_write_sysreg_s(reg, SYS_MPAM0_EL1, "SYS_MPAM0_EL1");
/* set in EL1 */ /* set in EL1 */
reg = read_sysreg_s(SYS_MPAM1_EL1); reg = mpam_read_sysreg_s(SYS_MPAM1_EL1, "SYS_MPAM1_EL1");
reg = reg & (~PARTID_MASK) & partid; reg = reg & (~PARTID_MASK) & partid;
reg = reg & (~PMG_MASK) & pmg; reg = reg & (~PMG_MASK) & pmg;
write_sysreg_s(reg, SYS_MPAM1_EL1); mpam_write_sysreg_s(reg, SYS_MPAM1_EL1, "SYS_MPAM1_EL1");
/* set in EL2 */ /* set in EL2 */
reg = read_sysreg_s(SYS_MPAM2_EL2); reg = mpam_read_sysreg_s(SYS_MPAM2_EL2, "SYS_MPAM2_EL2");
reg = reg & (~PARTID_MASK) & partid; reg = reg & (~PARTID_MASK) & partid;
reg = reg & (~PMG_MASK) & pmg; reg = reg & (~PMG_MASK) & pmg;
write_sysreg_s(reg, SYS_MPAM2_EL2); mpam_write_sysreg_s(reg, SYS_MPAM2_EL2, "SYS_MPAM2_EL2");
} }
} }
......
...@@ -61,6 +61,7 @@ arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o ...@@ -61,6 +61,7 @@ arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o
arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o
arm64-obj-$(CONFIG_SDEI_WATCHDOG) += watchdog_sdei.o arm64-obj-$(CONFIG_SDEI_WATCHDOG) += watchdog_sdei.o
arm64-obj-$(CONFIG_MPAM) += mpam.o mpam_ctrlmon.o mpam_mon.o arm64-obj-$(CONFIG_MPAM) += mpam.o mpam_ctrlmon.o mpam_mon.o
arm64-obj-$(CONFIG_MPAM) += mpam.o mpam_ctrlmon.o mpam_mon.o mpam_resource.o
obj-y += $(arm64-obj-y) vdso/ probes/ obj-y += $(arm64-obj-y) vdso/ probes/
obj-m += $(arm64-obj-m) obj-m += $(arm64-obj-m)
......
...@@ -34,7 +34,9 @@ ...@@ -34,7 +34,9 @@
#include <linux/resctrlfs.h> #include <linux/resctrlfs.h>
#include <asm/mpam_sched.h> #include <asm/mpam_sched.h>
#include <asm/mpam_resource.h>
#include <asm/resctrl.h> #include <asm/resctrl.h>
#include <asm/io.h>
/* Mutex to protect rdtgroup access. */ /* Mutex to protect rdtgroup access. */
DEFINE_MUTEX(resctrl_group_mutex); DEFINE_MUTEX(resctrl_group_mutex);
...@@ -59,51 +61,168 @@ int max_name_width, max_data_width; ...@@ -59,51 +61,168 @@ int max_name_width, max_data_width;
*/ */
bool rdt_alloc_capable; bool rdt_alloc_capable;
char *mpam_types_str[] = {
"MPAM_RESOURCE_SMMU",
"MPAM_RESOURCE_CACHE",
"MPAM_RESOURCE_MC",
};
struct mpam_node mpam_node_all[] = {
/* P0 DIE 0: cluster 0 */
{
.name = "L3T0",
.type = MPAM_RESOURCE_CACHE,
.addr = 0x90390000,
.cpus_list = "0",
.default_ctrl = 0x7fff,
},
/* P0 DIE 0: cluster 1 */
{
.name = "L3T1",
.type = MPAM_RESOURCE_CACHE,
.addr = 0x903a0000,
.cpus_list = "1",
.default_ctrl = 0x7fff,
},
/* P0 DIE 0: cluster 2 */
{
.name = "L3T2",
.type = MPAM_RESOURCE_CACHE,
.addr = 0x903b0000,
.cpus_list = "2",
.default_ctrl = 0x7fff,
},
/* P0 DIE 0: cluster 3 */
{
.name = "L3T3",
.type = MPAM_RESOURCE_CACHE,
.addr = 0x903c0000,
.cpus_list = "3",
.default_ctrl = 0x7fff,
},
/* P0 DIE 0: HHA0 */
{
.name = "HHA0",
.type = MPAM_RESOURCE_MC,
.addr = 0x90410000,
.cpus_list = "0-3",
},
/* P0 DIE 0: HHA1 */
{
.name = "HHA1",
.type = MPAM_RESOURCE_MC,
.addr = 0x90420000,
.cpus_list = "0-3",
},
/* other mpam nodes ... */
};
int mpam_nodes_init(void)
{
int i, ret = 0;
size_t num_nodes = ARRAY_SIZE(mpam_node_all);
struct mpam_node *n;
for (i = 0; i < num_nodes; i++) {
n = &mpam_node_all[i];
ret |= cpulist_parse(n->cpus_list, &n->cpu_mask);
n->base = ioremap(n->addr, 0x10000);
}
return ret;
}
void mpam_nodes_show(void)
{
int i, cpu;
size_t num_nodes = ARRAY_SIZE(mpam_node_all);
struct mpam_node *n;
char *types[] = {"MPAM_RESOURCE_SMMU", "MPAM_RESOURCE_CACHE", "MPAM_RESOURCE_MC"};
for (i = 0; i < num_nodes; i++) {
n = &mpam_node_all[i];
pr_cont("type: %s; addr = %p; cpus_list = %s; cpus: ",
types[n->type], (void *)n->addr, n->cpus_list);
for_each_cpu(cpu, &n->cpu_mask) {
pr_cont("%d, ", cpu);
}
pr_cont("\n");
}
}
static void
cat_wrmsr(struct rdt_domain *d, int partid);
static void
bw_wrmsr(struct rdt_domain *d, int partid);
#define domain_init(id) LIST_HEAD_INIT(resctrl_resources_all[id].domains) #define domain_init(id) LIST_HEAD_INIT(resctrl_resources_all[id].domains)
struct resctrl_resource resctrl_resources_all[] = { struct raw_resctrl_resource raw_resctrl_resources_all[] = {
[MPAM_RESOURCE_L3] = { [MPAM_RESOURCE_SMMU] = {
.rid = MPAM_RESOURCE_L3, .msr_update = cat_wrmsr,
.name = "L3", .parse_ctrlval = parse_cbm,
.domains = domain_init(MPAM_RESOURCE_L3), .format_str = "%d=%0*x",
.fflags = RFTYPE_RES_CACHE,
}, },
[MPAM_RESOURCE_L3DATA] = { [MPAM_RESOURCE_CACHE] = {
.rid = MPAM_RESOURCE_L3DATA, .msr_update = cat_wrmsr,
.name = "L3DATA", .parse_ctrlval = parse_cbm,
.domains = domain_init(MPAM_RESOURCE_L3DATA), .format_str = "%d=%0*x",
.fflags = RFTYPE_RES_CACHE,
}, },
[MPAM_RESOURCE_L3CODE] = ( [MPAM_RESOURCE_MC] = {
.rid = MPAM_RESOURCE_L3CODE, .msr_update = bw_wrmsr,
.name = "L3CODE", .parse_ctrlval = parse_cbm, /* [FIXME] add parse_bw() helper */
.domains = domain_init(MPAM_RESOURCE_L3CODE), .format_str = "%d=%0*x",
.fflags = RFTYPE_RES_CACHE,
}, },
[MPAM_RESOURCE_L2] = { };
.rid = MPAM_RESOURCE_L2,
.name = "L2", struct resctrl_resource resctrl_resources_all[] = {
.domains = domain_init(MPAM_RESOURCE_L2), [MPAM_RESOURCE_SMMU] = {
.fflags = RFTYPE_RES_CACHE, .rid = MPAM_RESOURCE_SMMU,
.name = "SMMU",
.domains = domain_init(MPAM_RESOURCE_SMMU),
.res = &raw_resctrl_resources_all[MPAM_RESOURCE_SMMU],
.fflags = RFTYPE_RES_SMMU,
.alloc_enabled = 1,
}, },
[MPAM_RESOURCE_L2DATA] = { [MPAM_RESOURCE_CACHE] = {
.rid = MPAM_RESOURCE_L2DATA, .rid = MPAM_RESOURCE_CACHE,
.name = "L2DATA", .name = "L3",
.domains = domain_init(MPAM_RESOURCE_L2DATA), .domains = domain_init(MPAM_RESOURCE_CACHE),
.res = &raw_resctrl_resources_all[MPAM_RESOURCE_CACHE],
.fflags = RFTYPE_RES_CACHE, .fflags = RFTYPE_RES_CACHE,
.alloc_enabled = 1,
}, },
[MPAM_RESOURCE_L2CODE] = { [MPAM_RESOURCE_MC] = {
.rid = MPAM_RESOURCE_L2CODE, .rid = MPAM_RESOURCE_MC,
.name = "L2CODE", .name = "MB",
.domains = domain_init(MPAM_RESOURCE_L2CODE), .domains = domain_init(MPAM_RESOURCE_MC),
.fflags = RFTYPE_RES_CACHE, .res = &raw_resctrl_resources_all[MPAM_RESOURCE_MC],
.fflags = RFTYPE_RES_MC,
.alloc_enabled = 1,
}, },
}; };
static void rdt_get_cache_alloc_cfg(int idx, struct resctrl_resource *r) static void
cat_wrmsr(struct rdt_domain *d, int partid)
{
mpam_writel(partid, d->base + MPAMCFG_PART_SEL);
mpam_writel(d->ctrl_val[partid], d->base + MPAMCFG_CPBM);
}
static void
bw_wrmsr(struct rdt_domain *d, int partid)
{ {
r->alloc_capable = true; u64 val = MBW_MAX_SET(d->ctrl_val[partid]);
r->alloc_enabled = true;
mpam_writel(partid, d->base + MPAMCFG_PART_SEL);
mpam_writel(val, d->base + MPAMCFG_MBW_MAX);
} }
/* /*
...@@ -125,7 +244,6 @@ static int closid_free_map; ...@@ -125,7 +244,6 @@ static int closid_free_map;
void closid_init(void) void closid_init(void)
{ {
struct resctrl_resource *r;
int resctrl_min_closid = 32; int resctrl_min_closid = 32;
closid_free_map = BIT_MASK(resctrl_min_closid) - 1; closid_free_map = BIT_MASK(resctrl_min_closid) - 1;
...@@ -151,14 +269,9 @@ void closid_free(int closid) ...@@ -151,14 +269,9 @@ void closid_free(int closid)
closid_free_map |= 1 << closid; closid_free_map |= 1 << closid;
} }
static void clear_closid_rmid(int cpu)
{
struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
}
static int mpam_online_cpu(unsigned int cpu) static int mpam_online_cpu(unsigned int cpu)
{ {
pr_info("online cpu\n"); pr_info("CPU %2d: online cpu and enable mpam\n", cpu);
return 0; return 0;
} }
...@@ -170,15 +283,14 @@ static int mpam_offline_cpu(unsigned int cpu) ...@@ -170,15 +283,14 @@ static int mpam_offline_cpu(unsigned int cpu)
static __init bool get_rdt_alloc_resources(void) static __init bool get_rdt_alloc_resources(void)
{ {
bool ret = false; bool ret = true;
return ret; return ret;
} }
static __init bool get_rdt_mon_resources(void) static __init bool get_rdt_mon_resources(void)
{ {
bool ret = true;
bool ret = false;
return ret; return ret;
} }
...@@ -193,9 +305,6 @@ static __init bool get_resctrl_resources(void) ...@@ -193,9 +305,6 @@ static __init bool get_resctrl_resources(void)
void post_resctrl_mount(void) void post_resctrl_mount(void)
{ {
struct rdt_domain *dom;
struct resctrl_resource *r;
if (rdt_alloc_capable) if (rdt_alloc_capable)
static_branch_enable_cpuslocked(&resctrl_alloc_enable_key); static_branch_enable_cpuslocked(&resctrl_alloc_enable_key);
if (rdt_mon_capable) if (rdt_mon_capable)
...@@ -208,6 +317,7 @@ void post_resctrl_mount(void) ...@@ -208,6 +317,7 @@ void post_resctrl_mount(void)
static int reset_all_ctrls(struct resctrl_resource *r) static int reset_all_ctrls(struct resctrl_resource *r)
{ {
pr_info("%s\n", __func__); pr_info("%s\n", __func__);
return 0;
} }
void resctrl_resource_reset(void) void resctrl_resource_reset(void)
...@@ -234,7 +344,6 @@ int parse_rdtgroupfs_options(char *data) ...@@ -234,7 +344,6 @@ int parse_rdtgroupfs_options(char *data)
return ret; return ret;
} }
/* /*
* This is safe against intel_resctrl_sched_in() called from __switch_to() * This is safe against intel_resctrl_sched_in() called from __switch_to()
* because __switch_to() is executed with interrupts disabled. A local call * because __switch_to() is executed with interrupts disabled. A local call
...@@ -671,6 +780,100 @@ static struct rftype res_specific_files[] = { ...@@ -671,6 +780,100 @@ static struct rftype res_specific_files[] = {
}, },
}; };
struct rdt_domain *mpam_find_domain(struct resctrl_resource *r, int id,
struct list_head **pos)
{
struct rdt_domain *d;
struct list_head *l;
if (id < 0)
return ERR_PTR(id);
list_for_each(l, &r->domains) {
d = list_entry(l, struct rdt_domain, list);
/* When id is found, return its domain. */
if (id == d->id)
return d;
/* Stop searching when finding id's position in sorted list. */
if (id < d->id)
break;
}
if (pos)
*pos = l;
return NULL;
}
static void mpam_domains_init(struct resctrl_resource *r)
{
int i, cpu, id = 0;
size_t num_nodes = ARRAY_SIZE(mpam_node_all);
struct mpam_node *n;
struct list_head *add_pos = NULL, *l;
struct rdt_domain *d;
struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res;
char *types[] = {"MPAM_RESOURCE_SMMU", "MPAM_RESOURCE_CACHE", "MPAM_RESOURCE_MC"};
for (i = 0; i < num_nodes; i++) {
n = &mpam_node_all[i];
if (r->rid != n->type)
continue;
pr_cont("type: %s; addr = %p; cpus_list = %s; cpus: ",
types[n->type], (void *)n->addr, n->cpus_list);
for_each_cpu(cpu, &n->cpu_mask) {
pr_cont("%d, ", cpu);
}
pr_cont("\n");
d = mpam_find_domain(r, id, &add_pos);
if (IS_ERR(d)) {
pr_warn("Could't find cache id for cpu %d\n", cpu);
return;
}
if (!d)
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return;
d->id = id;
d->base = n->base;
cpumask_copy(&d->cpu_mask, &n->cpu_mask);
rr->default_ctrl = n->default_ctrl;
rr->num_partid = 32;
d->cpus_list = n->cpus_list;
d->ctrl_val = kmalloc_array(rr->num_partid, sizeof(*d->ctrl_val), GFP_KERNEL);
if (!d->ctrl_val)
return;
list_add_tail(&d->list, add_pos);
id++;
}
/*
* for debug
*/
list_for_each(l, &r->domains) {
d = list_entry(l, struct rdt_domain, list);
pr_cont("domain: %d; type: %s; addr = %p; cpus_list = %s; cpus: ",
d->id, types[r->rid], (void *)d->base, d->cpus_list);
for_each_cpu(cpu, &d->cpu_mask) {
pr_cont("%d, ", cpu);
}
pr_cont("\n");
}
}
static int __init mpam_late_init(void) static int __init mpam_late_init(void)
{ {
struct resctrl_resource *r; struct resctrl_resource *r;
...@@ -679,6 +882,18 @@ static int __init mpam_late_init(void) ...@@ -679,6 +882,18 @@ static int __init mpam_late_init(void)
if (!get_resctrl_resources()) if (!get_resctrl_resources())
return -ENODEV; return -ENODEV;
ret = mpam_nodes_init();
if (ret) {
pr_err("internal error: bad cpu list\n");
return ret;
}
/* for debug */
mpam_nodes_show();
mpam_domains_init(&resctrl_resources_all[MPAM_RESOURCE_CACHE]);
mpam_domains_init(&resctrl_resources_all[MPAM_RESOURCE_MC]);
state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"arm64/mpam:online:", "arm64/mpam:online:",
mpam_online_cpu, mpam_offline_cpu); mpam_online_cpu, mpam_offline_cpu);
......
...@@ -30,11 +30,180 @@ ...@@ -30,11 +30,180 @@
#include <asm/resctrl.h> #include <asm/resctrl.h>
/*
* Check whether a cache bit mask is valid. The SDM says:
* Please note that all (and only) contiguous '1' combinations
* are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.).
* Additionally Haswell requires at least two bits set.
*/
static bool cbm_validate(char *buf, unsigned long *data, struct raw_resctrl_resource *r)
{
u64 val;
int ret;
ret = kstrtou64(buf, 16, &val);
if (ret) {
rdt_last_cmd_printf("non-hex character in mask %s\n", buf);
return false;
}
#if 0
if (val == 0 || val > r->default_ctrl) {
rdt_last_cmd_puts("mask out of range\n");
return false;
}
#endif
*data = val;
return true;
}
/*
* Read one cache bit mask (hex). Check that it is valid for the current
* resource type.
*/
int parse_cbm(char *buf, struct raw_resctrl_resource *r, struct rdt_domain *d)
{
unsigned long data;
if (d->have_new_ctrl) {
rdt_last_cmd_printf("duplicate domain %d\n", d->id);
return -EINVAL;
}
if (!cbm_validate(buf, &data, r))
return -EINVAL;
d->new_ctrl = data;
d->have_new_ctrl = true;
return 0;
}
/*
* For each domain in this resource we expect to find a series of:
* id=mask
* separated by ";". The "id" is in decimal, and must match one of
* the "id"s for this resource.
*/
static int parse_line(char *line, struct resctrl_resource *r)
{
struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res;
char *dom = NULL, *id;
struct rdt_domain *d;
unsigned long dom_id;
next:
if (!line || line[0] == '\0')
return 0;
dom = strsep(&line, ";");
id = strsep(&dom, "=");
if (!dom || kstrtoul(id, 10, &dom_id)) {
rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
return -EINVAL;
}
dom = strim(dom);
list_for_each_entry(d, &r->domains, list) {
if (d->id == dom_id) {
if (rr->parse_ctrlval(dom, (struct raw_resctrl_resource *)&r->res, d))
return -EINVAL;
goto next;
}
}
return -EINVAL;
}
static int update_domains(struct resctrl_resource *r, int partid)
{
struct raw_resctrl_resource *rr;
struct rdt_domain *d;
rr = (struct raw_resctrl_resource *)r->res;
list_for_each_entry(d, &r->domains, list) {
if (d->have_new_ctrl && d->new_ctrl != d->ctrl_val[partid]) {
d->ctrl_val[partid] = d->new_ctrl;
rr->msr_update(d, partid);
}
}
return 0;
}
static int resctrl_group_parse_resource(char *resname, char *tok, int closid)
{
struct resctrl_resource *r;
struct raw_resctrl_resource *rr;
for_each_resctrl_resource(r) {
if (r->alloc_enabled) {
rr = (struct raw_resctrl_resource *)r->res;
if (!strcmp(resname, r->name) && closid < rr->num_partid)
return parse_line(tok, r);
}
}
rdt_last_cmd_printf("unknown/unsupported resource name '%s'\n", resname);
return -EINVAL;
}
ssize_t resctrl_group_schemata_write(struct kernfs_open_file *of, ssize_t resctrl_group_schemata_write(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off) char *buf, size_t nbytes, loff_t off)
{ {
return 0; struct rdtgroup *rdtgrp;
struct rdt_domain *dom;
struct resctrl_resource *r;
char *tok, *resname;
int closid, ret = 0;
/* Valid input requires a trailing newline */
if (nbytes == 0 || buf[nbytes - 1] != '\n')
return -EINVAL;
buf[nbytes - 1] = '\0';
rdtgrp = resctrl_group_kn_lock_live(of->kn);
if (!rdtgrp) {
resctrl_group_kn_unlock(of->kn);
return -ENOENT;
}
rdt_last_cmd_clear();
closid = rdtgrp->closid;
for_each_resctrl_resource(r) {
if (r->alloc_enabled) {
list_for_each_entry(dom, &r->domains, list)
dom->have_new_ctrl = false;
}
}
while ((tok = strsep(&buf, "\n")) != NULL) {
resname = strim(strsep(&tok, ":"));
if (!tok) {
rdt_last_cmd_puts("Missing ':'\n");
ret = -EINVAL;
goto out;
}
if (tok[0] == '\0') {
rdt_last_cmd_printf("Missing '%s' value\n", resname);
ret = -EINVAL;
goto out;
}
ret = resctrl_group_parse_resource(resname, tok, closid);
if (ret)
goto out;
}
for_each_resctrl_resource(r) {
if (r->alloc_enabled) {
ret = update_domains(r, closid);
if (ret)
goto out;
}
}
out:
resctrl_group_kn_unlock(of->kn);
return ret ?: nbytes;
} }
int resctrl_group_schemata_show(struct kernfs_open_file *of, int resctrl_group_schemata_show(struct kernfs_open_file *of,
......
#include <linux/io.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/kthread.h>
#include <linux/resctrlfs.h>
#include <asm/mpam_resource.h>
#include <asm/mpam.h>
...@@ -109,7 +109,7 @@ static int __resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflag ...@@ -109,7 +109,7 @@ static int __resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflag
struct rftype *rfts, int len) struct rftype *rfts, int len)
{ {
struct rftype *rft; struct rftype *rft;
int ret; int ret = 0;
lockdep_assert_held(&resctrl_group_mutex); lockdep_assert_held(&resctrl_group_mutex);
...@@ -136,7 +136,7 @@ static int __resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflag ...@@ -136,7 +136,7 @@ static int __resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflag
static int resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflags) static int resctrl_group_add_files(struct kernfs_node *kn, unsigned long fflags)
{ {
int ret; int ret = 0;
if (res_common_files) if (res_common_files)
ret = __resctrl_group_add_files(kn, fflags, res_common_files, ret = __resctrl_group_add_files(kn, fflags, res_common_files,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册