Skip to content

Commit 0efc89b

Browse files
Fenghua YuKAGA-KOKO
authored andcommitted
x86/intel_rdt: Update task closid immediately on CPU in rmdir and unmount
When removing a sub directory/rdtgroup by rmdir or umount, closid in a task in the sub directory is set to default rdtgroup's closid which is 0. If the task is running on a CPU, the PQR_ASSOC MSR is only updated when the task runs through a context switch. Up to the context switch, the task runs with the wrong closid. Make the change immediately effective by invoking a smp function call on all CPUs which are running moved task. If one of the affected tasks was moved or scheduled out before the function call is executed on the CPU the only damage is the extra interruption of the CPU. [ tglx: Reworked it to avoid blindly interrupting all CPUs and extra loops ] Signed-off-by: Fenghua Yu <[email protected]> Cc: "Ravi V Shankar" <[email protected]> Cc: "Tony Luck" <[email protected]> Cc: "Sai Prakhya" <[email protected]> Cc: "Vikas Shivappa" <[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 2659f46 commit 0efc89b

File tree

1 file changed

+83
-30
lines changed

1 file changed

+83
-30
lines changed

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,13 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
194194
/*
195195
* This is safe against intel_rdt_sched_in() called from __switch_to()
196196
* because __switch_to() is executed with interrupts disabled. A local call
197-
* from rdt_update_percpu_closid() is proteced against __switch_to() because
197+
* from rdt_update_closid() is proteced against __switch_to() because
198198
* preemption is disabled.
199199
*/
200-
static void rdt_update_cpu_closid(void *v)
200+
static void rdt_update_cpu_closid(void *closid)
201201
{
202-
this_cpu_write(cpu_closid, *(int *)v);
202+
if (closid)
203+
this_cpu_write(cpu_closid, *(int *)closid);
203204
/*
204205
* We cannot unconditionally write the MSR because the current
205206
* executing task might have its own closid selected. Just reuse
@@ -208,14 +209,23 @@ static void rdt_update_cpu_closid(void *v)
208209
intel_rdt_sched_in();
209210
}
210211

211-
/* Update the per cpu closid and eventually the PGR_ASSOC MSR */
212-
static void rdt_update_percpu_closid(const struct cpumask *cpu_mask, int closid)
212+
/*
213+
* Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
214+
*
215+
* Per task closids must have been set up before calling this function.
216+
*
217+
* The per cpu closids are updated with the smp function call, when @closid
218+
* is not NULL. If @closid is NULL then all affected percpu closids must
219+
* have been set up before calling this function.
220+
*/
221+
static void
222+
rdt_update_closid(const struct cpumask *cpu_mask, int *closid)
213223
{
214224
int cpu = get_cpu();
215225

216226
if (cpumask_test_cpu(cpu, cpu_mask))
217-
rdt_update_cpu_closid(&closid);
218-
smp_call_function_many(cpu_mask, rdt_update_cpu_closid, &closid, 1);
227+
rdt_update_cpu_closid(closid);
228+
smp_call_function_many(cpu_mask, rdt_update_cpu_closid, closid, 1);
219229
put_cpu();
220230
}
221231

@@ -264,7 +274,7 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
264274
/* Give any dropped cpus to rdtgroup_default */
265275
cpumask_or(&rdtgroup_default.cpu_mask,
266276
&rdtgroup_default.cpu_mask, tmpmask);
267-
rdt_update_percpu_closid(tmpmask, rdtgroup_default.closid);
277+
rdt_update_closid(tmpmask, &rdtgroup_default.closid);
268278
}
269279

270280
/*
@@ -278,7 +288,7 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
278288
continue;
279289
cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask);
280290
}
281-
rdt_update_percpu_closid(tmpmask, rdtgrp->closid);
291+
rdt_update_closid(tmpmask, &rdtgrp->closid);
282292
}
283293

284294
/* Done pushing/pulling - update this group with new mask */
@@ -807,18 +817,49 @@ static int reset_all_cbms(struct rdt_resource *r)
807817
}
808818

