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