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