Skip to content

Commit 6eca639

Browse files
James Morsebp3tk0v
authored andcommitted
x86/resctrl: Move CLOSID/RMID matching and setting to use helpers
When switching tasks, the CLOSID and RMID that the new task should use are stored in struct task_struct. For x86 the CLOSID known by resctrl, the value in task_struct, and the value written to the CPU register are all the same thing. MPAM's CPU interface has two different PARTIDs - one for data accesses the other for instruction fetch. Storing resctrl's CLOSID value in struct task_struct implies the arch code knows whether resctrl is using CDP. Move the matching and setting of the struct task_struct properties to use helpers. This allows arm64 to store the hardware format of the register, instead of having to convert it each time. __rdtgroup_move_task()s use of READ_ONCE()/WRITE_ONCE() ensures torn values aren't seen as another CPU may schedule the task being moved while the value is being changed. MPAM has an additional corner-case here as the PMG bits extend the PARTID space. If the scheduler sees a new-CLOSID but old-RMID, the task will dirty an RMID that the limbo code is not watching causing an inaccurate count. x86's RMID are independent values, so the limbo code will still be watching the old-RMID in this circumstance. To avoid this, arm64 needs both the CLOSID/RMID WRITE_ONCE()d together. Both values must be provided together. Because MPAM's RMID values are not unique, the CLOSID must be provided when matching the RMID. Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Shaopeng Tan <tan.shaopeng@fujitsu.com> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Reviewed-by: Babu Moger <babu.moger@amd.com> Tested-by: Shaopeng Tan <tan.shaopeng@fujitsu.com> Tested-by: Peter Newman <peternewman@google.com> Tested-by: Babu Moger <babu.moger@amd.com> Tested-by: Carl Worth <carl@os.amperecomputing.com> # arm64 Link: https://lore.kernel.org/r/20240213184438.16675-12-james.morse@arm.com Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
1 parent 6eac36b commit 6eca639

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

arch/x86/include/asm/resctrl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,24 @@ static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
9595
return val * scale;
9696
}
9797

98+
static inline void resctrl_arch_set_closid_rmid(struct task_struct *tsk,
99+
u32 closid, u32 rmid)
100+
{
101+
WRITE_ONCE(tsk->closid, closid);
102+
WRITE_ONCE(tsk->rmid, rmid);
103+
}
104+
105+
static inline bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
106+
{
107+
return READ_ONCE(tsk->closid) == closid;
108+
}
109+
110+
static inline bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 ignored,
111+
u32 rmid)
112+
{
113+
return READ_ONCE(tsk->rmid) == rmid;
114+
}
115+
98116
static inline void resctrl_sched_in(struct task_struct *tsk)
99117
{
100118
if (static_branch_likely(&rdt_enable_key))

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void rdt_staged_configs_clear(void)
102102
*
103103
* Using a global CLOSID across all resources has some advantages and
104104
* some drawbacks:
105-
* + We can simply set "current->closid" to assign a task to a resource
105+
* + We can simply set current's closid to assign a task to a resource
106106
* group.
107107
* + Context switch code can avoid extra memory references deciding which
108108
* CLOSID to load into the PQR_ASSOC MSR
@@ -574,14 +574,26 @@ static void update_task_closid_rmid(struct task_struct *t)
574574
_update_task_closid_rmid(t);
575575
}
576576

577+
static bool task_in_rdtgroup(struct task_struct *tsk, struct rdtgroup *rdtgrp)
578+
{
579+
u32 closid, rmid = rdtgrp->mon.rmid;
580+
581+
if (rdtgrp->type == RDTCTRL_GROUP)
582+
closid = rdtgrp->closid;
583+
else if (rdtgrp->type == RDTMON_GROUP)
584+
closid = rdtgrp->mon.parent->closid;
585+
else
586+
return false;
587+
588+
return resctrl_arch_match_closid(tsk, closid) &&
589+
resctrl_arch_match_rmid(tsk, closid, rmid);
590+
}
591+
577592
static int __rdtgroup_move_task(struct task_struct *tsk,
578593
struct rdtgroup *rdtgrp)
579594
{
580595
/* If the task is already in rdtgrp, no need to move the task. */
581-
if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid &&
582-
tsk->rmid == rdtgrp->mon.rmid) ||
583-
(rdtgrp->type == RDTMON_GROUP && tsk->rmid == rdtgrp->mon.rmid &&
584-
tsk->closid == rdtgrp->mon.parent->closid))
596+
if (task_in_rdtgroup(tsk, rdtgrp))
585597
return 0;
586598

