Skip to content

Commit 12e0110

Browse files
aeglKAGA-KOKO
authored andcommitted
x86/intel_rdt: Add cpus file
Now we populate each directory with a read/write (mode 0644) file named "cpus". This is used to over-ride the resources available to processes in the default resource group when running on specific CPUs. Each "cpus" file reads as a cpumask showing which CPUs belong to this resource group. Initially all online CPUs are assigned to the default group. They can be added to other groups by writing a cpumask to the "cpus" file in the directory for the resource group (which will remove them from the previous group to which they were assigned). CPU online/offline operations will delete CPUs that go offline from whatever group they are in and add new CPUs to the default group. If there are CPUs assigned to a group when the directory is removed, they are returned to the default group. Signed-off-by: Tony Luck <[email protected]> Signed-off-by: Fenghua Yu <[email protected]> Cc: "Ravi V Shankar" <[email protected]> Cc: "Shaohua Li" <[email protected]> Cc: "Sai Prakhya" <[email protected]> Cc: "Peter Zijlstra" <[email protected]> Cc: "Stephane Eranian" <[email protected]> Cc: "Dave Hansen" <[email protected]> Cc: "David Carrillo-Cisneros" <[email protected]> Cc: "Nilay Vaish" <[email protected]> Cc: "Vikas Shivappa" <[email protected]> Cc: "Ingo Molnar" <[email protected]> Cc: "Borislav Petkov" <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 60cf5e1 commit 12e0110

File tree

3 files changed

+154
-5
lines changed

3 files changed

+154
-5
lines changed

arch/x86/include/asm/intel_rdt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
* @kn: kernfs node
1515
* @rdtgroup_list: linked list for all rdtgroups
1616
* @closid: closid for this rdtgroup
17+
* @cpu_mask: CPUs assigned to this rdtgroup
1718
* @flags: status bits
1819
* @waitcount: how many cpus expect to find this
20+
* group when they acquire rdtgroup_mutex
1921
*/
2022
struct rdtgroup {
2123
struct kernfs_node *kn;
2224
struct list_head rdtgroup_list;
2325
int closid;
26+
struct cpumask cpu_mask;
2427
int flags;
2528
atomic_t waitcount;
2629
};
@@ -162,6 +165,8 @@ union cpuid_0x10_1_edx {
162165
unsigned int full;
163166
};
164167

168+
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
169+
165170
void rdt_cbm_update(void *arg);
166171
struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
167172
void rdtgroup_kn_unlock(struct kernfs_node *kn);

arch/x86/kernel/cpu/intel_rdt.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
/* Mutex to protect rdtgroup access. */
3737
DEFINE_MUTEX(rdtgroup_mutex);
3838

39+
DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
40+
3941
#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains)
4042

4143
struct rdt_resource rdt_resources_all[] = {
@@ -331,28 +333,43 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
331333
}
332334
}
333335

334-
static int intel_rdt_online_cpu(unsigned int cpu)
336+
static void clear_closid(int cpu)
335337
{
336338
struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
339+
340+
per_cpu(cpu_closid, cpu) = 0;
341+
state->closid = 0;
342+
wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
343+
}
344+
345+
static int intel_rdt_online_cpu(unsigned int cpu)
346+
{
337347
struct rdt_resource *r;
338348

339349
mutex_lock(&rdtgroup_mutex);
340350
for_each_capable_rdt_resource(r)
341351
domain_add_cpu(cpu, r);
342-
state->closid = 0;
343-
wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
352+
/* The cpu is set in default rdtgroup after online. */
353+
cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
354+
clear_closid(cpu);
344355
mutex_unlock(&rdtgroup_mutex);
345356

346357
return 0;
347358
}
348359

349360
static int intel_rdt_offline_cpu(unsigned int cpu)
350361
{
362+
struct rdtgroup *rdtgrp;
351363
struct rdt_resource *r;
352364

353365
mutex_lock(&rdtgroup_mutex);
354366
for_each_capable_rdt_resource(r)
355367
domain_remove_cpu(cpu, r);
368+
list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
369+
if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
370+
break;
371+
}
372+
clear_closid(cpu);
356373
mutex_unlock(&rdtgroup_mutex);
357374

358375
return 0;

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2222

23+
#include <linux/cpu.h>
2324
#include <linux/fs.h>
2425
#include <linux/sysfs.h>
2526
#include <linux/kernfs.h>
@@ -172,6 +173,111 @@ static struct kernfs_ops rdtgroup_kf_single_ops = {
172173
.seq_show = rdtgroup_seqfile_show,
173174
};
174175

