Skip to content

Commit 0424a7d

Browse files
Shawn Wanghansendc
authored andcommitted
x86/resctrl: Clear staged_config[] before and after it is used
As a temporary storage, staged_config[] in rdt_domain should be cleared before and after it is used. The stale value in staged_config[] could cause an MSR access error. Here is a reproducer on a system with 16 usable CLOSIDs for a 15-way L3 Cache (MBA should be disabled if the number of CLOSIDs for MB is less than 16.) : mount -t resctrl resctrl -o cdp /sys/fs/resctrl mkdir /sys/fs/resctrl/p{1..7} umount /sys/fs/resctrl/ mount -t resctrl resctrl /sys/fs/resctrl mkdir /sys/fs/resctrl/p{1..8} An error occurs when creating resource group named p8: unchecked MSR access error: WRMSR to 0xca0 (tried to write 0x00000000000007ff) at rIP: 0xffffffff82249142 (cat_wrmsr+0x32/0x60) Call Trace: <IRQ> __flush_smp_call_function_queue+0x11d/0x170 __sysvec_call_function+0x24/0xd0 sysvec_call_function+0x89/0xc0 </IRQ> <TASK> asm_sysvec_call_function+0x16/0x20 When creating a new resource control group, hardware will be configured by the following process: rdtgroup_mkdir() rdtgroup_mkdir_ctrl_mon() rdtgroup_init_alloc() resctrl_arch_update_domains() resctrl_arch_update_domains() iterates and updates all resctrl_conf_type whose have_new_ctrl is true. Since staged_config[] holds the same values as when CDP was enabled, it will continue to update the CDP_CODE and CDP_DATA configurations. When group p8 is created, get_config_index() called in resctrl_arch_update_domains() will return 16 and 17 as the CLOSIDs for CDP_CODE and CDP_DATA, which will be translated to an invalid register - 0xca0 in this scenario. Fix it by clearing staged_config[] before and after it is used. [reinette: re-order commit tags] Fixes: 75408e4 ("x86/resctrl: Allow different CODE/DATA configurations to be staged") Suggested-by: Xin Hao <[email protected]> Signed-off-by: Shawn Wang <[email protected]> Signed-off-by: Reinette Chatre <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Tested-by: Reinette Chatre <[email protected]> Cc:[email protected] Link: https://lore.kernel.org/all/2fad13f49fbe89687fc40e9a5a61f23a28d1507a.1673988935.git.reinette.chatre%40intel.com
1 parent 72f7754 commit 0424a7d

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
368368
{
369369
struct resctrl_schema *s;
370370
struct rdtgroup *rdtgrp;
371-
struct rdt_domain *dom;
372371
struct rdt_resource *r;
373372
char *tok, *resname;
374373
int ret = 0;
@@ -397,10 +396,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
397396
goto out;
398397
}
399398

400-
list_for_each_entry(s, &resctrl_schema_all, list) {
401-
list_for_each_entry(dom, &s->res->domains, list)
402-
memset(dom->staged_config, 0, sizeof(dom->staged_config));
403-
}
399+
rdt_staged_configs_clear();
404400

405401
while ((tok = strsep(&buf, "\n")) != NULL) {
406402
resname = strim(strsep(&tok, ":"));
@@ -445,6 +441,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
445441
}
446442

447443
out:
444+
rdt_staged_configs_clear();
448445
rdtgroup_kn_unlock(of->kn);
449446
cpus_read_unlock();
450447
return ret ?: nbytes;

arch/x86/kernel/cpu/resctrl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,5 +555,6 @@ void __check_limbo(struct rdt_domain *d, bool force_free);
555555
void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
556556
void __init thread_throttle_mode_init(void);
557557
void __init mbm_config_rftype_init(const char *config);
558+
void rdt_staged_configs_clear(void);
558559

559560
#endif /* _ASM_X86_RESCTRL_INTERNAL_H */

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ void rdt_last_cmd_printf(const char *fmt, ...)
7878
va_end(ap);
7979
}
8080

81+
void rdt_staged_configs_clear(void)
82+
{
83+
struct rdt_resource *r;
84+
struct rdt_domain *dom;
85+
86+
lockdep_assert_held(&rdtgroup_mutex);
87+
88+
for_each_alloc_capable_rdt_resource(r) {
89+
list_for_each_entry(dom, &r->domains, list)
90+
memset(dom->staged_config, 0, sizeof(dom->staged_config));
91+
}
92+
}
93+
8194
/*
8295
* Trivial allocator for CLOSIDs. Since h/w only supports a small number,
8396
* we can keep a bitmap of free CLOSIDs in a single integer.
@@ -3107,7 +3120,9 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
31073120
{
31083121
struct resctrl_schema *s;
31093122
struct rdt_resource *r;
3110-
int ret;
3123+
int ret = 0;
3124+
3125+
rdt_staged_configs_clear();
31113126

31123127
list_for_each_entry(s, &resctrl_schema_all, list) {
31133128
r = s->res;
@@ -3119,20 +3134,22 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
31193134
} else {
31203135
ret = rdtgroup_init_cat(s, rdtgrp->closid);
31213136
if (ret < 0)
3122-
return ret;
3137+
goto out;
31233138
}
31243139

31253140
ret = resctrl_arch_update_domains(r, rdtgrp->closid);
31263141
if (ret < 0) {
31273142
rdt_last_cmd_puts("Failed to initialize allocations\n");
3128-
return ret;
3143+
goto out;
31293144
}
31303145

31313146
}
31323147

31333148
rdtgrp->mode = RDT_MODE_SHAREABLE;
31343149

3135-
return 0;
3150+
out:
3151+
rdt_staged_configs_clear();
3152+
return ret;
31363153
}
31373154

31383155
static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,

0 commit comments

Comments
 (0)