Commit cf92ebfa authored by Wang ShaoBo's avatar Wang ShaoBo Committed by Zheng Zengkai
Browse files

arm64/mpam: Add resctrl_ctrl_feature structure to manage ctrl features



hulk inclusion
category: feature
feature: ARM MPAM support
bugzilla: 48265
CVE: NA

--------------------------------

Structure resctrl_ctrl_feature taken by resources is introduced to manage
ctrl features, of which characteristic like max width from outer input
and the base we parse from.

Now it is more practical for declaring a new ctrl feature, such as SCHEMA_PRI
feature, only associated with internal priority setting exported by mpam
devices, where informations is collected from mpam_resctrl_resource_init(),
and next be chosen open or close by user options.

ctrl_ctrl_feature structure contains a flags field to avoid duplicated
control type, for instance, SCHEMA_COMM feature selectes cpbm (Cache
portion bitmap) as resource Cache default control type, so we should not
enable this feature no longer if user manually selectes cpbm control
type through mount options.

This field evt in ctrl_ctrl_feature structure is enum rdt_event_id type
variable which works like eee4ad2a36e6 ("arm64/mpam: Add hook-events id
for ctrl features") illustrates.

Signed-off-by: default avatarWang ShaoBo <bobo.shaobowang@huawei.com>
Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: default avatarCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 7d3cd1a2
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -124,14 +124,28 @@ enum resctrl_ctrl_type {
	SCHEMA_NUM_CTRL_TYPE
};

struct resctrl_ctrl_feature {
	enum resctrl_ctrl_type type;
	int        flags;
	const char *name;

	u32        max_wd;

	int        base;
	int        evt;

	int        default_ctrl;

	bool       capable;
	bool       enabled;
};

#define for_each_ctrl_type(t)	\
		for (t = SCHEMA_COMM; t != SCHEMA_NUM_CTRL_TYPE; t++)

#define for_each_extend_ctrl_type(t)	\
		for (t = SCHEMA_PRI; t != SCHEMA_NUM_CTRL_TYPE; t++)

bool resctrl_ctrl_extend_bits_match(u32 bitmap, enum resctrl_ctrl_type type);

enum resctrl_conf_type {
	CDP_BOTH = 0,
	CDP_CODE,
@@ -319,11 +333,10 @@ struct raw_resctrl_resource {
	u16                 num_intpartid;
	u16                 num_pmg;

	u16                 extend_ctrls_wd[SCHEMA_NUM_CTRL_TYPE];

	void (*msr_update)(struct resctrl_resource *r, struct rdt_domain *d,
				struct msr_param *para);
	u64 (*msr_read)(struct rdt_domain *d, struct msr_param *para);
	u64 (*msr_read)(struct resctrl_resource *r, struct rdt_domain *d,
				struct msr_param *para);

	int			data_width;
	const char		*format_str;
@@ -334,6 +347,8 @@ struct raw_resctrl_resource {
	u16                num_mon;
	u64 (*mon_read)(struct rdt_domain *d, void *md_priv);
	int (*mon_write)(struct rdt_domain *d, void *md_priv);

	struct resctrl_ctrl_feature ctrl_features[SCHEMA_NUM_CTRL_TYPE];
};

/* 64bit arm64 specified */
+20 −9
Original line number Diff line number Diff line
@@ -92,8 +92,8 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
	rr = r->res;
	INIT_LIST_HEAD(&s->schema_ctrl_list);
	for_each_extend_ctrl_type(type) {
		if (!resctrl_ctrl_extend_bits_match(r->ctrl_extend_bits, type) ||
			!rr->extend_ctrls_wd[type])
		if (!rr->ctrl_features[type].enabled ||
			!rr->ctrl_features[type].max_wd)
			continue;

		sc = kzalloc(sizeof(*sc), GFP_KERNEL);
@@ -281,6 +281,9 @@ parse_line(char *line, struct resctrl_resource *r,
	unsigned long dom_id;
	hw_closid_t hw_closid;

	if (!rr->ctrl_features[ctrl_type].enabled)
		return -EINVAL;

next:
	if (!line || line[0] == '\0')
		return 0;
@@ -428,6 +431,9 @@ static void show_doms(struct seq_file *s, struct resctrl_resource *r,
	bool prev_auto_fill = false;
	u32 reg_val;

	if (!rr->ctrl_features[type].enabled)
		return;

	para.closid = closid;
	para.type = type;

@@ -436,15 +442,15 @@ static void show_doms(struct seq_file *s, struct resctrl_resource *r,

	seq_printf(s, "%*s:", max_name_width, schema_name);
	list_for_each_entry(dom, &r->domains, list) {
		reg_val = rr->msr_read(dom, &para);
		reg_val = rr->msr_read(r, dom, &para);

		if (rg && reg_val == r->default_ctrl[SCHEMA_COMM] &&
				prev_auto_fill == true)
		if (reg_val == rr->ctrl_features[SCHEMA_COMM].default_ctrl &&
			rg && prev_auto_fill == true)
			continue;

		if (sep)
			seq_puts(s, ";");
		if (rg && reg_val == r->default_ctrl[SCHEMA_COMM]) {
		if (rg && reg_val == rr->ctrl_features[SCHEMA_COMM].default_ctrl) {
			prev_auto_fill = true;
			seq_puts(s, "S");
		} else {
@@ -750,22 +756,24 @@ static void rdtgroup_init_mba(struct resctrl_schema *s, u32 closid)
{
	struct resctrl_staged_config *cfg;
	struct resctrl_resource *r;
	struct raw_resctrl_resource *rr;
	struct rdt_domain *d;
	enum resctrl_ctrl_type t;

	r = s->res;
	if (WARN_ON(!r))
		return;
	rr = r->res;

	list_for_each_entry(d, &s->res->domains, list) {
		cfg = &d->staged_cfg[CDP_BOTH];
		cfg->cdp_both_ctrl = s->cdp_mc_both;
		cfg->new_ctrl[SCHEMA_COMM] = r->default_ctrl[SCHEMA_COMM];
		cfg->new_ctrl[SCHEMA_COMM] = rr->ctrl_features[SCHEMA_COMM].default_ctrl;
		resctrl_cdp_map(clos, closid, CDP_BOTH, cfg->hw_closid);
		cfg->have_new_ctrl = true;
		/* Set extension ctrl default value, e.g. priority/hardlimit */
		for_each_extend_ctrl_type(t) {
			cfg->new_ctrl[t] = r->default_ctrl[t];
			cfg->new_ctrl[t] = rr->ctrl_features[t].default_ctrl;
		}
	}
}
@@ -787,6 +795,7 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
	enum resctrl_ctrl_type ctrl_type;
	struct rdt_domain *d;
	struct resctrl_resource *r;
	struct raw_resctrl_resource *rr;
	u32 used_b = 0;
	u32 unused_b = 0;
	unsigned long tmp_cbm;
@@ -794,6 +803,7 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
	r = s->res;
	if (WARN_ON(!r))
		return -EINVAL;
	rr = r->res;

	list_for_each_entry(d, &s->res->domains, list) {
		cfg = &d->staged_cfg[conf_type];
@@ -823,7 +833,8 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
		 * with MPAM capabilities.
		 */
		for_each_extend_ctrl_type(ctrl_type) {
			cfg->new_ctrl[ctrl_type] = r->default_ctrl[ctrl_type];
			cfg->new_ctrl[ctrl_type] =
				rr->ctrl_features[ctrl_type].default_ctrl;
		}
	}

+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ extern bool rdt_mon_capable;
extern struct list_head mpam_classes;

#define MAX_MBA_BW  100u
#define GRAN_MBA_BW 2u

#define MPAM_ERRCODE_NONE                       0
#define MPAM_ERRCODE_PARTID_SEL_RANGE           1
+134 −153
Original line number Diff line number Diff line
@@ -100,22 +100,6 @@ bool is_resctrl_cdp_enabled(void)
	return !!resctrl_cdp_enabled;
}

static void
resctrl_ctrl_extend_bits_set(u32 *bitmap, enum resctrl_ctrl_type type)
{
	*bitmap |= BIT(type);
}

static void resctrl_ctrl_extend_bits_clear(u32 *bitmap)
{
	*bitmap = 0;
}

bool resctrl_ctrl_extend_bits_match(u32 bitmap, enum resctrl_ctrl_type type)
{
	return bitmap & BIT(type);
}

static void
mpam_resctrl_update_component_cfg(struct resctrl_resource *r,
	struct rdt_domain *d, struct sd_closid *closid);
@@ -124,8 +108,10 @@ static void
common_wrmsr(struct resctrl_resource *r, struct rdt_domain *d,
	struct msr_param *para);

static u64 cache_rdmsr(struct rdt_domain *d, struct msr_param *para);
static u64 mbw_rdmsr(struct rdt_domain *d, struct msr_param *para);
static u64 cache_rdmsr(struct resctrl_resource *r, struct rdt_domain *d,
	struct msr_param *para);
static u64 mbw_rdmsr(struct resctrl_resource *r, struct rdt_domain *d,
	struct msr_param *para);

static u64 cache_rdmon(struct rdt_domain *d, void *md_priv);
static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv);
@@ -145,6 +131,23 @@ struct raw_resctrl_resource raw_resctrl_resources_all[] = {
		.format_str     = "%d=%0*x",
		.mon_read       = cache_rdmon,
		.mon_write      = common_wrmon,
		.ctrl_features  = {
			[SCHEMA_COMM] = {
				.type = SCHEMA_COMM,
				.flags = SCHEMA_COMM,
				.name = "comm",
				.base = 16,
				.evt = QOS_CAT_CPBM_EVENT_ID,
				.capable = 1,
			},
			[SCHEMA_PRI] = {
				.type = SCHEMA_PRI,
				.flags = SCHEMA_PRI,
				.name = "caPrio",
				.base = 10,
				.evt = QOS_CAT_INTPRI_EVENT_ID,
			},
		},
	},
	[RDT_RESOURCE_L2] = {
		.msr_update     = common_wrmsr,
@@ -153,6 +156,23 @@ struct raw_resctrl_resource raw_resctrl_resources_all[] = {
		.format_str     = "%d=%0*x",
		.mon_read       = cache_rdmon,
		.mon_write      = common_wrmon,
		.ctrl_features  = {
			[SCHEMA_COMM] = {
				.type = SCHEMA_COMM,
				.flags = SCHEMA_COMM,
				.name = "comm",
				.base = 16,
				.evt = QOS_CAT_CPBM_EVENT_ID,
				.capable = 1,
			},
			[SCHEMA_PRI] = {
				.type = SCHEMA_PRI,
				.flags = SCHEMA_PRI,
				.name = "caPrio",
				.base = 10,
				.evt = QOS_CAT_INTPRI_EVENT_ID,
			},
		},
	},
	[RDT_RESOURCE_MC] = {
		.msr_update     = common_wrmsr,
@@ -161,6 +181,30 @@ struct raw_resctrl_resource raw_resctrl_resources_all[] = {
		.format_str     = "%d=%0*d",
		.mon_read       = mbw_rdmon,
		.mon_write      = common_wrmon,
		.ctrl_features  = {
			[SCHEMA_COMM] = {
				.type = SCHEMA_COMM,
				.flags = SCHEMA_COMM,
				.name = "comm",
				.base = 10,
				.evt = QOS_MBA_MAX_EVENT_ID,
				.capable = 1,
			},
			[SCHEMA_PRI] = {
				.type = SCHEMA_PRI,
				.flags = SCHEMA_PRI,
				.name = "mbPrio",
				.base = 10,
				.evt = QOS_MBA_INTPRI_EVENT_ID,
			},
			[SCHEMA_HDL] = {
				.type = SCHEMA_HDL,
				.flags = SCHEMA_HDL,
				.name = "mbHdl",
				.base = 10,
				.evt = QOS_MBA_HDL_EVENT_ID,
			},
		},
	},
};

@@ -183,28 +227,18 @@ parse_cache(char *buf, struct resctrl_resource *r,
		enum resctrl_ctrl_type type)
{
	unsigned long data;
	struct raw_resctrl_resource *rr = r->res;

	if (cfg->have_new_ctrl) {
		rdt_last_cmd_printf("duplicate domain\n");
		return -EINVAL;
	}

	switch (type) {
	case SCHEMA_COMM:
		if (kstrtoul(buf, 16, &data))
	if (kstrtoul(buf, rr->ctrl_features[type].base, &data))
		return -EINVAL;
		break;
	case SCHEMA_PRI:
		if (kstrtoul(buf, 10, &data))
			return -EINVAL;
		break;
	case SCHEMA_HDL:
		if (kstrtoul(buf, 10, &data))
			return -EINVAL;
		break;
	default:

	if (data >= rr->ctrl_features[type].max_wd)
		return -EINVAL;
	}

	cfg->new_ctrl[type] = data;
	cfg->have_new_ctrl = true;
@@ -212,54 +246,35 @@ parse_cache(char *buf, struct resctrl_resource *r,
	return 0;
}

static bool bw_validate(char *buf, unsigned long *data,
			struct resctrl_resource *r)
{
	unsigned long bw;
	int ret;

	ret = kstrtoul(buf, 10, &bw);
	if (ret) {
		rdt_last_cmd_printf("non-hex character in mask %s\n", buf);
		return false;
	}

	bw = bw > MAX_MBA_BW ? MAX_MBA_BW : bw;
	bw = bw < r->mbw.min_bw ?  r->mbw.min_bw : bw;
	*data = roundup(bw, r->mbw.bw_gran);

	return true;
}

static int
parse_bw(char *buf, struct resctrl_resource *r,
		struct resctrl_staged_config *cfg,
		enum resctrl_ctrl_type type)
{
	unsigned long data;
	struct raw_resctrl_resource *rr = r->res;

	if (cfg->have_new_ctrl) {
		rdt_last_cmd_printf("duplicate domain\n");
		return -EINVAL;
	}

	switch (type) {
	case SCHEMA_COMM:
		if (!bw_validate(buf, &data, r))
			return -EINVAL;
		break;
	case SCHEMA_PRI:
		if (kstrtoul(buf, 10, &data))
			return -EINVAL;
		break;
	case SCHEMA_HDL:
		if (kstrtoul(buf, 10, &data))
	switch (rr->ctrl_features[type].evt) {
	case QOS_MBA_MAX_EVENT_ID:
		if (kstrtoul(buf, rr->ctrl_features[type].base, &data))
			return -EINVAL;
		data = (data < r->mbw.min_bw) ? r->mbw.min_bw : data;
		data = roundup(data, r->mbw.bw_gran);
		break;
	default:
		if (kstrtoul(buf, rr->ctrl_features[type].base, &data))
			return -EINVAL;
		break;
	}

	if (data >= rr->ctrl_features[type].max_wd)
		return -EINVAL;

	cfg->new_ctrl[type] = data;
	cfg->have_new_ctrl = true;

@@ -285,61 +300,43 @@ common_wrmsr(struct resctrl_resource *r, struct rdt_domain *d,
	mpam_component_config(dom->comp, &args);
}

static u64 cache_rdmsr(struct rdt_domain *d, struct msr_param *para)
static u64 cache_rdmsr(struct resctrl_resource *r, struct rdt_domain *d,
			struct msr_param *para)
{
	u32 result, intpri, dspri;
	u32 result;
	struct sync_args args;
	struct mpam_resctrl_dom *dom;
	struct raw_resctrl_resource *rr = r->res;

	args.closid = *para->closid;
	dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom);

	switch (para->type) {
	case SCHEMA_COMM:
		args.eventid = QOS_CAT_CPBM_EVENT_ID;
	args.eventid = rr->ctrl_features[para->type].evt;
	mpam_component_get_config(dom->comp, &args, &result);
		break;
	case SCHEMA_PRI:
		args.eventid = QOS_CAT_INTPRI_EVENT_ID;
		mpam_component_get_config(dom->comp, &args, &intpri);
		args.eventid = QOS_MBA_DSPRI_EVENT_ID;
		mpam_component_get_config(dom->comp, &args, &dspri);
		result = (intpri > dspri) ? intpri : dspri;
		break;
	default:
		return 0;
	}

	return result;
}

static u64 mbw_rdmsr(struct rdt_domain *d, struct msr_param *para)
static u64 mbw_rdmsr(struct resctrl_resource *r, struct rdt_domain *d,
			struct msr_param *para)
{
	u32 result, intpri, dspri;
	u32 result;
	struct sync_args args;
	struct mpam_resctrl_dom *dom;
	struct raw_resctrl_resource *rr = r->res;

	args.closid = *para->closid;
	dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom);

	switch (para->type) {
	case SCHEMA_COMM:
		args.eventid = QOS_MBA_MAX_EVENT_ID;
		mpam_component_get_config(dom->comp, &args, &result);
		break;
	case SCHEMA_PRI:
		args.eventid = QOS_MBA_INTPRI_EVENT_ID;
		mpam_component_get_config(dom->comp, &args, &intpri);
		args.eventid = QOS_MBA_DSPRI_EVENT_ID;
		mpam_component_get_config(dom->comp, &args, &dspri);
		result = (intpri > dspri) ? intpri : dspri;
		break;
	case SCHEMA_HDL:
		args.eventid = QOS_MBA_HDL_EVENT_ID;
	args.eventid = rr->ctrl_features[para->type].evt;
	mpam_component_get_config(dom->comp, &args, &result);

	switch (rr->ctrl_features[para->type].evt) {
	case QOS_MBA_MAX_EVENT_ID:
		result = roundup(result, r->mbw.bw_gran);
		break;
	default:
		return 0;
		break;
	}

	return result;
@@ -1023,27 +1020,25 @@ static int cdpl2_enable(void)
static void basic_ctrl_enable(void)
{
	struct mpam_resctrl_res *res;
	struct resctrl_resource *r;
	struct raw_resctrl_resource *rr;

	for_each_supported_resctrl_exports(res) {
		r = &res->resctrl_res;
		rr = res->resctrl_res.res;
		/* At least SCHEMA_COMM is supported */
		resctrl_ctrl_extend_bits_set(&r->ctrl_extend_bits, SCHEMA_COMM);
		rr->ctrl_features[SCHEMA_COMM].enabled = true;
	}
}

static int extend_ctrl_enable(enum resctrl_ctrl_type type)
{
	bool match = false;
	struct resctrl_resource *r;
	struct raw_resctrl_resource *rr;
	struct mpam_resctrl_res *res;

	for_each_supported_resctrl_exports(res) {
		r = &res->resctrl_res;
		rr = r->res;
		if (rr->extend_ctrls_wd[type]) {
			resctrl_ctrl_extend_bits_set(&r->ctrl_extend_bits, type);
		rr = res->resctrl_res.res;
		if (rr->ctrl_features[type].capable) {
			rr->ctrl_features[type].enabled = true;
			match = true;
		}
	}
@@ -1056,12 +1051,13 @@ static int extend_ctrl_enable(enum resctrl_ctrl_type type)

static void extend_ctrl_disable(void)
{
	struct resctrl_resource *r;
	struct raw_resctrl_resource *rr;
	struct mpam_resctrl_res *res;

	for_each_supported_resctrl_exports(res) {
		r = &res->resctrl_res;
		resctrl_ctrl_extend_bits_clear(&r->ctrl_extend_bits);
		rr = res->resctrl_res.res;
		rr->ctrl_features[SCHEMA_PRI].enabled = false;
		rr->ctrl_features[SCHEMA_HDL].enabled = false;
	}
}

@@ -1843,48 +1839,32 @@ void __mpam_sched_in(void)

static void
mpam_update_from_resctrl_cfg(struct mpam_resctrl_res *res,
			u32 resctrl_cfg, enum resctrl_ctrl_type ctrl_type,
			u32 resctrl_cfg, enum rdt_event_id evt,
			struct mpam_config *mpam_cfg)
{
	switch (ctrl_type) {
	case SCHEMA_COMM:
		if (res == &mpam_resctrl_exports[RDT_RESOURCE_MC]) {
	u64 range;

			/* For MBA cfg is a percentage of .. */
			if (res->resctrl_mba_uses_mbw_part) {
				/* .. the number of bits we can set */
				range = res->class->mbw_pbm_bits;
				mpam_cfg->mbw_pbm =
					(resctrl_cfg * range) / MAX_MBA_BW;
				mpam_set_feature(mpam_feat_mbw_part, &mpam_cfg->valid);
			} else {
	switch (evt) {
	case QOS_MBA_MAX_EVENT_ID:
		/* .. the number of fractions we can represent */
		range = MBW_MAX_BWA_FRACT(res->class->bwa_wd);
		mpam_cfg->mbw_max = (resctrl_cfg * range) / (MAX_MBA_BW - 1);
		mpam_cfg->mbw_max =
			(mpam_cfg->mbw_max > range) ? range : mpam_cfg->mbw_max;
		mpam_set_feature(mpam_feat_mbw_max, &mpam_cfg->valid);
			}
		} else {
			/*
			 * Nothing clever here as mpam_resctrl_pick_caches()
			 * capped the size at RESCTRL_MAX_CBM.
			 */
		break;
	case QOS_MBA_HDL_EVENT_ID:
		mpam_cfg->hdl = resctrl_cfg;
		mpam_set_feature(mpam_feat_part_hdl, &mpam_cfg->valid);
		break;
	case QOS_CAT_CPBM_EVENT_ID:
		mpam_cfg->cpbm = resctrl_cfg;
		mpam_set_feature(mpam_feat_cpor_part, &mpam_cfg->valid);
		}
		break;
	case SCHEMA_PRI:
		mpam_cfg->dspri = resctrl_cfg;
	case QOS_CAT_INTPRI_EVENT_ID:
		mpam_cfg->intpri = resctrl_cfg;
		mpam_set_feature(mpam_feat_dspri_part, &mpam_cfg->valid);
		mpam_set_feature(mpam_feat_intpri_part, &mpam_cfg->valid);
		break;
	case SCHEMA_HDL:
		mpam_cfg->hdl = resctrl_cfg;
		mpam_set_feature(mpam_feat_part_hdl, &mpam_cfg->valid);
		break;
	default:
		break;
	}
@@ -1903,6 +1883,7 @@ mpam_resctrl_update_component_cfg(struct resctrl_resource *r,
	struct mpam_resctrl_dom *dom;
	struct mpam_resctrl_res *res;
	struct mpam_config *slave_mpam_cfg;
	struct raw_resctrl_resource *rr = r->res;
	enum resctrl_ctrl_type type;
	u32 intpartid = closid->intpartid;
	u32 reqpartid = closid->reqpartid;
@@ -1930,11 +1911,9 @@ mpam_resctrl_update_component_cfg(struct resctrl_resource *r,
	slave_mpam_cfg->valid = 0;

	for_each_ctrl_type(type) {
		/*
		 * we don't need check if we have enabled this ctrl type, because
		 * this ctrls also should be applied an default configuration and
		 * this feature type would be rechecked when configuring mpam devices.
		 */
		if (!rr->ctrl_features[type].enabled)
			continue;

		resctrl_cfg = d->ctrl_val[type][intpartid];
		mpam_update_from_resctrl_cfg(res, resctrl_cfg,
			type, slave_mpam_cfg);
@@ -1947,13 +1926,15 @@ static void mpam_reset_cfg(struct mpam_resctrl_res *res,
{
	int i;
	struct resctrl_resource *r = &res->resctrl_res;
	struct raw_resctrl_resource *rr = r->res;
	enum resctrl_ctrl_type type;

	for (i = 0; i != mpam_sysprops_num_partid(); i++) {
		for_each_ctrl_type(type) {
			mpam_update_from_resctrl_cfg(res, r->default_ctrl[type],
				type, &dom->comp->cfg[i]);
			d->ctrl_val[type][i] = r->default_ctrl[type];
			mpam_update_from_resctrl_cfg(res,
				rr->ctrl_features[type].default_ctrl,
				rr->ctrl_features[type].evt, &dom->comp->cfg[i]);
			d->ctrl_val[type][i] = rr->ctrl_features[type].default_ctrl;
		}
	}
}
+85 −51
Original line number Diff line number Diff line
@@ -334,13 +334,6 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
	struct resctrl_resource *r = &res->resctrl_res;
	struct raw_resctrl_resource *rr = NULL;

	if (class && !r->default_ctrl) {
		r->default_ctrl = kmalloc_array(SCHEMA_NUM_CTRL_TYPE,
			sizeof(*r->default_ctrl), GFP_KERNEL);
		if (!r->default_ctrl)
			return -ENOMEM;
	}

	if (class == mpam_resctrl_exports[RDT_RESOURCE_SMMU].class) {
		return 0;
	} else if (class == mpam_resctrl_exports[RDT_RESOURCE_MC].class) {
@@ -373,17 +366,32 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
			r->mbw.min_bw = MAX_MBA_BW /
				((1ULL << class->bwa_wd) - 1);
			/* the largest mbw_max is 100 */
			r->default_ctrl[SCHEMA_COMM] = 100;
			rr->ctrl_features[SCHEMA_COMM].default_ctrl = MAX_MBA_BW;
			rr->ctrl_features[SCHEMA_COMM].max_wd = MAX_MBA_BW + 1;
			rr->ctrl_features[SCHEMA_COMM].capable = true;
		}

		if (mpam_has_feature(mpam_feat_intpri_part, class->features)) {
			/*
			 * Export internal priority setting, which represents the
			 * max level of control we can export to resctrl. this default
			 * priority is from hardware, no clever here.
			 */
			rr->ctrl_features[SCHEMA_PRI].max_wd = 1 << class->intpri_wd;
			rr->ctrl_features[SCHEMA_PRI].default_ctrl = class->hwdef_intpri;
			rr->ctrl_features[SCHEMA_PRI].capable = true;
		}

		/* Just in case we have an excessive number of bits */
		if (!r->mbw.min_bw)
			r->mbw.min_bw = 1;

		/*
		 * because its linear with no offset, the granule is the same
		 * as the smallest value
		 * james said because its linear with no offset, the granule is the same
		 * as the smallest value. It is a little fuzzy here because a granularity
		 * of 1 would appear too fine to make percentage conversions.
		 */
		r->mbw.bw_gran = r->mbw.min_bw;
		r->mbw.bw_gran = GRAN_MBA_BW;

		/* We will only pick a class that can monitor and control */
		r->alloc_capable = true;
@@ -392,8 +400,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
		r->mon_capable = true;
		r->mon_enabled = true;
		/* Export memory bandwidth hardlimit, default active hardlimit */
		rr->extend_ctrls_wd[SCHEMA_HDL] = 2;
		r->default_ctrl[SCHEMA_HDL] = 1;
		rr->ctrl_features[SCHEMA_HDL].default_ctrl = 1;
		rr->ctrl_features[SCHEMA_HDL].max_wd = 2;
		rr->ctrl_features[SCHEMA_HDL].capable = true;
	} else if (class == mpam_resctrl_exports[RDT_RESOURCE_L3].class) {
		r->rid = RDT_RESOURCE_L3;
		rr = mpam_get_raw_resctrl_resource(RDT_RESOURCE_L3);
@@ -402,22 +411,40 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
		r->fflags = RFTYPE_RES_CACHE;
		r->name = "L3";

		if (mpam_has_feature(mpam_feat_cpor_part, class->features)) {
			r->cache.cbm_len = class->cpbm_wd;
		r->default_ctrl[SCHEMA_COMM] = GENMASK(class->cpbm_wd - 1, 0);
			rr->ctrl_features[SCHEMA_COMM].default_ctrl = GENMASK(class->cpbm_wd - 1, 0);
			rr->ctrl_features[SCHEMA_COMM].max_wd =
				rr->ctrl_features[SCHEMA_COMM].default_ctrl + 1;
			rr->ctrl_features[SCHEMA_COMM].capable = true;
			/*
			 * Which bits are shared with other ...things...
			 * Unknown devices use partid-0 which uses all the bitmap
			 * fields. Until we configured the SMMU and GIC not to do this
			 * 'all the bits' is the correct answer here.
			 */
		r->cache.shareable_bits = r->default_ctrl[SCHEMA_COMM];
			r->cache.shareable_bits = rr->ctrl_features[SCHEMA_COMM].default_ctrl;
			r->cache.min_cbm_bits = 1;
		}

		if (mpam_has_feature(mpam_feat_cpor_part, class->features)) {
		if (mpam_has_feature(mpam_feat_intpri_part, class->features)) {
			/*
			 * Export internal priority setting, which represents the
			 * max level of control we can export to resctrl. this default
			 * priority is from hardware, no clever here.
			 */
			rr->ctrl_features[SCHEMA_PRI].max_wd = 1 << class->intpri_wd;
			rr->ctrl_features[SCHEMA_PRI].default_ctrl = class->hwdef_intpri;
			rr->ctrl_features[SCHEMA_PRI].capable = true;
		}
		/*
		 * Only this resource is allocable can it be picked from
		 * mpam_resctrl_pick_caches(). So directly set following
		 * fields to true.
		 */
		r->alloc_capable = true;
		r->alloc_enabled = true;
		rdt_alloc_capable = true;
		}
		/*
		 * While this is a CPU-interface feature of MPAM, we only tell
		 * resctrl about it for caches, as that seems to be how x86
@@ -435,21 +462,39 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
		r->fflags = RFTYPE_RES_CACHE;
		r->name = "L2";

		if (mpam_has_feature(mpam_feat_cpor_part, class->features)) {
			r->cache.cbm_len = class->cpbm_wd;
		r->default_ctrl[SCHEMA_COMM] = GENMASK(class->cpbm_wd - 1, 0);
			rr->ctrl_features[SCHEMA_COMM].default_ctrl = GENMASK(class->cpbm_wd - 1, 0);
			rr->ctrl_features[SCHEMA_COMM].max_wd =
				rr->ctrl_features[SCHEMA_COMM].default_ctrl + 1;
			rr->ctrl_features[SCHEMA_COMM].capable = true;
			/*
			 * Which bits are shared with other ...things...
			 * Unknown devices use partid-0 which uses all the bitmap
			 * fields. Until we configured the SMMU and GIC not to do this
			 * 'all the bits' is the correct answer here.
			 */
		r->cache.shareable_bits = r->default_ctrl[SCHEMA_COMM];
			r->cache.shareable_bits = rr->ctrl_features[SCHEMA_COMM].default_ctrl;
		}

		if (mpam_has_feature(mpam_feat_cpor_part, class->features)) {
		if (mpam_has_feature(mpam_feat_intpri_part, class->features)) {
			/*
			 * Export internal priority setting, which represents the
			 * max level of control we can export to resctrl. this default
			 * priority is from hardware, no clever here.
			 */
			rr->ctrl_features[SCHEMA_PRI].max_wd = 1 << class->intpri_wd;
			rr->ctrl_features[SCHEMA_PRI].default_ctrl = class->hwdef_intpri;
			rr->ctrl_features[SCHEMA_PRI].capable = true;
		}
		/*
		 * Only this resource is allocable can it be picked from
		 * mpam_resctrl_pick_caches(). So directly set following
		 * fields to true.
		 */
		r->alloc_capable = true;
		r->alloc_enabled = true;
		rdt_alloc_capable = true;
		}

		/*
		 * While this is a CPU-interface feature of MPAM, we only tell
@@ -464,17 +509,6 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
		rr->num_partid = class->num_partid;
		rr->num_intpartid = class->num_intpartid;
		rr->num_pmg = class->num_pmg;

		/*
		 * Export priority setting, extend_ctrls_wd represents the
		 * max level of control we can export. this default priority
		 * is just from hardware, no need to define another default
		 * value.
		 */
		rr->extend_ctrls_wd[SCHEMA_PRI] = 1 << max(class->intpri_wd,
			class->dspri_wd);
		r->default_ctrl[SCHEMA_PRI] = max(class->hwdef_intpri,
			class->hwdef_dspri);
	}

	return 0;
Loading