809819
/*
810-
* Forcibly remove all of subdirectories under root.
820+
* Move tasks from one to the other group. If @from is NULL, then all tasks
821+
* in the systems are moved unconditionally (used for teardown).
822+
*
823+
* If @mask is not NULL the cpus on which moved tasks are running are set
824+
* in that mask so the update smp function call is restricted to affected
825+
* cpus.
811826
*/
812-
static void rmdir_all_sub(void)
827+
static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
828+
struct cpumask *mask)
813829
{
814-
struct rdtgroup *rdtgrp, *tmp;
815830
struct task_struct *p, *t;
816831

817-
/* move all tasks to default resource group */
818832
read_lock(&tasklist_lock);
819-
for_each_process_thread(p, t)
820-
t->closid = 0;
833+
for_each_process_thread(p, t) {
834+
if (!from || t->closid == from->closid) {
835+
t->closid = to->closid;
836+
#ifdef CONFIG_SMP
837+
/*
838+
* This is safe on x86 w/o barriers as the ordering
839+
* of writing to task_cpu() and t->on_cpu is
840+
* reverse to the reading here. The detection is
841+
* inaccurate as tasks might move or schedule
842+
* before the smp function call takes place. In
843+
* such a case the function call is pointless, but
844+
* there is no other side effect.
845+
*/
846+
if (mask && t->on_cpu)
847+
cpumask_set_cpu(task_cpu(t), mask);
848+
#endif
849+
}
850+
}
821851
read_unlock(&tasklist_lock);
852+
}
853+
854+
/*
855+
* Forcibly remove all of subdirectories under root.
856+
*/
857+
static void rmdir_all_sub(void)
858+
{
859+
struct rdtgroup *rdtgrp, *tmp;
860+
861+
/* Move all tasks to the default resource group */
862+
rdt_move_group_tasks(NULL, &rdtgroup_default, NULL);
822863

823864
list_for_each_entry_safe(rdtgrp, tmp, &rdt_all_groups, rdtgroup_list) {
824865
/* Remove each rdtgroup other than root */
@@ -833,13 +874,15 @@ static void rmdir_all_sub(void)
833874
cpumask_or(&rdtgroup_default.cpu_mask,
834875
&rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
835876

836-
rdt_update_percpu_closid(&rdtgrp->cpu_mask,
837-
rdtgroup_default.closid);
838-
839877
kernfs_remove(rdtgrp->kn);
840878
list_del(&rdtgrp->rdtgroup_list);
841879
kfree(rdtgrp);
842880
}
881+
/* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
882+
get_online_cpus();
883+
rdt_update_closid(cpu_online_mask, &rdtgroup_default.closid);
884+
put_online_cpus();
885+
843886
kernfs_remove(kn_info);
844887
}
845888

@@ -944,27 +987,35 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
944987

945988
static int rdtgroup_rmdir(struct kernfs_node *kn)
946989
{
947-
struct task_struct *p, *t;
990+
int ret, cpu, closid = rdtgroup_default.closid;
948991
struct rdtgroup *rdtgrp;
992+
cpumask_var_t tmpmask;
993+
994+
if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
995+
return -ENOMEM;
949996

950997
rdtgrp = rdtgroup_kn_lock_live(kn);
951998
if (!rdtgrp) {
952-
rdtgroup_kn_unlock(kn);
953-
return -EPERM;
999+
ret = -EPERM;
1000+
goto out;
9541001
}
9551002

9561003
/* Give any tasks back to the default group */
957-
read_lock(&tasklist_lock);
958-
for_each_process_thread(p, t) {
959-
if (t->closid == rdtgrp->closid)
960-
t->closid = 0;
961-
}
962-
read_unlock(&tasklist_lock);
1004+
rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
9631005

9641006
/* Give any CPUs back to the default group */
9651007
cpumask_or(&rdtgroup_default.cpu_mask,
9661008
&rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
967-
rdt_update_percpu_closid(&rdtgrp->cpu_mask, rdtgroup_default.closid);
1009+
1010+
/* Update per cpu closid of the moved CPUs first */
1011+
for_each_cpu(cpu, &rdtgrp->cpu_mask)
1012+
per_cpu(cpu_closid, cpu) = closid;
1013+
/*
1014+
* Update the MSR on moved CPUs and CPUs which have moved
1015+
* task running on them.
1016+
*/
1017+
cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
1018+
rdt_update_closid(tmpmask, NULL);
9681019

9691020
rdtgrp->flags = RDT_DELETED;
9701021
closid_free(rdtgrp->closid);
@@ -976,9 +1027,11 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
9761027
*/
9771028
kernfs_get(kn);
9781029
kernfs_remove(rdtgrp->kn);
979-
1030+
ret = 0;
1031+
out:
9801032
rdtgroup_kn_unlock(kn);
981-
return 0;
1033+
free_cpumask_var(tmpmask);
1034+
return ret;
9821035
}
9831036

9841037
static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {

0 commit comments

Comments
 (0)