ctrlmondata.c 15 KB

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