blob: 43ee3cee6494ef4903605e3d38bd38b51d4df47f [file] [log] [blame]
Tony Luck60ec2442016-10-28 15:04:47 -07001/*
2 * Resource Director Technology(RDT)
3 * - Cache Allocation code.
4 *
5 * Copyright (C) 2016 Intel Corporation
6 *
7 * Authors:
8 * Fenghua Yu <fenghua.yu@intel.com>
9 * Tony Luck <tony.luck@intel.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * More information about RDT be found in the Intel (R) x86 Architecture
21 * Software Developer Manual June 2016, volume 3, section 17.17.
22 */
23
24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
26#include <linux/kernfs.h>
27#include <linux/seq_file.h>
28#include <linux/slab.h>
Babu Mogerfa7d9492018-11-21 20:28:25 +000029#include "internal.h"
Tony Luck60ec2442016-10-28 15:04:47 -070030
31/*
Vikas Shivappa64e8ed32017-04-07 17:33:57 -070032 * Check whether MBA bandwidth percentage value is correct. The value is
Babu Moger4d05bf72018-11-21 20:28:45 +000033 * checked against the minimum and maximum bandwidth values specified by
34 * the hardware. The allocated bandwidth percentage is rounded to the next
35 * control step available on the hardware.
36 */
37static bool bw_validate_amd(char *buf, unsigned long *data,
38 struct rdt_resource *r)
39{
40 unsigned long bw;
41 int ret;
42
43 ret = kstrtoul(buf, 10, &bw);
44 if (ret) {
45 rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf);
46 return false;
47 }
48
49 if (bw < r->membw.min_bw || bw > r->default_ctrl) {
50 rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw,
51 r->membw.min_bw, r->default_ctrl);
52 return false;
53 }
54
55 *data = roundup(bw, (unsigned long)r->membw.bw_gran);
56 return true;
57}
58
59int parse_bw_amd(struct rdt_parse_data *data, struct rdt_resource *r,
60 struct rdt_domain *d)
61{
62 unsigned long bw_val;
63
64 if (d->have_new_ctrl) {
65 rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
66 return -EINVAL;
67 }
68
69 if (!bw_validate_amd(data->buf, &bw_val, r))
70 return -EINVAL;
71
72 d->new_ctrl = bw_val;
73 d->have_new_ctrl = true;
74
75 return 0;
76}
77
78/*
79 * Check whether MBA bandwidth percentage value is correct. The value is
Vikas Shivappa64e8ed32017-04-07 17:33:57 -070080 * checked against the minimum and max bandwidth values specified by the
81 * hardware. The allocated bandwidth percentage is rounded to the next
82 * control step available on the hardware.
83 */
84static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
85{
86 unsigned long bw;
87 int ret;
88
89 /*
90 * Only linear delay values is supported for current Intel SKUs.
91 */
Tony Luckc377dcf2017-09-25 16:39:34 -070092 if (!r->membw.delay_linear) {
93 rdt_last_cmd_puts("No support for non-linear MB domains\n");
Vikas Shivappa64e8ed32017-04-07 17:33:57 -070094 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -070095 }
Vikas Shivappa64e8ed32017-04-07 17:33:57 -070096
97 ret = kstrtoul(buf, 10, &bw);
Tony Luckc377dcf2017-09-25 16:39:34 -070098 if (ret) {
99 rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf);
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700100 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700101 }
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700102
Vikas Shivappa8205a072018-04-20 15:36:19 -0700103 if ((bw < r->membw.min_bw || bw > r->default_ctrl) &&
104 !is_mba_sc(r)) {
Tony Luckc377dcf2017-09-25 16:39:34 -0700105 rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw,
106 r->membw.min_bw, r->default_ctrl);
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700107 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700108 }
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700109
110 *data = roundup(bw, (unsigned long)r->membw.bw_gran);
111 return true;
112}
113
Babu Moger1ad4fa42018-11-21 20:28:33 +0000114int parse_bw_intel(struct rdt_parse_data *data, struct rdt_resource *r,
115 struct rdt_domain *d)
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700116{
Xiaochen Shen753694a2018-09-15 14:58:19 -0700117 unsigned long bw_val;
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700118
Tony Luckc377dcf2017-09-25 16:39:34 -0700119 if (d->have_new_ctrl) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000120 rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700121 return -EINVAL;
Tony Luckc377dcf2017-09-25 16:39:34 -0700122 }
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700123
Xiaochen Shen753694a2018-09-15 14:58:19 -0700124 if (!bw_validate(data->buf, &bw_val, r))
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700125 return -EINVAL;
Xiaochen Shen753694a2018-09-15 14:58:19 -0700126 d->new_ctrl = bw_val;
Vikas Shivappa64e8ed32017-04-07 17:33:57 -0700127 d->have_new_ctrl = true;
128
129 return 0;
130}
131
132/*
Tony Luck60ec2442016-10-28 15:04:47 -0700133 * Check whether a cache bit mask is valid. The SDM says:
134 * Please note that all (and only) contiguous '1' combinations
135 * are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.).
136 * Additionally Haswell requires at least two bits set.
137 */
Babu Mogera36c5ff2018-11-21 20:28:35 +0000138bool cbm_validate_intel(char *buf, u32 *data, struct rdt_resource *r)
Tony Luck60ec2442016-10-28 15:04:47 -0700139{
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700140 unsigned long first_bit, zero_bit, val;
Thomas Gleixnerd3e11b42017-04-14 13:00:36 +0200141 unsigned int cbm_len = r->cache.cbm_len;
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700142 int ret;
Tony Luck60ec2442016-10-28 15:04:47 -0700143
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700144 ret = kstrtoul(buf, 16, &val);
Tony Luckc377dcf2017-09-25 16:39:34 -0700145 if (ret) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000146 rdt_last_cmd_printf("Non-hex character in the mask %s\n", buf);
Tony Luck60ec2442016-10-28 15:04:47 -0700147 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700148 }
Tony Luck60ec2442016-10-28 15:04:47 -0700149
Tony Luckc377dcf2017-09-25 16:39:34 -0700150 if (val == 0 || val > r->default_ctrl) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000151 rdt_last_cmd_puts("Mask out of range\n");
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700152 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700153 }
Tony Luck60ec2442016-10-28 15:04:47 -0700154
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700155 first_bit = find_first_bit(&val, cbm_len);
156 zero_bit = find_next_zero_bit(&val, cbm_len, first_bit);
157
Tony Luckc377dcf2017-09-25 16:39:34 -0700158 if (find_next_bit(&val, cbm_len, zero_bit) < cbm_len) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000159 rdt_last_cmd_printf("The mask %lx has non-consecutive 1-bits\n", val);
Tony Luck60ec2442016-10-28 15:04:47 -0700160 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700161 }
Tony Luck60ec2442016-10-28 15:04:47 -0700162
Tony Luckc377dcf2017-09-25 16:39:34 -0700163 if ((zero_bit - first_bit) < r->cache.min_cbm_bits) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000164 rdt_last_cmd_printf("Need at least %d bits in the mask\n",
Tony Luckc377dcf2017-09-25 16:39:34 -0700165 r->cache.min_cbm_bits);
Tony Luck60ec2442016-10-28 15:04:47 -0700166 return false;
Tony Luckc377dcf2017-09-25 16:39:34 -0700167 }
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700168
169 *data = val;
Tony Luck60ec2442016-10-28 15:04:47 -0700170 return true;
171}
172
173/*
Babu Moger4d05bf72018-11-21 20:28:45 +0000174 * Check whether a cache bit mask is valid. AMD allows non-contiguous
175 * bitmasks
176 */
177bool cbm_validate_amd(char *buf, u32 *data, struct rdt_resource *r)
178{
179 unsigned long val;
180 int ret;
181
182 ret = kstrtoul(buf, 16, &val);
183 if (ret) {
184 rdt_last_cmd_printf("Non-hex character in the mask %s\n", buf);
185 return false;
186 }
187
188 if (val > r->default_ctrl) {
189 rdt_last_cmd_puts("Mask out of range\n");
190 return false;
191 }
192
193 *data = val;
194 return true;
195}
196
197/*
Tony Luck60ec2442016-10-28 15:04:47 -0700198 * Read one cache bit mask (hex). Check that it is valid for the current
199 * resource type.
200 */
Xiaochen Shen753694a2018-09-15 14:58:19 -0700201int parse_cbm(struct rdt_parse_data *data, struct rdt_resource *r,
202 struct rdt_domain *d)
Tony Luck60ec2442016-10-28 15:04:47 -0700203{
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700204 struct rdtgroup *rdtgrp = data->rdtgrp;
Reinette Chatre9af4c0a2018-06-22 15:42:02 -0700205 u32 cbm_val;
Tony Luck60ec2442016-10-28 15:04:47 -0700206
Tony Luckc377dcf2017-09-25 16:39:34 -0700207 if (d->have_new_ctrl) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000208 rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
Tony Luckc4026b7b2017-04-03 14:44:16 -0700209 return -EINVAL;
Tony Luckc377dcf2017-09-25 16:39:34 -0700210 }
Tony Luckc4026b7b2017-04-03 14:44:16 -0700211
Reinette Chatree0bdfe82018-06-22 15:42:22 -0700212 /*
213 * Cannot set up more than one pseudo-locked region in a cache
214 * hierarchy.
215 */
216 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP &&
217 rdtgroup_pseudo_locked_in_hierarchy(d)) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000218 rdt_last_cmd_printf("Pseudo-locked region in hierarchy\n");
Reinette Chatree0bdfe82018-06-22 15:42:22 -0700219 return -EINVAL;
220 }
221
Babu Mogera36c5ff2018-11-21 20:28:35 +0000222 if (r->cbm_validate && !r->cbm_validate(data->buf, &cbm_val, r))
Tony Luck60ec2442016-10-28 15:04:47 -0700223 return -EINVAL;
Reinette Chatre9af4c0a2018-06-22 15:42:02 -0700224
Reinette Chatree0bdfe82018-06-22 15:42:22 -0700225 if ((rdtgrp->mode == RDT_MODE_EXCLUSIVE ||
226 rdtgrp->mode == RDT_MODE_SHAREABLE) &&
227 rdtgroup_cbm_overlaps_pseudo_locked(d, cbm_val)) {
228 rdt_last_cmd_printf("CBM overlaps with pseudo-locked region\n");
229 return -EINVAL;
230 }
231
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700232 /*
233 * The CBM may not overlap with the CBM of another closid if
234 * either is exclusive.
235 */
236 if (rdtgroup_cbm_overlaps(r, d, cbm_val, rdtgrp->closid, true)) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000237 rdt_last_cmd_printf("Overlaps with exclusive group\n");
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700238 return -EINVAL;
239 }
240
241 if (rdtgroup_cbm_overlaps(r, d, cbm_val, rdtgrp->closid, false)) {
Reinette Chatredfe96742018-06-22 15:42:17 -0700242 if (rdtgrp->mode == RDT_MODE_EXCLUSIVE ||
243 rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
Babu Moger723f1a0d2018-11-21 20:28:43 +0000244 rdt_last_cmd_printf("0verlaps with other group\n");
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700245 return -EINVAL;
246 }
247 }
248
Reinette Chatre9af4c0a2018-06-22 15:42:02 -0700249 d->new_ctrl = cbm_val;
Vikas Shivappa2545e9f2017-04-07 17:33:51 -0700250 d->have_new_ctrl = true;
Tony Luck60ec2442016-10-28 15:04:47 -0700251
252 return 0;
253}
254
255/*
256 * For each domain in this resource we expect to find a series of:
257 * id=mask
Tony Luckc4026b7b2017-04-03 14:44:16 -0700258 * separated by ";". The "id" is in decimal, and must match one of
259 * the "id"s for this resource.
Tony Luck60ec2442016-10-28 15:04:47 -0700260 */
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700261static int parse_line(char *line, struct rdt_resource *r,
262 struct rdtgroup *rdtgrp)
Tony Luck60ec2442016-10-28 15:04:47 -0700263{
Xiaochen Shen753694a2018-09-15 14:58:19 -0700264 struct rdt_parse_data data;
Tony Luck60ec2442016-10-28 15:04:47 -0700265 char *dom = NULL, *id;
266 struct rdt_domain *d;
267 unsigned long dom_id;
268
Reinette Chatre32d736a2018-09-15 14:58:24 -0700269 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP &&
270 r->rid == RDT_RESOURCE_MBA) {
271 rdt_last_cmd_puts("Cannot pseudo-lock MBA resource\n");
272 return -EINVAL;
273 }
274
Tony Luckc4026b7b2017-04-03 14:44:16 -0700275next:
276 if (!line || line[0] == '\0')
277 return 0;
278 dom = strsep(&line, ";");
279 id = strsep(&dom, "=");
Tony Luckc377dcf2017-09-25 16:39:34 -0700280 if (!dom || kstrtoul(id, 10, &dom_id)) {
281 rdt_last_cmd_puts("Missing '=' or non-numeric domain\n");
Tony Luck60ec2442016-10-28 15:04:47 -0700282 return -EINVAL;
Tony Luckc377dcf2017-09-25 16:39:34 -0700283 }
Vikas Shivappa634b0e02017-04-19 16:50:03 -0700284 dom = strim(dom);
Tony Luckc4026b7b2017-04-03 14:44:16 -0700285 list_for_each_entry(d, &r->domains, list) {
286 if (d->id == dom_id) {
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700287 data.buf = dom;
288 data.rdtgrp = rdtgrp;
289 if (r->parse_ctrlval(&data, r, d))
Tony Luckc4026b7b2017-04-03 14:44:16 -0700290 return -EINVAL;
Reinette Chatree0bdfe82018-06-22 15:42:22 -0700291 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
292 /*
293 * In pseudo-locking setup mode and just
294 * parsed a valid CBM that should be
295 * pseudo-locked. Only one locked region per
296 * resource group and domain so just do
297 * the required initialization for single
298 * region and return.
299 */
300 rdtgrp->plr->r = r;
301 rdtgrp->plr->d = d;
302 rdtgrp->plr->cbm = d->new_ctrl;
303 d->plr = rdtgrp->plr;
304 return 0;
305 }
Tony Luckc4026b7b2017-04-03 14:44:16 -0700306 goto next;
307 }
308 }
309 return -EINVAL;
Tony Luck60ec2442016-10-28 15:04:47 -0700310}
311
Reinette Chatre024d15b2018-06-22 15:41:58 -0700312int update_domains(struct rdt_resource *r, int closid)
Tony Luck60ec2442016-10-28 15:04:47 -0700313{
314 struct msr_param msr_param;
315 cpumask_var_t cpu_mask;
316 struct rdt_domain *d;
Vikas Shivappa8205a072018-04-20 15:36:19 -0700317 bool mba_sc;
318 u32 *dc;
Tony Luckc4026b7b2017-04-03 14:44:16 -0700319 int cpu;
Tony Luck60ec2442016-10-28 15:04:47 -0700320
321 if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
322 return -ENOMEM;
323
324 msr_param.low = closid;
325 msr_param.high = msr_param.low + 1;
326 msr_param.res = r;
327
Vikas Shivappa8205a072018-04-20 15:36:19 -0700328 mba_sc = is_mba_sc(r);
Tony Luck60ec2442016-10-28 15:04:47 -0700329 list_for_each_entry(d, &r->domains, list) {
Vikas Shivappa8205a072018-04-20 15:36:19 -0700330 dc = !mba_sc ? d->ctrl_val : d->mbps_val;
331 if (d->have_new_ctrl && d->new_ctrl != dc[closid]) {
Tony Luckc4026b7b2017-04-03 14:44:16 -0700332 cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
Vikas Shivappa8205a072018-04-20 15:36:19 -0700333 dc[closid] = d->new_ctrl;
Tony Luckc4026b7b2017-04-03 14:44:16 -0700334 }
Tony Luck60ec2442016-10-28 15:04:47 -0700335 }
Vikas Shivappa8205a072018-04-20 15:36:19 -0700336
337 /*
338 * Avoid writing the control msr with control values when
339 * MBA software controller is enabled
340 */
341 if (cpumask_empty(cpu_mask) || mba_sc)
Tony Luckc4026b7b2017-04-03 14:44:16 -0700342 goto done;
Tony Luck60ec2442016-10-28 15:04:47 -0700343 cpu = get_cpu();
344 /* Update CBM on this cpu if it's in cpu_mask. */
345 if (cpumask_test_cpu(cpu, cpu_mask))
Vikas Shivappa2545e9f2017-04-07 17:33:51 -0700346 rdt_ctrl_update(&msr_param);
Tony Luck60ec2442016-10-28 15:04:47 -0700347 /* Update CBM on other cpus. */
Vikas Shivappa2545e9f2017-04-07 17:33:51 -0700348 smp_call_function_many(cpu_mask, rdt_ctrl_update, &msr_param, 1);
Tony Luck60ec2442016-10-28 15:04:47 -0700349 put_cpu();
350
Tony Luckc4026b7b2017-04-03 14:44:16 -0700351done:
Tony Luck60ec2442016-10-28 15:04:47 -0700352 free_cpumask_var(cpu_mask);
353
354 return 0;
355}
356
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700357static int rdtgroup_parse_resource(char *resname, char *tok,
358 struct rdtgroup *rdtgrp)
Vikas Shivappa4797b7d2017-04-19 16:50:04 -0700359{
360 struct rdt_resource *r;
361
Vikas Shivappa1b5c0b72017-07-25 14:14:25 -0700362 for_each_alloc_enabled_rdt_resource(r) {
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700363 if (!strcmp(resname, r->name) && rdtgrp->closid < r->num_closid)
364 return parse_line(tok, r, rdtgrp);
Vikas Shivappa4797b7d2017-04-19 16:50:04 -0700365 }
Babu Moger723f1a0d2018-11-21 20:28:43 +0000366 rdt_last_cmd_printf("Unknown or unsupported resource name '%s'\n", resname);
Vikas Shivappa4797b7d2017-04-19 16:50:04 -0700367 return -EINVAL;
368}
369
Tony Luck60ec2442016-10-28 15:04:47 -0700370ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
371 char *buf, size_t nbytes, loff_t off)
372{
373 struct rdtgroup *rdtgrp;
Tony Luckc4026b7b2017-04-03 14:44:16 -0700374 struct rdt_domain *dom;
Tony Luck60ec2442016-10-28 15:04:47 -0700375 struct rdt_resource *r;
376 char *tok, *resname;
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700377 int ret = 0;
Tony Luck60ec2442016-10-28 15:04:47 -0700378
379 /* Valid input requires a trailing newline */
Tony Luck29e74f32017-09-25 16:39:35 -0700380 if (nbytes == 0 || buf[nbytes - 1] != '\n')
Tony Luck60ec2442016-10-28 15:04:47 -0700381 return -EINVAL;
382 buf[nbytes - 1] = '\0';
383
384 rdtgrp = rdtgroup_kn_lock_live(of->kn);
385 if (!rdtgrp) {
386 rdtgroup_kn_unlock(of->kn);
387 return -ENOENT;
388 }
Tony Luckc377dcf2017-09-25 16:39:34 -0700389 rdt_last_cmd_clear();
Tony Luck60ec2442016-10-28 15:04:47 -0700390
Reinette Chatrec966dac2018-06-22 15:42:12 -0700391 /*
392 * No changes to pseudo-locked region allowed. It has to be removed
393 * and re-created instead.
394 */
395 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
396 ret = -EINVAL;
Babu Moger723f1a0d2018-11-21 20:28:43 +0000397 rdt_last_cmd_puts("Resource group is pseudo-locked\n");
Reinette Chatrec966dac2018-06-22 15:42:12 -0700398 goto out;
399 }
400
Vikas Shivappa1b5c0b72017-07-25 14:14:25 -0700401 for_each_alloc_enabled_rdt_resource(r) {
Tony Luckc4026b7b2017-04-03 14:44:16 -0700402 list_for_each_entry(dom, &r->domains, list)
Vikas Shivappa2545e9f2017-04-07 17:33:51 -0700403 dom->have_new_ctrl = false;
Vikas Shivappa4797b7d2017-04-19 16:50:04 -0700404 }
Tony Luck60ec2442016-10-28 15:04:47 -0700405
406 while ((tok = strsep(&buf, "\n")) != NULL) {
Vikas Shivappa634b0e02017-04-19 16:50:03 -0700407 resname = strim(strsep(&tok, ":"));
Tony Luck60ec2442016-10-28 15:04:47 -0700408 if (!tok) {
Tony Luckc377dcf2017-09-25 16:39:34 -0700409 rdt_last_cmd_puts("Missing ':'\n");
Tony Luck60ec2442016-10-28 15:04:47 -0700410 ret = -EINVAL;
411 goto out;
412 }
Xiaochen Shen22446452017-11-10 11:16:24 -0800413 if (tok[0] == '\0') {
414 rdt_last_cmd_printf("Missing '%s' value\n", resname);
415 ret = -EINVAL;
416 goto out;
417 }
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700418 ret = rdtgroup_parse_resource(resname, tok, rdtgrp);
Vikas Shivappa4797b7d2017-04-19 16:50:04 -0700419 if (ret)
Tony Luck60ec2442016-10-28 15:04:47 -0700420 goto out;
Tony Luck60ec2442016-10-28 15:04:47 -0700421 }
422
Vikas Shivappa1b5c0b72017-07-25 14:14:25 -0700423 for_each_alloc_enabled_rdt_resource(r) {
Reinette Chatre9ab9aa12018-06-22 15:42:04 -0700424 ret = update_domains(r, rdtgrp->closid);
Tony Luck60ec2442016-10-28 15:04:47 -0700425 if (ret)
426 goto out;
427 }
428
Reinette Chatree0bdfe82018-06-22 15:42:22 -0700429 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
430 /*
431 * If pseudo-locking fails we keep the resource group in
432 * mode RDT_MODE_PSEUDO_LOCKSETUP with its class of service
433 * active and updated for just the domain the pseudo-locked
434 * region was requested for.
435 */
436 ret = rdtgroup_pseudo_lock_create(rdtgrp);
437 }
438
Tony Luck60ec2442016-10-28 15:04:47 -0700439out:
440 rdtgroup_kn_unlock(of->kn);
Tony Luck60ec2442016-10-28 15:04:47 -0700441 return ret ?: nbytes;
442}
443
444static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid)
445{
446 struct rdt_domain *dom;
447 bool sep = false;
Vikas Shivappa8205a072018-04-20 15:36:19 -0700448 u32 ctrl_val;
Tony Luck60ec2442016-10-28 15:04:47 -0700449
Vikas Shivappade016df2017-04-03 14:44:17 -0700450 seq_printf(s, "%*s:", max_name_width, r->name);
Tony Luck60ec2442016-10-28 15:04:47 -0700451 list_for_each_entry(dom, &r->domains, list) {
452 if (sep)
453 seq_puts(s, ";");
Vikas Shivappa8205a072018-04-20 15:36:19 -0700454
455 ctrl_val = (!is_mba_sc(r) ? dom->ctrl_val[closid] :
456 dom->mbps_val[closid]);
Vikas Shivappac6ea67d2017-04-07 17:33:56 -0700457 seq_printf(s, r->format_str, dom->id, max_data_width,
Vikas Shivappa8205a072018-04-20 15:36:19 -0700458 ctrl_val);
Tony Luck60ec2442016-10-28 15:04:47 -0700459 sep = true;
460 }
461 seq_puts(s, "\n");
462}
463
464int rdtgroup_schemata_show(struct kernfs_open_file *of,
465 struct seq_file *s, void *v)
466{
467 struct rdtgroup *rdtgrp;
468 struct rdt_resource *r;
Vikas Shivappad89b7372017-07-25 14:14:38 -0700469 int ret = 0;
470 u32 closid;
Tony Luck60ec2442016-10-28 15:04:47 -0700471
472 rdtgrp = rdtgroup_kn_lock_live(of->kn);
473 if (rdtgrp) {
Reinette Chatredfe96742018-06-22 15:42:17 -0700474 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
475 for_each_alloc_enabled_rdt_resource(r)
476 seq_printf(s, "%s:uninitialized\n", r->name);
Reinette Chatref4e80d62018-06-22 15:42:23 -0700477 } else if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
Jithu Josephb61b8bb2018-10-12 15:51:01 -0700478 if (!rdtgrp->plr->d) {
479 rdt_last_cmd_clear();
480 rdt_last_cmd_puts("Cache domain offline\n");
481 ret = -ENODEV;
482 } else {
483 seq_printf(s, "%s:%d=%x\n",
484 rdtgrp->plr->r->name,
485 rdtgrp->plr->d->id,
486 rdtgrp->plr->cbm);
487 }
Reinette Chatredfe96742018-06-22 15:42:17 -0700488 } else {
489 closid = rdtgrp->closid;
490 for_each_alloc_enabled_rdt_resource(r) {
491 if (closid < r->num_closid)
492 show_doms(s, r, closid);
493 }
Tony Luck60ec2442016-10-28 15:04:47 -0700494 }
495 } else {
496 ret = -ENOENT;
497 }
498 rdtgroup_kn_unlock(of->kn);
499 return ret;
500}
Vikas Shivappad89b7372017-07-25 14:14:38 -0700501
502void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
Vikas Shivappaa4de1df2017-07-25 14:14:46 -0700503 struct rdtgroup *rdtgrp, int evtid, int first)
Vikas Shivappad89b7372017-07-25 14:14:38 -0700504{
505 /*
506 * setup the parameters to send to the IPI to read the data.
507 */
508 rr->rgrp = rdtgrp;
509 rr->evtid = evtid;
Tony Luck9f524252017-07-25 14:14:45 -0700510 rr->d = d;
Vikas Shivappad89b7372017-07-25 14:14:38 -0700511 rr->val = 0;
Vikas Shivappaa4de1df2017-07-25 14:14:46 -0700512 rr->first = first;
Vikas Shivappad89b7372017-07-25 14:14:38 -0700513
514 smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
515}
516
517int rdtgroup_mondata_show(struct seq_file *m, void *arg)
518{
519 struct kernfs_open_file *of = m->private;
520 u32 resid, evtid, domid;
521 struct rdtgroup *rdtgrp;
522 struct rdt_resource *r;
523 union mon_data_bits md;
524 struct rdt_domain *d;
525 struct rmid_read rr;
526 int ret = 0;
527
528 rdtgrp = rdtgroup_kn_lock_live(of->kn);
529
530 md.priv = of->kn->priv;
531 resid = md.u.rid;
532 domid = md.u.domid;
533 evtid = md.u.evtid;
534
535 r = &rdt_resources_all[resid];
536 d = rdt_find_domain(r, domid, NULL);
537 if (!d) {
538 ret = -ENOENT;
539 goto out;
540 }
541
Vikas Shivappaa4de1df2017-07-25 14:14:46 -0700542 mon_event_read(&rr, d, rdtgrp, evtid, false);
Vikas Shivappad89b7372017-07-25 14:14:38 -0700543
544 if (rr.val & RMID_VAL_ERROR)
545 seq_puts(m, "Error\n");
546 else if (rr.val & RMID_VAL_UNAVAIL)
547 seq_puts(m, "Unavailable\n");
548 else
549 seq_printf(m, "%llu\n", rr.val * r->mon_scale);
550
551out:
552 rdtgroup_kn_unlock(of->kn);
553 return ret;
554}