587599
/*
@@ -592,19 +604,19 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
592604
* For monitor groups, can move the tasks only from
593605
* their parent CTRL group.
594606
*/
595-
596-
if (rdtgrp->type == RDTCTRL_GROUP) {
597-
WRITE_ONCE(tsk->closid, rdtgrp->closid);
598-
WRITE_ONCE(tsk->rmid, rdtgrp->mon.rmid);
599-
} else if (rdtgrp->type == RDTMON_GROUP) {
600-
if (rdtgrp->mon.parent->closid == tsk->closid) {
601-
WRITE_ONCE(tsk->rmid, rdtgrp->mon.rmid);
602-
} else {
603-
rdt_last_cmd_puts("Can't move task to different control group\n");
604-
return -EINVAL;
605-
}
607+
if (rdtgrp->type == RDTMON_GROUP &&
608+
!resctrl_arch_match_closid(tsk, rdtgrp->mon.parent->closid)) {
609+
rdt_last_cmd_puts("Can't move task to different control group\n");
610+
return -EINVAL;
606611
}
607612

613+
if (rdtgrp->type == RDTMON_GROUP)
614+
resctrl_arch_set_closid_rmid(tsk, rdtgrp->mon.parent->closid,
615+
rdtgrp->mon.rmid);
616+
else
617+
resctrl_arch_set_closid_rmid(tsk, rdtgrp->closid,
618+
rdtgrp->mon.rmid);
619+
608620
/*
609621
* Ensure the task's closid and rmid are written before determining if
610622
* the task is current that will decide if it will be interrupted.
@@ -626,14 +638,15 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
626638

627639
static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
628640
{
629-
return (rdt_alloc_capable &&
630-
(r->type == RDTCTRL_GROUP) && (t->closid == r->closid));
641+
return (rdt_alloc_capable && (r->type == RDTCTRL_GROUP) &&
642+
resctrl_arch_match_closid(t, r->closid));
631643
}
632644

633645
static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
634646
{
635-
return (rdt_mon_capable &&
636-
(r->type == RDTMON_GROUP) && (t->rmid == r->mon.rmid));
647+
return (rdt_mon_capable && (r->type == RDTMON_GROUP) &&
648+
resctrl_arch_match_rmid(t, r->mon.parent->closid,
649+
r->mon.rmid));
637650
}
638651

639652
/**
@@ -884,15 +897,16 @@ int proc_resctrl_show(struct seq_file *s, struct pid_namespace *ns,
884897
rdtg->mode != RDT_MODE_EXCLUSIVE)
885898
continue;
886899

887-
if (rdtg->closid != tsk->closid)
900+
if (!resctrl_arch_match_closid(tsk, rdtg->closid))
888901
continue;
889902

890903
seq_printf(s, "res:%s%s\n", (rdtg == &rdtgroup_default) ? "/" : "",
891904
rdtg->kn->name);
892905
seq_puts(s, "mon:");
893906
list_for_each_entry(crg, &rdtg->mon.crdtgrp_list,
894907
mon.crdtgrp_list) {
895-
if (tsk->rmid != crg->mon.rmid)
908+
if (!resctrl_arch_match_rmid(tsk, crg->mon.parent->closid,
909+
crg->mon.rmid))
896910
continue;
897911
seq_printf(s, "%s", crg->kn->name);
898912
break;
@@ -2820,8 +2834,8 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
28202834
for_each_process_thread(p, t) {
28212835
if (!from || is_closid_match(t, from) ||
28222836
is_rmid_match(t, from)) {
2823-
WRITE_ONCE(t->closid, to->closid);
2824-
WRITE_ONCE(t->rmid, to->mon.rmid);
2837+
resctrl_arch_set_closid_rmid(t, to->closid,
2838+
to->mon.rmid);
28252839

28262840
/*
28272841
* Order the closid/rmid stores above before the loads

0 commit comments

Comments
 (0)