176+
static int rdtgroup_cpus_show(struct kernfs_open_file *of,
177+
struct seq_file *s, void *v)
178+
{
179+
struct rdtgroup *rdtgrp;
180+
int ret = 0;
181+
182+
rdtgrp = rdtgroup_kn_lock_live(of->kn);
183+
184+
if (rdtgrp)
185+
seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask));
186+
else
187+
ret = -ENOENT;
188+
rdtgroup_kn_unlock(of->kn);
189+
190+
return ret;
191+
}
192+
193+
static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
194+
char *buf, size_t nbytes, loff_t off)
195+
{
196+
cpumask_var_t tmpmask, newmask;
197+
struct rdtgroup *rdtgrp, *r;
198+
int ret, cpu;
199+
200+
if (!buf)
201+
return -EINVAL;
202+
203+
if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
204+
return -ENOMEM;
205+
if (!zalloc_cpumask_var(&newmask, GFP_KERNEL)) {
206+
free_cpumask_var(tmpmask);
207+
return -ENOMEM;
208+
}
209+
rdtgrp = rdtgroup_kn_lock_live(of->kn);
210+
if (!rdtgrp) {
211+
ret = -ENOENT;
212+
goto unlock;
213+
}
214+
215+
ret = cpumask_parse(buf, newmask);
216+
if (ret)
217+
goto unlock;
218+
219+
get_online_cpus();
220+
/* check that user didn't specify any offline cpus */
221+
cpumask_andnot(tmpmask, newmask, cpu_online_mask);
222+
if (cpumask_weight(tmpmask)) {
223+
ret = -EINVAL;
224+
goto end;
225+
}
226+
227+
/* Check whether cpus are dropped from this group */
228+
cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
229+
if (cpumask_weight(tmpmask)) {
230+
/* Can't drop from default group */
231+
if (rdtgrp == &rdtgroup_default) {
232+
ret = -EINVAL;
233+
goto end;
234+
}
235+
/* Give any dropped cpus to rdtgroup_default */
236+
cpumask_or(&rdtgroup_default.cpu_mask,
237+
&rdtgroup_default.cpu_mask, tmpmask);
238+
for_each_cpu(cpu, tmpmask)
239+
per_cpu(cpu_closid, cpu) = 0;
240+
}
241+
242+
/*
243+
* If we added cpus, remove them from previous group that owned them
244+
* and update per-cpu closid
245+
*/
246+
cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
247+
if (cpumask_weight(tmpmask)) {
248+
list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
249+
if (r == rdtgrp)
250+
continue;
251+
cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask);
252+
}
253+
for_each_cpu(cpu, tmpmask)
254+
per_cpu(cpu_closid, cpu) = rdtgrp->closid;
255+
}
256+
257+
/* Done pushing/pulling - update this group with new mask */
258+
cpumask_copy(&rdtgrp->cpu_mask, newmask);
259+
260+
end:
261+
put_online_cpus();
262+
unlock:
263+
rdtgroup_kn_unlock(of->kn);
264+
free_cpumask_var(tmpmask);
265+
free_cpumask_var(newmask);
266+
267+
return ret ?: nbytes;
268+
}
269+
270+
/* Files in each rdtgroup */
271+
static struct rftype rdtgroup_base_files[] = {
272+
{
273+
.name = "cpus",
274+
.mode = 0644,
275+
.kf_ops = &rdtgroup_kf_single_ops,
276+
.write = rdtgroup_cpus_write,
277+
.seq_show = rdtgroup_cpus_show,
278+
},
279+
};
280+
175281
static int rdt_num_closids_show(struct kernfs_open_file *of,
176282
struct seq_file *seq, void *v)
177283
{
@@ -582,6 +688,11 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
582688
if (ret)
583689
goto out_destroy;
584690

691+
ret = rdtgroup_add_files(kn, rdtgroup_base_files,
692+
ARRAY_SIZE(rdtgroup_base_files));
693+
if (ret)
694+
goto out_destroy;
695+
585696
kernfs_activate(kn);
586697

587698
ret = 0;
@@ -602,14 +713,20 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
602713
static int rdtgroup_rmdir(struct kernfs_node *kn)
603714
{
604715
struct rdtgroup *rdtgrp;
605-
int ret = 0;
716+
int cpu, ret = 0;
606717

607718
rdtgrp = rdtgroup_kn_lock_live(kn);
608719
if (!rdtgrp) {
609720
rdtgroup_kn_unlock(kn);
610721
return -ENOENT;
611722
}
612723

724+
/* Give any CPUs back to the default group */
725+
cpumask_or(&rdtgroup_default.cpu_mask,
726+
&rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
727+
for_each_cpu(cpu, &rdtgrp->cpu_mask)
728+
per_cpu(cpu_closid, cpu) = 0;
729+
613730
rdtgrp->flags = RDT_DELETED;
614731
closid_free(rdtgrp->closid);
615732
list_del(&rdtgrp->rdtgroup_list);
@@ -633,6 +750,8 @@ static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
633750

634751
static int __init rdtgroup_setup_root(void)
635752
{
753+
int ret;
754+
636755
rdt_root = kernfs_create_root(&rdtgroup_kf_syscall_ops,
637756
KERNFS_ROOT_CREATE_DEACTIVATED,
638757
&rdtgroup_default);
@@ -644,12 +763,20 @@ static int __init rdtgroup_setup_root(void)
644763
rdtgroup_default.closid = 0;
645764
list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
646765

766+
ret = rdtgroup_add_files(rdt_root->kn, rdtgroup_base_files,
767+
ARRAY_SIZE(rdtgroup_base_files));
768+
if (ret) {
769+
kernfs_destroy_root(rdt_root);
770+
goto out;
771+
}
772+
647773
rdtgroup_default.kn = rdt_root->kn;
648774
kernfs_activate(rdtgroup_default.kn);
649775

776+
out:
650777
mutex_unlock(&rdtgroup_mutex);
651778

652-
return 0;
779+
return ret;
653780
}
654781

655782
/*

0 commit comments

Comments
 (0)