xref: /linux/fs/resctrl/ctrlmondata.c (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
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_mon_domain *d, 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->d = d;
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_domain_hdr *hdr;
604 	struct rmid_read rr = {0};
605 	struct rdt_mon_domain *d;
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 || WARN_ON_ONCE(hdr->type != RESCTRL_MON_DOMAIN)) {
657 			ret = -ENOENT;
658 			goto out;
659 		}
660 		d = container_of(hdr, struct rdt_mon_domain, hdr);
661 		mon_event_read(&rr, r, d, rdtgrp, &d->hdr.cpu_mask, evtid, false);
662 	}
663 
664 checkresult:
665 
666 	/*
667 	 * -ENOENT is a special case, set only when "mbm_event" counter assignment
668 	 * mode is enabled and no counter has been assigned.
669 	 */
670 	if (rr.err == -EIO)
671 		seq_puts(m, "Error\n");
672 	else if (rr.err == -EINVAL)
673 		seq_puts(m, "Unavailable\n");
674 	else if (rr.err == -ENOENT)
675 		seq_puts(m, "Unassigned\n");
676 	else
677 		seq_printf(m, "%llu\n", rr.val);
678 
679 out:
680 	rdtgroup_kn_unlock(of->kn);
681 	return ret;
682 }
683 
684 int resctrl_io_alloc_show(struct kernfs_open_file *of, struct seq_file *seq, void *v)
685 {
686 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
687 	struct rdt_resource *r = s->res;
688 
689 	mutex_lock(&rdtgroup_mutex);
690 
691 	if (r->cache.io_alloc_capable) {
692 		if (resctrl_arch_get_io_alloc_enabled(r))
693 			seq_puts(seq, "enabled\n");
694 		else
695 			seq_puts(seq, "disabled\n");
696 	} else {
697 		seq_puts(seq, "not supported\n");
698 	}
699 
700 	mutex_unlock(&rdtgroup_mutex);
701 
702 	return 0;
703 }
704 
705 /*
706  * resctrl_io_alloc_closid_supported() - io_alloc feature utilizes the
707  * highest CLOSID value to direct I/O traffic. Ensure that io_alloc_closid
708  * is in the supported range.
709  */
710 static bool resctrl_io_alloc_closid_supported(u32 io_alloc_closid)
711 {
712 	return io_alloc_closid < closids_supported();
713 }
714 
715 /*
716  * Initialize io_alloc CLOSID cache resource CBM with all usable (shared
717  * and unused) cache portions.
718  */
719 static int resctrl_io_alloc_init_cbm(struct resctrl_schema *s, u32 closid)
720 {
721 	enum resctrl_conf_type peer_type;
722 	struct rdt_resource *r = s->res;
723 	struct rdt_ctrl_domain *d;
724 	int ret;
725 
726 	rdt_staged_configs_clear();
727 
728 	ret = rdtgroup_init_cat(s, closid);
729 	if (ret < 0)
730 		goto out;
731 
732 	/* Keep CDP_CODE and CDP_DATA of io_alloc CLOSID's CBM in sync. */
733 	if (resctrl_arch_get_cdp_enabled(r->rid)) {
734 		peer_type = resctrl_peer_type(s->conf_type);
735 		list_for_each_entry(d, &s->res->ctrl_domains, hdr.list)
736 			memcpy(&d->staged_config[peer_type],
737 			       &d->staged_config[s->conf_type],
738 			       sizeof(d->staged_config[0]));
739 	}
740 
741 	ret = resctrl_arch_update_domains(r, closid);
742 out:
743 	rdt_staged_configs_clear();
744 	return ret;
745 }
746 
747 /*
748  * resctrl_io_alloc_closid() - io_alloc feature routes I/O traffic using
749  * the highest available CLOSID. Retrieve the maximum CLOSID supported by the
750  * resource. Note that if Code Data Prioritization (CDP) is enabled, the number
751  * of available CLOSIDs is reduced by half.
752  */
753 u32 resctrl_io_alloc_closid(struct rdt_resource *r)
754 {
755 	if (resctrl_arch_get_cdp_enabled(r->rid))
756 		return resctrl_arch_get_num_closid(r) / 2  - 1;
757 	else
758 		return resctrl_arch_get_num_closid(r) - 1;
759 }
760 
761 ssize_t resctrl_io_alloc_write(struct kernfs_open_file *of, char *buf,
762 			       size_t nbytes, loff_t off)
763 {
764 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
765 	struct rdt_resource *r = s->res;
766 	char const *grp_name;
767 	u32 io_alloc_closid;
768 	bool enable;
769 	int ret;
770 
771 	ret = kstrtobool(buf, &enable);
772 	if (ret)
773 		return ret;
774 
775 	cpus_read_lock();
776 	mutex_lock(&rdtgroup_mutex);
777 
778 	rdt_last_cmd_clear();
779 
780 	if (!r->cache.io_alloc_capable) {
781 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
782 		ret = -ENODEV;
783 		goto out_unlock;
784 	}
785 
786 	/* If the feature is already up to date, no action is needed. */
787 	if (resctrl_arch_get_io_alloc_enabled(r) == enable)
788 		goto out_unlock;
789 
790 	io_alloc_closid = resctrl_io_alloc_closid(r);
791 	if (!resctrl_io_alloc_closid_supported(io_alloc_closid)) {
792 		rdt_last_cmd_printf("io_alloc CLOSID (ctrl_hw_id) %u is not available\n",
793 				    io_alloc_closid);
794 		ret = -EINVAL;
795 		goto out_unlock;
796 	}
797 
798 	if (enable) {
799 		if (!closid_alloc_fixed(io_alloc_closid)) {
800 			grp_name = rdtgroup_name_by_closid(io_alloc_closid);
801 			WARN_ON_ONCE(!grp_name);
802 			rdt_last_cmd_printf("CLOSID (ctrl_hw_id) %u for io_alloc is used by %s group\n",
803 					    io_alloc_closid, grp_name ? grp_name : "another");
804 			ret = -ENOSPC;
805 			goto out_unlock;
806 		}
807 
808 		ret = resctrl_io_alloc_init_cbm(s, io_alloc_closid);
809 		if (ret) {
810 			rdt_last_cmd_puts("Failed to initialize io_alloc allocations\n");
811 			closid_free(io_alloc_closid);
812 			goto out_unlock;
813 		}
814 	} else {
815 		closid_free(io_alloc_closid);
816 	}
817 
818 	ret = resctrl_arch_io_alloc_enable(r, enable);
819 	if (enable && ret) {
820 		rdt_last_cmd_puts("Failed to enable io_alloc feature\n");
821 		closid_free(io_alloc_closid);
822 	}
823 
824 out_unlock:
825 	mutex_unlock(&rdtgroup_mutex);
826 	cpus_read_unlock();
827 
828 	return ret ?: nbytes;
829 }
830 
831 int resctrl_io_alloc_cbm_show(struct kernfs_open_file *of, struct seq_file *seq, void *v)
832 {
833 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
834 	struct rdt_resource *r = s->res;
835 	int ret = 0;
836 
837 	cpus_read_lock();
838 	mutex_lock(&rdtgroup_mutex);
839 
840 	rdt_last_cmd_clear();
841 
842 	if (!r->cache.io_alloc_capable) {
843 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
844 		ret = -ENODEV;
845 		goto out_unlock;
846 	}
847 
848 	if (!resctrl_arch_get_io_alloc_enabled(r)) {
849 		rdt_last_cmd_printf("io_alloc is not enabled on %s\n", s->name);
850 		ret = -EINVAL;
851 		goto out_unlock;
852 	}
853 
854 	/*
855 	 * When CDP is enabled, the CBMs of the highest CLOSID of CDP_CODE and
856 	 * CDP_DATA are kept in sync. As a result, the io_alloc CBMs shown for
857 	 * either CDP resource are identical and accurately represent the CBMs
858 	 * used for I/O.
859 	 */
860 	show_doms(seq, s, NULL, resctrl_io_alloc_closid(r));
861 
862 out_unlock:
863 	mutex_unlock(&rdtgroup_mutex);
864 	cpus_read_unlock();
865 	return ret;
866 }
867 
868 static int resctrl_io_alloc_parse_line(char *line,  struct rdt_resource *r,
869 				       struct resctrl_schema *s, u32 closid)
870 {
871 	enum resctrl_conf_type peer_type;
872 	struct rdt_parse_data data;
873 	struct rdt_ctrl_domain *d;
874 	char *dom = NULL, *id;
875 	unsigned long dom_id;
876 
877 next:
878 	if (!line || line[0] == '\0')
879 		return 0;
880 
881 	dom = strsep(&line, ";");
882 	id = strsep(&dom, "=");
883 	if (!dom || kstrtoul(id, 10, &dom_id)) {
884 		rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
885 		return -EINVAL;
886 	}
887 
888 	dom = strim(dom);
889 	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
890 		if (d->hdr.id == dom_id) {
891 			data.buf = dom;
892 			data.mode = RDT_MODE_SHAREABLE;
893 			data.closid = closid;
894 			if (parse_cbm(&data, s, d))
895 				return -EINVAL;
896 			/*
897 			 * Keep io_alloc CLOSID's CBM of CDP_CODE and CDP_DATA
898 			 * in sync.
899 			 */
900 			if (resctrl_arch_get_cdp_enabled(r->rid)) {
901 				peer_type = resctrl_peer_type(s->conf_type);
902 				memcpy(&d->staged_config[peer_type],
903 				       &d->staged_config[s->conf_type],
904 				       sizeof(d->staged_config[0]));
905 			}
906 			goto next;
907 		}
908 	}
909 
910 	return -EINVAL;
911 }
912 
913 ssize_t resctrl_io_alloc_cbm_write(struct kernfs_open_file *of, char *buf,
914 				   size_t nbytes, loff_t off)
915 {
916 	struct resctrl_schema *s = rdt_kn_parent_priv(of->kn);
917 	struct rdt_resource *r = s->res;
918 	u32 io_alloc_closid;
919 	int ret = 0;
920 
921 	/* Valid input requires a trailing newline */
922 	if (nbytes == 0 || buf[nbytes - 1] != '\n')
923 		return -EINVAL;
924 
925 	buf[nbytes - 1] = '\0';
926 
927 	cpus_read_lock();
928 	mutex_lock(&rdtgroup_mutex);
929 	rdt_last_cmd_clear();
930 
931 	if (!r->cache.io_alloc_capable) {
932 		rdt_last_cmd_printf("io_alloc is not supported on %s\n", s->name);
933 		ret = -ENODEV;
934 		goto out_unlock;
935 	}
936 
937 	if (!resctrl_arch_get_io_alloc_enabled(r)) {
938 		rdt_last_cmd_printf("io_alloc is not enabled on %s\n", s->name);
939 		ret = -EINVAL;
940 		goto out_unlock;
941 	}
942 
943 	io_alloc_closid = resctrl_io_alloc_closid(r);
944 
945 	rdt_staged_configs_clear();
946 	ret = resctrl_io_alloc_parse_line(buf, r, s, io_alloc_closid);
947 	if (ret)
948 		goto out_clear_configs;
949 
950 	ret = resctrl_arch_update_domains(r, io_alloc_closid);
951 
952 out_clear_configs:
953 	rdt_staged_configs_clear();
954 out_unlock:
955 	mutex_unlock(&rdtgroup_mutex);
956 	cpus_read_unlock();
957 
958 	return ret ?: nbytes;
959 }
960