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