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