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 "internal.h" 23 24 /* 25 * Check whether MBA bandwidth percentage value is correct. The value is 26 * checked against the minimum and max bandwidth values specified by the 27 * hardware. The allocated bandwidth percentage is rounded to the next 28 * control step available on the hardware. 29 */ 30 static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r) 31 { 32 int ret; 33 u32 bw; 34 35 /* 36 * Only linear delay values is supported for current Intel SKUs. 37 */ 38 if (!r->membw.delay_linear && r->membw.arch_needs_linear) { 39 rdt_last_cmd_puts("No support for non-linear MB domains\n"); 40 return false; 41 } 42 43 ret = kstrtou32(buf, 10, &bw); 44 if (ret) { 45 rdt_last_cmd_printf("Invalid MB value %s\n", buf); 46 return false; 47 } 48 49 /* Nothing else to do if software controller is enabled. */ 50 if (is_mba_sc(r)) { 51 *data = bw; 52 return true; 53 } 54 55 if (bw < r->membw.min_bw || bw > r->default_ctrl) { 56 rdt_last_cmd_printf("MB value %u out of range [%d,%d]\n", 57 bw, r->membw.min_bw, r->default_ctrl); 58 return false; 59 } 60 61 *data = roundup(bw, (unsigned long)r->membw.bw_gran); 62 return true; 63 } 64 65 int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, 66 struct rdt_domain *d) 67 { 68 struct resctrl_staged_config *cfg; 69 u32 closid = data->rdtgrp->closid; 70 struct rdt_resource *r = s->res; 71 u32 bw_val; 72 73 cfg = &d->staged_config[s->conf_type]; 74 if (cfg->have_new_ctrl) { 75 rdt_last_cmd_printf("Duplicate domain %d\n", d->id); 76 return -EINVAL; 77 } 78 79 if (!bw_validate(data->buf, &bw_val, r)) 80 return -EINVAL; 81 82 if (is_mba_sc(r)) { 83 d->mbps_val[closid] = bw_val; 84 return 0; 85 } 86 87 cfg->new_ctrl = bw_val; 88 cfg->have_new_ctrl = true; 89 90 return 0; 91 } 92 93 /* 94 * Check whether a cache bit mask is valid. 95 * For Intel the SDM says: 96 * Please note that all (and only) contiguous '1' combinations 97 * are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.). 98 * Additionally Haswell requires at least two bits set. 99 * AMD allows non-contiguous bitmasks. 100 */ 101 static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r) 102 { 103 unsigned long first_bit, zero_bit, val; 104 unsigned int cbm_len = r->cache.cbm_len; 105 int ret; 106 107 ret = kstrtoul(buf, 16, &val); 108 if (ret) { 109 rdt_last_cmd_printf("Non-hex character in the mask %s\n", buf); 110 return false; 111 } 112 113 if ((r->cache.min_cbm_bits > 0 && val == 0) || val > r->default_ctrl) { 114 rdt_last_cmd_puts("Mask out of range\n"); 115 return false; 116 } 117 118 first_bit = find_first_bit(&val, cbm_len); 119 zero_bit = find_next_zero_bit(&val, cbm_len, first_bit); 120 121 /* Are non-contiguous bitmaps allowed? */ 122 if (!r->cache.arch_has_sparse_bitmaps && 123 (find_next_bit(&val, cbm_len, zero_bit) < cbm_len)) { 124 rdt_last_cmd_printf("The mask %lx has non-consecutive 1-bits\n", val); 125 return false; 126 } 127 128 if ((zero_bit - first_bit) < r->cache.min_cbm_bits) { 129 rdt_last_cmd_printf("Need at least %d bits in the mask\n", 130 r->cache.min_cbm_bits); 131 return false; 132 } 133 134 *data = val; 135 return true; 136 } 137 138 /* 139 * Read one cache bit mask (hex). Check that it is valid for the current 140 * resource type. 141 */ 142 int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s, 143 struct rdt_domain *d) 144 { 145 struct rdtgroup *rdtgrp = data->rdtgrp; 146 struct resctrl_staged_config *cfg; 147 struct rdt_resource *r = s->res; 148 u32 cbm_val; 149 150 cfg = &d->staged_config[s->conf_type]; 151 if (cfg->have_new_ctrl) { 152 rdt_last_cmd_printf("Duplicate domain %d\n", d->id); 153 return -EINVAL; 154 } 155 156 /* 157 * Cannot set up more than one pseudo-locked region in a cache 158 * hierarchy. 159 */ 160 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP && 161 rdtgroup_pseudo_locked_in_hierarchy(d)) { 162 rdt_last_cmd_puts("Pseudo-locked region in hierarchy\n"); 163 return -EINVAL; 164 } 165 166 if (!cbm_validate(data->buf, &cbm_val, r)) 167 return -EINVAL; 168 169 if ((rdtgrp->mode == RDT_MODE_EXCLUSIVE || 170 rdtgrp->mode == RDT_MODE_SHAREABLE) && 171 rdtgroup_cbm_overlaps_pseudo_locked(d, cbm_val)) { 172 rdt_last_cmd_puts("CBM overlaps with pseudo-locked region\n"); 173 return -EINVAL; 174 } 175 176 /* 177 * The CBM may not overlap with the CBM of another closid if 178 * either is exclusive. 179 */ 180 if (rdtgroup_cbm_overlaps(s, d, cbm_val, rdtgrp->closid, true)) { 181 rdt_last_cmd_puts("Overlaps with exclusive group\n"); 182 return -EINVAL; 183 } 184 185 if (rdtgroup_cbm_overlaps(s, d, cbm_val, rdtgrp->closid, false)) { 186 if (rdtgrp->mode == RDT_MODE_EXCLUSIVE || 187 rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { 188 rdt_last_cmd_puts("Overlaps with other group\n"); 189 return -EINVAL; 190 } 191 } 192 193 cfg->new_ctrl = cbm_val; 194 cfg->have_new_ctrl = true; 195 196 return 0; 197 } 198 199 /* 200 * For each domain in this resource we expect to find a series of: 201 * id=mask 202 * separated by ";". The "id" is in decimal, and must match one of 203 * the "id"s for this resource. 204 */ 205 static int parse_line(char *line, struct resctrl_schema *s, 206 struct rdtgroup *rdtgrp) 207 { 208 enum resctrl_conf_type t = s->conf_type; 209 struct resctrl_staged_config *cfg; 210 struct rdt_resource *r = s->res; 211 struct rdt_parse_data data; 212 char *dom = NULL, *id; 213 struct rdt_domain *d; 214 unsigned long dom_id; 215 216 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP && 217 (r->rid == RDT_RESOURCE_MBA || r->rid == RDT_RESOURCE_SMBA)) { 218 rdt_last_cmd_puts("Cannot pseudo-lock MBA resource\n"); 219 return -EINVAL; 220 } 221 222 next: 223 if (!line || line[0] == '\0') 224 return 0; 225 dom = strsep(&line, ";"); 226 id = strsep(&dom, "="); 227 if (!dom || kstrtoul(id, 10, &dom_id)) { 228 rdt_last_cmd_puts("Missing '=' or non-numeric domain\n"); 229 return -EINVAL; 230 } 231 dom = strim(dom); 232 list_for_each_entry(d, &r->domains, list) { 233 if (d->id == dom_id) { 234 data.buf = dom; 235 data.rdtgrp = rdtgrp; 236 if (r->parse_ctrlval(&data, s, d)) 237 return -EINVAL; 238 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { 239 cfg = &d->staged_config[t]; 240 /* 241 * In pseudo-locking setup mode and just 242 * parsed a valid CBM that should be 243 * pseudo-locked. Only one locked region per 244 * resource group and domain so just do 245 * the required initialization for single 246 * region and return. 247 */ 248 rdtgrp->plr->s = s; 249 rdtgrp->plr->d = d; 250 rdtgrp->plr->cbm = cfg->new_ctrl; 251 d->plr = rdtgrp->plr; 252 return 0; 253 } 254 goto next; 255 } 256 } 257 return -EINVAL; 258 } 259 260 static u32 get_config_index(u32 closid, enum resctrl_conf_type type) 261 { 262 switch (type) { 263 default: 264 case CDP_NONE: 265 return closid; 266 case CDP_CODE: 267 return closid * 2 + 1; 268 case CDP_DATA: 269 return closid * 2; 270 } 271 } 272 273 static bool apply_config(struct rdt_hw_domain *hw_dom, 274 struct resctrl_staged_config *cfg, u32 idx, 275 cpumask_var_t cpu_mask) 276 { 277 struct rdt_domain *dom = &hw_dom->d_resctrl; 278 279 if (cfg->new_ctrl != hw_dom->ctrl_val[idx]) { 280 cpumask_set_cpu(cpumask_any(&dom->cpu_mask), cpu_mask); 281 hw_dom->ctrl_val[idx] = cfg->new_ctrl; 282 283 return true; 284 } 285 286 return false; 287 } 288 289 int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, 290 u32 closid, enum resctrl_conf_type t, u32 cfg_val) 291 { 292 struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); 293 struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d); 294 u32 idx = get_config_index(closid, t); 295 struct msr_param msr_param; 296 297 if (!cpumask_test_cpu(smp_processor_id(), &d->cpu_mask)) 298 return -EINVAL; 299 300 hw_dom->ctrl_val[idx] = cfg_val; 301 302 msr_param.res = r; 303 msr_param.low = idx; 304 msr_param.high = idx + 1; 305 hw_res->msr_update(d, &msr_param, r); 306 307 return 0; 308 } 309 310 int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) 311 { 312 struct resctrl_staged_config *cfg; 313 struct rdt_hw_domain *hw_dom; 314 struct msr_param msr_param; 315 enum resctrl_conf_type t; 316 cpumask_var_t cpu_mask; 317 struct rdt_domain *d; 318 u32 idx; 319 320 if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL)) 321 return -ENOMEM; 322 323 msr_param.res = NULL; 324 list_for_each_entry(d, &r->domains, list) { 325 hw_dom = resctrl_to_arch_dom(d); 326 for (t = 0; t < CDP_NUM_TYPES; t++) { 327 cfg = &hw_dom->d_resctrl.staged_config[t]; 328 if (!cfg->have_new_ctrl) 329 continue; 330 331 idx = get_config_index(closid, t); 332 if (!apply_config(hw_dom, cfg, idx, cpu_mask)) 333 continue; 334 335 if (!msr_param.res) { 336 msr_param.low = idx; 337 msr_param.high = msr_param.low + 1; 338 msr_param.res = r; 339 } else { 340 msr_param.low = min(msr_param.low, idx); 341 msr_param.high = max(msr_param.high, idx + 1); 342 } 343 } 344 } 345 346 if (cpumask_empty(cpu_mask)) 347 goto done; 348 349 /* Update resource control msr on all the CPUs. */ 350 on_each_cpu_mask(cpu_mask, rdt_ctrl_update, &msr_param, 1); 351 352 done: 353 free_cpumask_var(cpu_mask); 354 355 return 0; 356 } 357 358 static int rdtgroup_parse_resource(char *resname, char *tok, 359 struct rdtgroup *rdtgrp) 360 { 361 struct resctrl_schema *s; 362 363 list_for_each_entry(s, &resctrl_schema_all, list) { 364 if (!strcmp(resname, s->name) && rdtgrp->closid < s->num_closid) 365 return parse_line(tok, s, rdtgrp); 366 } 367 rdt_last_cmd_printf("Unknown or unsupported resource name '%s'\n", resname); 368 return -EINVAL; 369 } 370 371 ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, 372 char *buf, size_t nbytes, loff_t off) 373 { 374 struct resctrl_schema *s; 375 struct rdtgroup *rdtgrp; 376 struct rdt_resource *r; 377 char *tok, *resname; 378 int ret = 0; 379 380 /* Valid input requires a trailing newline */ 381 if (nbytes == 0 || buf[nbytes - 1] != '\n') 382 return -EINVAL; 383 buf[nbytes - 1] = '\0'; 384 385 cpus_read_lock(); 386 rdtgrp = rdtgroup_kn_lock_live(of->kn); 387 if (!rdtgrp) { 388 rdtgroup_kn_unlock(of->kn); 389 cpus_read_unlock(); 390 return -ENOENT; 391 } 392 rdt_last_cmd_clear(); 393 394 /* 395 * No changes to pseudo-locked region allowed. It has to be removed 396 * and re-created instead. 397 */ 398 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) { 399 ret = -EINVAL; 400 rdt_last_cmd_puts("Resource group is pseudo-locked\n"); 401 goto out; 402 } 403 404 rdt_staged_configs_clear(); 405 406 while ((tok = strsep(&buf, "\n")) != NULL) { 407 resname = strim(strsep(&tok, ":")); 408 if (!tok) { 409 rdt_last_cmd_puts("Missing ':'\n"); 410 ret = -EINVAL; 411 goto out; 412 } 413 if (tok[0] == '\0') { 414 rdt_last_cmd_printf("Missing '%s' value\n", resname); 415 ret = -EINVAL; 416 goto out; 417 } 418 ret = rdtgroup_parse_resource(resname, tok, rdtgrp); 419 if (ret) 420 goto out; 421 } 422 423 list_for_each_entry(s, &resctrl_schema_all, list) { 424 r = s->res; 425 426 /* 427 * Writes to mba_sc resources update the software controller, 428 * not the control MSR. 429 */ 430 if (is_mba_sc(r)) 431 continue; 432 433 ret = resctrl_arch_update_domains(r, rdtgrp->closid); 434 if (ret) 435 goto out; 436 } 437 438 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { 439 /* 440 * If pseudo-locking fails we keep the resource group in 441 * mode RDT_MODE_PSEUDO_LOCKSETUP with its class of service 442 * active and updated for just the domain the pseudo-locked 443 * region was requested for. 444 */ 445 ret = rdtgroup_pseudo_lock_create(rdtgrp); 446 } 447 448 out: 449 rdt_staged_configs_clear(); 450 rdtgroup_kn_unlock(of->kn); 451 cpus_read_unlock(); 452 return ret ?: nbytes; 453 } 454 455 u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, 456 u32 closid, enum resctrl_conf_type type) 457 { 458 struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d); 459 u32 idx = get_config_index(closid, type); 460 461 return hw_dom->ctrl_val[idx]; 462 } 463 464 static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid) 465 { 466 struct rdt_resource *r = schema->res; 467 struct rdt_domain *dom; 468 bool sep = false; 469 u32 ctrl_val; 470 471 seq_printf(s, "%*s:", max_name_width, schema->name); 472 list_for_each_entry(dom, &r->domains, list) { 473 if (sep) 474 seq_puts(s, ";"); 475 476 if (is_mba_sc(r)) 477 ctrl_val = dom->mbps_val[closid]; 478 else 479 ctrl_val = resctrl_arch_get_config(r, dom, closid, 480 schema->conf_type); 481 482 seq_printf(s, r->format_str, dom->id, max_data_width, 483 ctrl_val); 484 sep = true; 485 } 486 seq_puts(s, "\n"); 487 } 488 489 int rdtgroup_schemata_show(struct kernfs_open_file *of, 490 struct seq_file *s, void *v) 491 { 492 struct resctrl_schema *schema; 493 struct rdtgroup *rdtgrp; 494 int ret = 0; 495 u32 closid; 496 497 rdtgrp = rdtgroup_kn_lock_live(of->kn); 498 if (rdtgrp) { 499 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { 500 list_for_each_entry(schema, &resctrl_schema_all, list) { 501 seq_printf(s, "%s:uninitialized\n", schema->name); 502 } 503 } else if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) { 504 if (!rdtgrp->plr->d) { 505 rdt_last_cmd_clear(); 506 rdt_last_cmd_puts("Cache domain offline\n"); 507 ret = -ENODEV; 508 } else { 509 seq_printf(s, "%s:%d=%x\n", 510 rdtgrp->plr->s->res->name, 511 rdtgrp->plr->d->id, 512 rdtgrp->plr->cbm); 513 } 514 } else { 515 closid = rdtgrp->closid; 516 list_for_each_entry(schema, &resctrl_schema_all, list) { 517 if (closid < schema->num_closid) 518 show_doms(s, schema, closid); 519 } 520 } 521 } else { 522 ret = -ENOENT; 523 } 524 rdtgroup_kn_unlock(of->kn); 525 return ret; 526 } 527 528 void mon_event_read(struct rmid_read *rr, struct rdt_resource *r, 529 struct rdt_domain *d, struct rdtgroup *rdtgrp, 530 int evtid, int first) 531 { 532 /* 533 * setup the parameters to send to the IPI to read the data. 534 */ 535 rr->rgrp = rdtgrp; 536 rr->evtid = evtid; 537 rr->r = r; 538 rr->d = d; 539 rr->val = 0; 540 rr->first = first; 541 542 smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1); 543 } 544 545 int rdtgroup_mondata_show(struct seq_file *m, void *arg) 546 { 547 struct kernfs_open_file *of = m->private; 548 u32 resid, evtid, domid; 549 struct rdtgroup *rdtgrp; 550 struct rdt_resource *r; 551 union mon_data_bits md; 552 struct rdt_domain *d; 553 struct rmid_read rr; 554 int ret = 0; 555 556 rdtgrp = rdtgroup_kn_lock_live(of->kn); 557 if (!rdtgrp) { 558 ret = -ENOENT; 559 goto out; 560 } 561 562 md.priv = of->kn->priv; 563 resid = md.u.rid; 564 domid = md.u.domid; 565 evtid = md.u.evtid; 566 567 r = &rdt_resources_all[resid].r_resctrl; 568 d = rdt_find_domain(r, domid, NULL); 569 if (IS_ERR_OR_NULL(d)) { 570 ret = -ENOENT; 571 goto out; 572 } 573 574 mon_event_read(&rr, r, d, rdtgrp, evtid, false); 575 576 if (rr.err == -EIO) 577 seq_puts(m, "Error\n"); 578 else if (rr.err == -EINVAL) 579 seq_puts(m, "Unavailable\n"); 580 else 581 seq_printf(m, "%llu\n", rr.val); 582 583 out: 584 rdtgroup_kn_unlock(of->kn); 585 return ret; 586 } 587