xref: /linux/fs/resctrl/ctrlmondata.c (revision 4bc3ef46ff41d5e7ba557e56e9cd2031527cd7f8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Resource Director Technology(RDT)
4  * - Cache Allocation code.
5  *
6  * Copyright (C) 2016 Intel Corporation
7  *
8  * Authors:
9  *    Fenghua Yu <fenghua.yu@intel.com>
10  *    Tony Luck <tony.luck@intel.com>
11  *
12  * More information about RDT be found in the Intel (R) x86 Architecture
13  * Software Developer Manual June 2016, volume 3, section 17.17.
14  */
15 
16 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
17 
18 #include <linux/cpu.h>
19 #include <linux/kernfs.h>
20 #include <linux/seq_file.h>
21 #include <linux/slab.h>
22 #include <linux/tick.h>
23 
24 #include "internal.h"
25 
26 struct rdt_parse_data {
27 	u32			closid;
28 	enum rdtgrp_mode	mode;
29 	char			*buf;
30 };
31 
32 typedef int (ctrlval_parser_t)(struct rdt_parse_data *data,
33 			       struct resctrl_schema *s,
34 			       struct rdt_ctrl_domain *d);
35 
36 /*
37  * Check whether MBA bandwidth percentage value is correct. The value is
38  * checked against the minimum and max bandwidth values specified by the
39  * hardware. The allocated bandwidth percentage is rounded to the next
40  * control step available on the hardware.
41  */
42 static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r)
43 {
44 	int ret;
45 	u32 bw;
46 
47 	/*
48 	 * Only linear delay values is supported for current Intel SKUs.
49 	 */
50 	if (!r->membw.delay_linear && r->membw.arch_needs_linear) {
51 		rdt_last_cmd_puts("No support for non-linear MB domains\n");
52 		return false;
53 	}
54 
55 	ret = kstrtou32(buf, 10, &bw);
56 	if (ret) {
57 		rdt_last_cmd_printf("Invalid MB value %s\n", buf);
58 		return false;
59 	}
60 
61 	/* Nothing else to do if software controller is enabled. */
62 	if (is_mba_sc(r)) {
63 		*data = bw;
64 		return true;
65 	}
66 
67 	if (bw < r->membw.min_bw || bw > r->membw.max_bw) {
68 		rdt_last_cmd_printf("MB value %u out of range [%d,%d]\n",
69 				    bw, r->membw.min_bw, r->membw.max_bw);
70 		return false;
71 	}
72 
73 	*data = roundup(bw, (unsigned long)r->membw.bw_gran);
74 	return true;
75 }
76 
77 static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
78 		    struct rdt_ctrl_domain *d)
79 {
80 	struct resctrl_staged_config *cfg;
81 	struct rdt_resource *r = s->res;
82 	u32 closid = data->closid;
83 	u32 bw_val;
84 
85 	cfg = &d->staged_config[s->conf_type];
86 	if (cfg->have_new_ctrl) {
87 		rdt_last_cmd_printf("Duplicate domain %d\n", d->hdr.id);
88 		return -EINVAL;
89 	}
90 
91 	if (!bw_validate(data->buf, &bw_val, r))
92 		return -EINVAL;
93 
94 	if (is_mba_sc(r)) {
95 		d->mbps_val[closid] = bw_val;
96 		return 0;
97 	}
98 
99 	cfg->new_ctrl = bw_val;
100 	cfg->have_new_ctrl = true;
101 
102 	return 0;
103 }
104 
105 /*
106  * Check whether a cache bit mask is valid.
107  * On Intel CPUs, non-contiguous 1s value support is indicated by CPUID:
108  *   - CPUID.0x10.1:ECX[3]: L3 non-contiguous 1s value supported if 1
109  *   - CPUID.0x10.2:ECX[3]: L2 non-contiguous 1s value supported if 1
110  *
111  * Haswell does not support a non-contiguous 1s value and additionally
112  * requires at least two bits set.
113  * AMD allows non-contiguous bitmasks.
114  */
115 static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
116 {
117 	u32 supported_bits = BIT_MASK(r->cache.cbm_len) - 1;
118 	unsigned int cbm_len = r->cache.cbm_len;
119 	unsigned long first_bit, zero_bit, val;
120 	int ret;
121 
122 	ret = kstrtoul(buf, 16, &val);
123 	if (ret) {
124 		rdt_last_cmd_printf("Non-hex character in the mask %s\n", buf);
125 		return false;
126 	}
127 
128 	if ((r->cache.min_cbm_bits > 0 && val == 0) || val > supported_bits) {
129 		rdt_last_cmd_puts("Mask out of range\n");
130 		return false;
131 	}
132 
133 	first_bit = find_first_bit(&val, cbm_len);
134 	zero_bit = find_next_zero_bit(&val, cbm_len, first_bit);
135 
136 	/* Are non-contiguous bitmasks allowed? */
137 	if (!r->cache.arch_has_sparse_bitmasks &&
138 	    (find_next_bit(&val, cbm_len, zero_bit) < cbm_len)) {
139 		rdt_last_cmd_printf("The mask %lx has non-consecutive 1-bits\n", val);
140 		return false;
141 	}
142 
143 	if ((zero_bit - first_bit) < r->cache.min_cbm_bits) {
144 		rdt_last_cmd_printf("Need at least %d bits in the mask\n",
145 				    r->cache.min_cbm_bits);
146 		return false;
147 	}
148 
149 	*data = val;
150 	return true;
151 }
152 
153 /*
154  * Read one cache bit mask (hex). Check that it is valid for the current
155  * resource type.
156  */
157 static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
158 		     struct rdt_ctrl_domain *d)
159 {
160 	enum rdtgrp_mode mode = data->mode;
161 	struct resctrl_staged_config *cfg;
162 	struct rdt_resource *r = s->res;
163 	u32 closid = data->closid;
164 	u32 cbm_val;
165 
166 	cfg = &d->staged_config[s->conf_type];
167 	if (cfg->have_new_ctrl) {
168 		rdt_last_cmd_printf("Duplicate domain %d\n", d->hdr.id);
169 		return -EINVAL;
170 	}
171 
172 	/*
173 	 * Cannot set up more than one pseudo-locked region in a cache
174 	 * hierarchy.
175 	 */
176 	if (mode == RDT_MODE_PSEUDO_LOCKSETUP &&
177 	    rdtgroup_pseudo_locked_in_hierarchy(d)) {
178 		rdt_last_cmd_puts("Pseudo-locked region in hierarchy\n");
179 		return -EINVAL;
180 	}
181 
182 	if (!cbm_validate(data->buf, &cbm_val, r))
183 		return -EINVAL;
184 
185 	if ((mode == RDT_MODE_EXCLUSIVE || mode == RDT_MODE_SHAREABLE) &&
186 	    rdtgroup_cbm_overlaps_pseudo_locked(d, cbm_val)) {
187 		rdt_last_cmd_puts("CBM overlaps with pseudo-locked region\n");
188 		return -EINVAL;
189 	}
190 
191 	/*
192 	 * The CBM may not overlap with the CBM of another closid if
193 	 * either is exclusive.
194 	 */
195 	if (rdtgroup_cbm_overlaps(s, d, cbm_val, closid, true)) {
196 		rdt_last_cmd_puts("Overlaps with exclusive group\n");
197 		return -EINVAL;
198 	}
199 
200 	if (rdtgroup_cbm_overlaps(s, d, cbm_val, closid, false)) {
201 		if (mode == RDT_MODE_EXCLUSIVE ||
202 		    mode == RDT_MODE_PSEUDO_LOCKSETUP) {
203 			rdt_last_cmd_puts("Overlaps with other group\n");
204 			return -EINVAL;
205 		}
206 	}
207 
208 	cfg->new_ctrl = cbm_val;
209 	cfg->have_new_ctrl = true;
210 
211 	return 0;
212 }
213 
214 /*
215  * For each domain in this resource we expect to find a series of:
216  *	id=mask
217  * separated by ";". The "id" is in decimal, and must match one of
218  * the "id"s for this resource.
219  */
220 static int parse_line(char *line, struct resctrl_schema *s,
221 		      struct rdtgroup *rdtgrp)
222 {
223 	enum resctrl_conf_type t = s->conf_type;
224 	ctrlval_parser_t *parse_ctrlval = NULL;
225 	struct resctrl_staged_config *cfg;
226 	struct rdt_resource *r = s->res;
227 	struct rdt_parse_data data;
228 	struct rdt_ctrl_domain *d;
229 	char *dom = NULL, *id;
230 	unsigned long dom_id;
231 
232 	/* Walking r->domains, ensure it can't race with cpuhp */
233 	lockdep_assert_cpus_held();
234 
235 	switch (r->schema_fmt) {
236 	case RESCTRL_SCHEMA_BITMAP:
237 		parse_ctrlval = &parse_cbm;
238 		break;
239 	case RESCTRL_SCHEMA_RANGE:
240 		parse_ctrlval = &parse_bw;
241 		break;
242 	}
243 
244 	if (WARN_ON_ONCE(!parse_ctrlval))
245 		return -EINVAL;
246 
247 	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP &&
248 	    (r->rid == RDT_RESOURCE_MBA || r->rid == RDT_RESOURCE_SMBA)) {
249 		rdt_last_cmd_puts("Cannot pseudo-lock MBA resource\n");
250 		return -EINVAL;
251 	}
252 
253 next:
254 	if (!line || line[0] == '\0')
255 		return 0;
256 	dom = strsep(&line, ";");
257 	id = strsep(&dom, "=");
258 	if (!dom || kstrtoul(id, 10, &dom_id)) {
259 		rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
260 		return -EINVAL;
261 	}
262 	dom = strim(dom);
263 	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
264 		if (d->hdr.id == dom_id) {
265 			data.buf = dom;
266 			data.closid = rdtgrp->closid;
267 			data.mode = rdtgrp->mode;
268 			if (parse_ctrlval(&data, s, d))
269 				return -EINVAL;
270 			if (rdtgrp->mode ==  RDT_MODE_PSEUDO_LOCKSETUP) {
271 				cfg = &d->staged_config[t];
272 				/*
273 				 * In pseudo-locking setup mode and just
274 				 * parsed a valid CBM that should be
275 				 * pseudo-locked. Only one locked region per
276 				 * resource group and domain so just do
277 				 * the required initialization for single
278 				 * region and return.
279 				 */
280 				rdtgrp->plr->s = s;
281 				rdtgrp->plr->d = d;
282 				rdtgrp->plr->cbm = cfg->new_ctrl;
283 				d->plr = rdtgrp->plr;
284 				return 0;
285 			}
286 			goto next;
287 		}
288 	}
289 	return -EINVAL;
290 }
291 
292 static int rdtgroup_parse_resource(char *resname, char *tok,
293 				   struct rdtgroup *rdtgrp)
294 {
295 	struct resctrl_schema *s;
296 
297 	list_for_each_entry(s, &resctrl_schema_all, list) {
298 		if (!strcmp(resname, s->name) && rdtgrp->closid < s->num_closid)
299 			return parse_line(tok, s, rdtgrp);
300 	}
301 	rdt_last_cmd_printf("Unknown or unsupported resource name '%s'\n", resname);
302 	return -EINVAL;
303 }
304 
305 ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
306 				char *buf, size_t nbytes, loff_t off)
307 {
308 	struct resctrl_schema *s;
309 	struct rdtgroup *rdtgrp;
310 	struct rdt_resource *r;
311 	char *tok, *resname;
312 	int ret = 0;
313 
314 	/* Valid input requires a trailing newline */
315 	if (nbytes == 0 || buf[nbytes - 1] != '\n')
316 		return -EINVAL;
317 	buf[nbytes - 1] = '\0';
318 
319 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
320 	if (!rdtgrp) {
321 		rdtgroup_kn_unlock(of->kn);
322 		return -ENOENT;
323 	}
324 	rdt_last_cmd_clear();
325 
326 	/*
327 	 * No changes to pseudo-locked region allowed. It has to be removed
328 	 * and re-created instead.
329 	 */
330 	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
331 		ret = -EINVAL;
332 		rdt_last_cmd_puts("Resource group is pseudo-locked\n");
333 		goto out;
334 	}
335 
336 	rdt_staged_configs_clear();
337 
338 	while ((tok = strsep(&buf, "\n")) != NULL) {
339 		resname = strim(strsep(&tok, ":"));
340 		if (!tok) {
341 			rdt_last_cmd_puts("Missing ':'\n");
342 			ret = -EINVAL;
343 			goto out;
344 		}
345 		if (tok[0] == '\0') {
346 			rdt_last_cmd_printf("Missing '%s' value\n", resname);
347 			ret = -EINVAL;
348 			goto out;
349 		}
350 		ret = rdtgroup_parse_resource(resname, tok, rdtgrp);
351 		if (ret)
352 			goto out;
353 	}
354 
355 	list_for_each_entry(s, &resctrl_schema_all, list) {
356 		r = s->res;
357 
358 		/*
359 		 * Writes to mba_sc resources update the software controller,
360 		 * not the control MSR.
361 		 */
362 		if (is_mba_sc(r))
363 			continue;
364 
365 		ret = resctrl_arch_update_domains(r, rdtgrp->closid);
366 		if (ret)
367 			goto out;
368 	}
369 
370 	if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
371 		/*
372 		 * If pseudo-locking fails we keep the resource group in
373 		 * mode RDT_MODE_PSEUDO_LOCKSETUP with its class of service
374 		 * active and updated for just the domain the pseudo-locked
375 		 * region was requested for.
376 		 */
377 		ret = rdtgroup_pseudo_lock_create(rdtgrp);
378 	}
379 
380 out:
381 	rdt_staged_configs_clear();
382 	rdtgroup_kn_unlock(of->kn);
383 	return ret ?: nbytes;
384 }
385 
386 static void show_doms(struct seq_file *s, struct resctrl_schema *schema,
387 		      char *resource_name, int closid)
388 {
389 	struct rdt_resource *r = schema->res;
390 	struct rdt_ctrl_domain *dom;
391 	bool sep = false;
392 	u32 ctrl_val;
393 
394 	/* Walking r->domains, ensure it can't race with cpuhp */
395 	lockdep_assert_cpus_held();
396 
397 	if (resource_name)
398 		seq_printf(s, "%*s:", max_name_width, resource_name);
399 	list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
400 		if (sep)
401 			seq_puts(s, ";");
402 
403 		if (is_mba_sc(r))
404 			ctrl_val = dom->mbps_val[closid];
405 		else
406 			ctrl_val = resctrl_arch_get_config(r, dom, closid,
407 							   schema->conf_type);
408 
409 		seq_printf(s, schema->fmt_str, dom->hdr.id, ctrl_val);
410 		sep = true;
411 	}
412 	seq_puts(s, "\n");
413 }
414 
415 int rdtgroup_schemata_show(struct kernfs_open_file *of,
416 			   struct seq_file *s, void *v)
417 {
418 	struct resctrl_schema *schema;
419 	struct rdtgroup *rdtgrp;
420 	int ret = 0;
421 	u32 closid;
422 
423 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
424 	if (rdtgrp) {
425 		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
426 			list_for_each_entry(schema, &resctrl_schema_all, list) {
427 				seq_printf(s, "%s:uninitialized\n", schema->name);
428 			}
429 		} else if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
430 			if (!rdtgrp->plr->d) {
431 				rdt_last_cmd_clear();
432 				rdt_last_cmd_puts("Cache domain offline\n");
433 				ret = -ENODEV;
434 			} else {
435 				seq_printf(s, "%s:%d=%x\n",
436 					   rdtgrp->plr->s->res->name,
437 					   rdtgrp->plr->d->hdr.id,
438 					   rdtgrp->plr->cbm);
439 			}
440 		} else {
441 			closid = rdtgrp->closid;
442 			list_for_each_entry(schema, &resctrl_schema_all, list) {
443 				if (closid < schema->num_closid)
444 					show_doms(s, schema, schema->name, closid);
445 			}
446 		}
447 	} else {
448 		ret = -ENOENT;
449 	}
450 	rdtgroup_kn_unlock(of->kn);
451 	return ret;
452 }
453 
454 static int smp_mon_event_count(void *arg)
455 {
456 	mon_event_count(arg);
457 
458 	return 0;
459 }
460 
461 ssize_t rdtgroup_mba_mbps_event_write(struct kernfs_open_file *of,
462 				      char *buf, size_t nbytes, loff_t off)
463 {
464 	struct rdtgroup *rdtgrp;
465 	int ret = 0;
466 
467 	/* Valid input requires a trailing newline */
468 	if (nbytes == 0 || buf[nbytes - 1] != '\n')
469 		return -EINVAL;
470 	buf[nbytes - 1] = '\0';
471 
472 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
473 	if (!rdtgrp) {
474 		rdtgroup_kn_unlock(of->kn);
475 		return -ENOENT;
476 	}
477 	rdt_last_cmd_clear();
478 
479 	if (!strcmp(buf, "mbm_local_bytes")) {
480 		if (resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID))
481 			rdtgrp->mba_mbps_event = QOS_L3_MBM_LOCAL_EVENT_ID;
482 		else
483 			ret = -EINVAL;
484 	} else if (!strcmp(buf, "mbm_total_bytes")) {
485 		if (resctrl_is_mon_event_enabled(QOS_L3_MBM_TOTAL_EVENT_ID))
486 			rdtgrp->mba_mbps_event = QOS_L3_MBM_TOTAL_EVENT_ID;
487 		else
488 			ret = -EINVAL;
489 	} else {
490 		ret = -EINVAL;
491 	}
492 
493 	if (ret)
494 		rdt_last_cmd_printf("Unsupported event id '%s'\n", buf);
495 
496 	rdtgroup_kn_unlock(of->kn);
497 
498 	return ret ?: nbytes;
499 }
500 
501 int rdtgroup_mba_mbps_event_show(struct kernfs_open_file *of,
502 				 struct seq_file *s, void *v)
503 {
504 	struct rdtgroup *rdtgrp;
505 	int ret = 0;
506 
507 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
508 
509 	if (rdtgrp) {
510 		switch (rdtgrp->mba_mbps_event) {
511 		case QOS_L3_MBM_LOCAL_EVENT_ID:
512 			seq_puts(s, "mbm_local_bytes\n");
513 			break;
514 		case QOS_L3_MBM_TOTAL_EVENT_ID:
515 			seq_puts(s, "mbm_total_bytes\n");
516 			break;
517 		default:
518 			pr_warn_once("Bad event %d\n", rdtgrp->mba_mbps_event);
519 			ret = -EINVAL;
520 			break;
521 		}
522 	} else {
523 		ret = -ENOENT;
524 	}
525 
526 	rdtgroup_kn_unlock(of->kn);
527 
528 	return ret;
529 }
530 
531 struct rdt_domain_hdr *resctrl_find_domain(struct list_head *h, int id,
532 					   struct list_head **pos)
533 {
534 	struct rdt_domain_hdr *d;
535 	struct list_head *l;
536 
537 	list_for_each(l, h) {
538 		d = list_entry(l, struct rdt_domain_hdr, list);
539 		/* When id is found, return its domain. */
540 		if (id == d->id)
541 			return d;
542 		/* Stop searching when finding id's position in sorted list. */
543 		if (id < d->id)
544 			break;
545 	}
546 
547 	if (pos)
548 		*pos = l;
549 
550 	return NULL;
551 }
552 
553 void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
554 		    struct rdt_domain_hdr *hdr, struct rdtgroup *rdtgrp,
555 		    cpumask_t *cpumask, int evtid, int first)
556 {
557 	int cpu;
558 
559 	/* When picking a CPU from cpu_mask, ensure it can't race with cpuhp */
560 	lockdep_assert_cpus_held();
561 
562 	/*
563 	 * Setup the parameters to pass to mon_event_count() to read the data.
564 	 */
565 	rr->rgrp = rdtgrp;
566 	rr->evtid = evtid;
567 	rr->r = r;
568 	rr->hdr = hdr;
569 	rr->first = first;
570 	if (resctrl_arch_mbm_cntr_assign_enabled(r) &&
571 	    resctrl_is_mbm_event(evtid)) {
572 		rr->is_mbm_cntr = true;
573 	} else {
574 		rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evtid);
575 		if (IS_ERR(rr->arch_mon_ctx)) {
576 			rr->err = -EINVAL;
577 			return;
578 		}
579 	}
580 
581 	cpu = cpumask_any_housekeeping(cpumask, RESCTRL_PICK_ANY_CPU);
582 
583 	/*
584 	 * cpumask_any_housekeeping() prefers housekeeping CPUs, but
585 	 * are all the CPUs nohz_full? If yes, pick a CPU to IPI.
586 	 * MPAM's resctrl_arch_rmid_read() is unable to read the
587 	 * counters on some platforms if its called in IRQ context.
588 	 */
589 	if (tick_nohz_full_cpu(cpu))
590 		smp_call_function_any(cpumask, mon_event_count, rr, 1);
591 	else
592 		smp_call_on_cpu(cpu, smp_mon_event_count, rr, false);
593 
594 	if (rr->arch_mon_ctx)
595 		resctrl_arch_mon_ctx_free(r, evtid, rr->arch_mon_ctx);
596 }
597 
598 int rdtgroup_mondata_show(struct seq_file *m, void *arg)
599 {
600 	struct kernfs_open_file *of = m->private;
601 	enum resctrl_res_level resid;
602 	enum resctrl_event_id evtid;
603 	struct rdt_l3_mon_domain *d;
604 	struct rdt_domain_hdr *hdr;
605 	struct rmid_read rr = {0};
606 	struct rdtgroup *rdtgrp;
607 	int domid, cpu, ret = 0;
608 	struct rdt_resource *r;
609 	struct cacheinfo *ci;
610 	struct mon_data *md;
611 
612 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
613 	if (!rdtgrp) {
614 		ret = -ENOENT;
615 		goto out;
616 	}
617 
618 	md = of->kn->priv;
619 	if (WARN_ON_ONCE(!md)) {
620 		ret = -EIO;
621 		goto out;
622 	}
623 
624 	resid = md->rid;
625 	domid = md->domid;
626 	evtid = md->evtid;
627 	r = resctrl_arch_get_resource(resid);
628 
629 	if (md->sum) {
630 		/*
631 		 * This file requires summing across all domains that share
632 		 * the L3 cache id that was provided in the "domid" field of the
633 		 * struct mon_data. Search all domains in the resource for
634 		 * one that matches this cache id.
635 		 */
636 		list_for_each_entry(d, &r->mon_domains, hdr.list) {
637 			if (d->ci_id == domid) {
638 				cpu = cpumask_any(&d->hdr.cpu_mask);
639 				ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE);
640 				if (!ci)
641 					continue;
642 				rr.ci = ci;
643 				mon_event_read(&rr, r, NULL, rdtgrp,
644 					       &ci->shared_cpu_map, evtid, false);
645 				goto checkresult;
646 			}
647 		}
648 		ret = -ENOENT;
649 		goto out;
650 	} else {
651 		/*
652 		 * This file provides data from a single domain. Search
653 		 * the resource to find the domain with "domid".
654 		 */
655 		hdr = resctrl_find_domain(&r->mon_domains, domid, NULL);
656 		if (!hdr) {
657 			ret = -ENOENT;
658 			goto out;
659 		}
660 		mon_event_read(&rr, r, hdr, rdtgrp, &hdr->cpu_mask, evtid, false);
661 	}
662 
663 checkresult:
664 
665 	/*
666 	 * -ENOENT is a special case, set only when "mbm_event" counter assignment
667 	 * mode is enabled and no counter has been assigned.
668 	 */
669 	if (rr.err == -EIO)
670 		seq_puts(m, "Error\n");
671 	else if (rr.err == -EINVAL)
672 		seq_puts(m, "Unavailable\n");
673 	else if (rr.err == -ENOENT)
674 		seq_puts(m, "Unassigned\n");
675 	else
676 		seq_printf(m, "%llu\n", rr.val);
677 
678 out:
679 	rdtgroup_kn_unlock(of->kn);
680 	return ret;
681 }
682 
683 int resctrl_io_alloc_show(struct kernfs_open_file *of, struct seq_file *seq, void *v)
684 {
685 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
686 	struct rdt_resource *r = s->res;
687 
688 	mutex_lock(&rdtgroup_mutex);
689 
690 	if (r->cache.io_alloc_capable) {
691 		if (resctrl_arch_get_io_alloc_enabled(r))
692 			seq_puts(seq, "enabled\n");
693 		else
694 			seq_puts(seq, "disabled\n");
695 	} else {
696 		seq_puts(seq, "not supported\n");
697 	}
698 
699 	mutex_unlock(&rdtgroup_mutex);
700 
701 	return 0;
702 }
703 
704 /*
705  * resctrl_io_alloc_closid_supported() - io_alloc feature utilizes the
706  * highest CLOSID value to direct I/O traffic. Ensure that io_alloc_closid
707  * is in the supported range.
708  */
709 static bool resctrl_io_alloc_closid_supported(u32 io_alloc_closid)
710 {
711 	return io_alloc_closid < closids_supported();
712 }
713 
714 /*
715  * Initialize io_alloc CLOSID cache resource CBM with all usable (shared
716  * and unused) cache portions.
717  */
718 static int resctrl_io_alloc_init_cbm(struct resctrl_schema *s, u32 closid)
719 {
720 	enum resctrl_conf_type peer_type;
721 	struct rdt_resource *r = s->res;
722 	struct rdt_ctrl_domain *d;
723 	int ret;
724 
725 	rdt_staged_configs_clear();
726 
727 	ret = rdtgroup_init_cat(s, closid);
728 	if (ret < 0)
729 		goto out;
730 
731 	/* Keep CDP_CODE and CDP_DATA of io_alloc CLOSID's CBM in sync. */
732 	if (resctrl_arch_get_cdp_enabled(r->rid)) {
733 		peer_type = resctrl_peer_type(s->conf_type);
734 		list_for_each_entry(d, &s->res->ctrl_domains, hdr.list)
735 			memcpy(&d->staged_config[peer_type],
736 			       &d->staged_config[s->conf_type],
737 			       sizeof(d->staged_config[0]));
738 	}
739 
740 	ret = resctrl_arch_update_domains(r, closid);
741 out:
742 	rdt_staged_configs_clear();
743 	return ret;
744 }
745 
746 /*
747  * resctrl_io_alloc_closid() - io_alloc feature routes I/O traffic using
748  * the highest available CLOSID. Retrieve the maximum CLOSID supported by the
749  * resource. Note that if Code Data Prioritization (CDP) is enabled, the number
750  * of available CLOSIDs is reduced by half.
751  */
752 u32 resctrl_io_alloc_closid(struct rdt_resource *r)
753 {
754 	if (resctrl_arch_get_cdp_enabled(r->rid))
755 		return resctrl_arch_get_num_closid(r) / 2  - 1;
756 	else
757 		return resctrl_arch_get_num_closid(r) - 1;
758 }
759 
760 ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
761 			       size_t nbytes, loff_t off)
762 {
763 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
764 	struct rdt_resource *r = s->res;
765 	char const *grp_name;
766 	u32 io_alloc_closid;
767 	bool enable;
768 	int ret;
769 
770 	ret = kstrtobool(buf, &enable);
771 	if (ret)
772 		return ret;
773 
774 	cpus_read_lock();
775 	mutex_lock(&rdtgroup_mutex);
776 
777 	rdt_last_cmd_clear();
778 
779 	if (!r->cache.io_alloc_capable) {
780 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
781 		ret = -ENODEV;
782 		goto out_unlock;
783 	}
784 
785 	/* If the feature is already up to date, no action is needed. */
786 	if (resctrl_arch_get_io_alloc_enabled(r) == enable)
787 		goto out_unlock;
788 
789 	io_alloc_closid = resctrl_io_alloc_closid(r);
790 	if (!resctrl_io_alloc_closid_supported(io_alloc_closid)) {
791 		rdt_last_cmd_printf("io_alloc CLOSID (ctrl_hw_id) %u is not available\n",
792 				    io_alloc_closid);
793 		ret = -EINVAL;
794 		goto out_unlock;
795 	}
796 
797 	if (enable) {
798 		if (!closid_alloc_fixed(io_alloc_closid)) {
799 			grp_name = rdtgroup_name_by_closid(io_alloc_closid);
800 			WARN_ON_ONCE(!grp_name);
801 			rdt_last_cmd_printf("CLOSID (ctrl_hw_id) %u for io_alloc is used by %s group\n",
802 					    io_alloc_closid, grp_name ? grp_name : "another");
803 			ret = -ENOSPC;
804 			goto out_unlock;
805 		}
806 
807 		ret = resctrl_io_alloc_init_cbm(s, io_alloc_closid);
808 		if (ret) {
809 			rdt_last_cmd_puts("Failed to initialize io_alloc allocations\n");
810 			closid_free(io_alloc_closid);
811 			goto out_unlock;
812 		}
813 	} else {
814 		closid_free(io_alloc_closid);
815 	}
816 
817 	ret = resctrl_arch_io_alloc_enable(r, enable);
818 	if (enable && ret) {
819 		rdt_last_cmd_puts("Failed to enable io_alloc feature\n");
820 		closid_free(io_alloc_closid);
821 	}
822 
823 out_unlock:
824 	mutex_unlock(&rdtgroup_mutex);
825 	cpus_read_unlock();
826 
827 	return ret ?: nbytes;
828 }
829 
830 int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of, struct seq_file *seq, void *v)
831 {
832 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
833 	struct rdt_resource *r = s->res;
834 	int ret = 0;
835 
836 	cpus_read_lock();
837 	mutex_lock(&rdtgroup_mutex);
838 
839 	rdt_last_cmd_clear();
840 
841 	if (!r->cache.io_alloc_capable) {
842 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
843 		ret = -ENODEV;
844 		goto out_unlock;
845 	}
846 
847 	if (!resctrl_arch_get_io_alloc_enabled(r)) {
848 		rdt_last_cmd_printf("io_alloc is not enabled on %s\n", s->name);
849 		ret = -EINVAL;
850 		goto out_unlock;
851 	}
852 
853 	/*
854 	 * When CDP is enabled, the CBMs of the highest CLOSID of CDP_CODE and
855 	 * CDP_DATA are kept in sync. As a result, the io_alloc CBMs shown for
856 	 * either CDP resource are identical and accurately represent the CBMs
857 	 * used for I/O.
858 	 */
859 	show_doms(seq, s, NULL, resctrl_io_alloc_closid(r));
860 
861 out_unlock:
862 	mutex_unlock(&rdtgroup_mutex);
863 	cpus_read_unlock();
864 	return ret;
865 }
866 
867 static int resctrl_io_alloc_parse_line(char *line,  struct rdt_resource *r,
868 				       struct resctrl_schema *s, u32 closid)
869 {
870 	enum resctrl_conf_type peer_type;
871 	struct rdt_parse_data data;
872 	struct rdt_ctrl_domain *d;
873 	char *dom = NULL, *id;
874 	unsigned long dom_id;
875 
876 next:
877 	if (!line || line[0] == '\0')
878 		return 0;
879 
880 	dom = strsep(&line, ";");
881 	id = strsep(&dom, "=");
882 	if (!dom || kstrtoul(id, 10, &dom_id)) {
883 		rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
884 		return -EINVAL;
885 	}
886 
887 	dom = strim(dom);
888 	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
889 		if (d->hdr.id == dom_id) {
890 			data.buf = dom;
891 			data.mode = RDT_MODE_SHAREABLE;
892 			data.closid = closid;
893 			if (parse_cbm(&data, s, d))
894 				return -EINVAL;
895 			/*
896 			 * Keep io_alloc CLOSID's CBM of CDP_CODE and CDP_DATA
897 			 * in sync.
898 			 */
899 			if (resctrl_arch_get_cdp_enabled(r->rid)) {
900 				peer_type = resctrl_peer_type(s->conf_type);
901 				memcpy(&d->staged_config[peer_type],
902 				       &d->staged_config[s->conf_type],
903 				       sizeof(d->staged_config[0]));
904 			}
905 			goto next;
906 		}
907 	}
908 
909 	return -EINVAL;
910 }
911 
912 ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of, char *buf,
913 				   size_t nbytes, loff_t off)
914 {
915 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
916 	struct rdt_resource *r = s->res;
917 	u32 io_alloc_closid;
918 	int ret = 0;
919 
920 	/* Valid input requires a trailing newline */
921 	if (nbytes == 0 || buf[nbytes - 1] != '\n')
922 		return -EINVAL;
923 
924 	buf[nbytes - 1] = '\0';
925 
926 	cpus_read_lock();
927 	mutex_lock(&rdtgroup_mutex);
928 	rdt_last_cmd_clear();
929 
930 	if (!r->cache.io_alloc_capable) {
931 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
932 		ret = -ENODEV;
933 		goto out_unlock;
934 	}
935 
936 	if (!resctrl_arch_get_io_alloc_enabled(r)) {
937 		rdt_last_cmd_printf("io_alloc is not enabled on %s\n", s->name);
938 		ret = -EINVAL;
939 		goto out_unlock;
940 	}
941 
942 	io_alloc_closid = resctrl_io_alloc_closid(r);
943 
944 	rdt_staged_configs_clear();
945 	ret = resctrl_io_alloc_parse_line(buf, r, s, io_alloc_closid);
946 	if (ret)
947 		goto out_clear_configs;
948 
949 	ret = resctrl_arch_update_domains(r, io_alloc_closid);
950 
951 out_clear_configs:
952 	rdt_staged_configs_clear();
953 out_unlock:
954 	mutex_unlock(&rdtgroup_mutex);
955 	cpus_read_unlock();
956 
957 	return ret ?: nbytes;
958 }
959