Skip to content

Commit c4026b7

Browse files
aeglKAGA-KOKO
authored andcommitted
x86/intel_rdt: Implement "update" mode when writing schemata file
The schemata file can have multiple lines and it is cumbersome to update all lines. Remove code that requires that the user provides values for every resource (in the right order). If the user provides values for just a few resources, update them and leave the rest unchanged. Side benefit: we now check which values were updated and only send IPIs to cpus that actually have updates. Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Vikas Shivappa <vikas.shivappa@linux.intel.com> Tested-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com> Cc: ravi.v.shankar@intel.com Cc: fenghua.yu@intel.com Cc: peterz@infradead.org Cc: vikas.shivappa@intel.com Cc: h.peter.anvin@intel.com Link: http://lkml.kernel.org/r/1491255857-17213-3-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 6415813 commit c4026b7

File tree

4 files changed

+51
-51
lines changed

4 files changed

+51
-51
lines changed

Documentation/x86/intel_rdt_ui.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ schemata format is always:
129129

130130
L2:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
131131

132+
Reading/writing the schemata file
133+
---------------------------------
134+
Reading the schemata file will show the state of all resources
135+
on all domains. When writing you only need to specify those values
136+
which you wish to change. E.g.
137+
138+
# cat schemata
139+
L3DATA:0=fffff;1=fffff;2=fffff;3=fffff
140+
L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
141+
# echo "L3DATA:2=3c0;" > schemata
142+
# cat schemata
143+
L3DATA:0=fffff;1=fffff;2=3c0;3=fffff
144+
L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
145+
132146
Example 1
133147
---------
134148
On a two socket machine (one L3 cache per socket) with just four bits

arch/x86/include/asm/intel_rdt.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,7 @@ struct rftype {
7676
* @min_cbm_bits: Minimum number of consecutive bits to be set
7777
* in a cache bit mask
7878
* @domains: All domains for this resource
79-
* @num_domains: Number of domains active
8079
* @msr_base: Base MSR address for CBMs
81-
* @tmp_cbms: Scratch space when updating schemata
82-
* @num_tmp_cbms: Number of CBMs in tmp_cbms
8380
* @cache_level: Which cache level defines scope of this domain
8481
* @cbm_idx_multi: Multiplier of CBM index
8582
* @cbm_idx_offset: Offset of CBM index. CBM index is computed by:
@@ -94,10 +91,7 @@ struct rdt_resource {
9491
int min_cbm_bits;
9592
u32 max_cbm;
9693
struct list_head domains;
97-
int num_domains;
9894
int msr_base;
99-
u32 *tmp_cbms;
100-
int num_tmp_cbms;
10195
int cache_level;
10296
int cbm_idx_multi;
10397
int cbm_idx_offset;
@@ -109,12 +103,16 @@ struct rdt_resource {
109103
* @id: unique id for this instance
110104
* @cpu_mask: which cpus share this resource
111105
* @cbm: array of cache bit masks (indexed by CLOSID)
106+
* @new_cbm: new cbm value to be loaded
107+
* @have_new_cbm: did user provide new_cbm for this domain
112108
*/
113109
struct rdt_domain {
114110
struct list_head list;
115111
int id;
116112
struct cpumask cpu_mask;
117113
u32 *cbm;
114+
u32 new_cbm;
115+
bool have_new_cbm;
118116
};
119117

120118
/**

arch/x86/kernel/cpu/intel_rdt.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
309309

310310
cpumask_set_cpu(cpu, &d->cpu_mask);
311311
list_add_tail(&d->list, add_pos);
312-
r->num_domains++;
313312
}
314313

315314
static void domain_remove_cpu(int cpu, struct rdt_resource *r)
@@ -325,7 +324,6 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
325324

326325
cpumask_clear_cpu(cpu, &d->cpu_mask);
327326
if (cpumask_empty(&d->cpu_mask)) {
328-
r->num_domains--;
329327
kfree(d->cbm);
330328
list_del(&d->list);
331329
kfree(d);

arch/x86/kernel/cpu/intel_rdt_schemata.c

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -56,56 +56,60 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r)
5656
* Read one cache bit mask (hex). Check that it is valid for the current
5757
* resource type.
5858
*/
59-
static int parse_cbm(char *buf, struct rdt_resource *r)
59+
static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d)
6060
{
6161
unsigned long data;
6262
int ret;
6363

64+
if (d->have_new_cbm)
65+
return -EINVAL;
66+
6467
ret = kstrtoul(buf, 16, &data);
6568
if (ret)
6669
return ret;
6770
if (!cbm_validate(data, r))
6871
return -EINVAL;
69-
r->tmp_cbms[r->num_tmp_cbms++] = data;
72+
d->new_cbm = data;
73+
d->have_new_cbm = true;
7074

7175
return 0;
7276
}
7377

7478
/*
7579
* For each domain in this resource we expect to find a series of:
7680
* id=mask
77-
* separated by ";". The "id" is in decimal, and must appear in the
78-
* right order.
81+
* separated by ";". The "id" is in decimal, and must match one of
82+
* the "id"s for this resource.
7983
*/
8084
static int parse_line(char *line, struct rdt_resource *r)
8185
{
8286
char *dom = NULL, *id;
8387
struct rdt_domain *d;
8488
unsigned long dom_id;
8589

90+
next:
91+
if (!line || line[0] == '\0')
92+
return 0;
93+
dom = strsep(&line, ";");
94+
id = strsep(&dom, "=");
95+
if (!dom || kstrtoul(id, 10, &dom_id))
96+
return -EINVAL;
8697
list_for_each_entry(d, &r->domains, list) {
87-
dom = strsep(&line, ";");
88-
if (!dom)
89-
return -EINVAL;
90-
id = strsep(&dom, "=");
91-
if (kstrtoul(id, 10, &dom_id) || dom_id != d->id)
92-
return -EINVAL;
93-
if (parse_cbm(dom, r))
94-
return -EINVAL;
98+
if (d->id == dom_id) {
99+
if (parse_cbm(dom, r, d))
100+
return -EINVAL;
101+
goto next;
102+
}
95103
}
96-
97-
/* Any garbage at the end of the line? */
98-
if (line && line[0])
99-
return -EINVAL;
100-
return 0;
104+
return -EINVAL;
101105
}
102106

103107
static int update_domains(struct rdt_resource *r, int closid)
104108
{
105109
struct msr_param msr_param;
106110
cpumask_var_t cpu_mask;
107111
struct rdt_domain *d;
108-
int cpu, idx = 0;
112+
int cpu;
109113

110114
if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
111115
return -ENOMEM;
@@ -115,9 +119,13 @@ static int update_domains(struct rdt_resource *r, int closid)
115119
msr_param.res = r;
116120

117121
list_for_each_entry(d, &r->domains, list) {
118-
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
119-
d->cbm[msr_param.low] = r->tmp_cbms[idx++];
122+
if (d->have_new_cbm && d->new_cbm != d->cbm[closid]) {
123+
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
124+
d->cbm[closid] = d->new_cbm;
125+
}
120126
}
127+
if (cpumask_empty(cpu_mask))
128+
goto done;
121129
cpu = get_cpu();
122130
/* Update CBM on this cpu if it's in cpu_mask. */
123131
if (cpumask_test_cpu(cpu, cpu_mask))
@@ -126,6 +134,7 @@ static int update_domains(struct rdt_resource *r, int closid)
126134
smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1);
127135
put_cpu();
128136

137+
done:
129138
free_cpumask_var(cpu_mask);
130139

131140
return 0;
@@ -135,10 +144,10 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
135144
char *buf, size_t nbytes, loff_t off)
136145
{
137146
struct rdtgroup *rdtgrp;
147+
struct rdt_domain *dom;
138148
struct rdt_resource *r;
139149
char *tok, *resname;
140150
int closid, ret = 0;
141-
u32 *l3_cbms = NULL;
142151

143152
/* Valid input requires a trailing newline */
144153
if (nbytes == 0 || buf[nbytes - 1] != '\n')
@@ -153,16 +162,9 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
153162

154163
closid = rdtgrp->closid;
155164

156-
/* get scratch space to save all the masks while we validate input */
157-
for_each_enabled_rdt_resource(r) {
158-
r->tmp_cbms = kcalloc(r->num_domains, sizeof(*l3_cbms),
159-
GFP_KERNEL);
160-
if (!r->tmp_cbms) {
161-
ret = -ENOMEM;
162-
goto out;
163-
}
164-
r->num_tmp_cbms = 0;
165-
}
165+
for_each_enabled_rdt_resource(r)
166+
list_for_each_entry(dom, &r->domains, list)
167+
dom->have_new_cbm = false;
166168

167169
while ((tok = strsep(&buf, "\n")) != NULL) {
168170
resname = strsep(&tok, ":");
@@ -185,14 +187,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
185187
}
186188
}
187189

188-
/* Did the parser find all the masks we need? */
189-
for_each_enabled_rdt_resource(r) {
190-
if (r->num_tmp_cbms != r->num_domains) {
191-
ret = -EINVAL;
192-
goto out;
193-
}
194-
}
195-
196190
for_each_enabled_rdt_resource(r) {
197191
ret = update_domains(r, closid);
198192
if (ret)
@@ -201,10 +195,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
201195

202196
out:
203197
rdtgroup_kn_unlock(of->kn);
204-
for_each_enabled_rdt_resource(r) {
205-
kfree(r->tmp_cbms);
206-
r->tmp_cbms = NULL;
207-
}
208198
return ret ?: nbytes;
209199
}
210200

0 commit comments

Comments
 (0)