Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 75408e43509e ("x86/resctrl: Allow different CODE/DATA configurations to be staged")
Suggested-by: Xin Hao <xhao@linux.alibaba.com>
Signed-off-by: Shawn Wang <shawnwang@linux.alibaba.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Tested-by: Reinette Chatre <reinette.chatre@intel.com>
Cc:stable@vger.kernel.org
Link: https://lore.kernel.org/all/2fad13f49fbe89687fc40e9a5a61f23a28d1507a.1673988935.git.reinette.chatre%40intel.com

authored by

Shawn Wang and committed by
Dave Hansen
0424a7df 72f7754d

+24 -9
+2 -5
arch/x86/kernel/cpu/resctrl/ctrlmondata.c
··· 368 368 { 369 369 struct resctrl_schema *s; 370 370 struct rdtgroup *rdtgrp; 371 - struct rdt_domain *dom; 372 371 struct rdt_resource *r; 373 372 char *tok, *resname; 374 373 int ret = 0; ··· 396 397 goto out; 397 398 } 398 399 399 - list_for_each_entry(s, &resctrl_schema_all, list) { 400 - list_for_each_entry(dom, &s->res->domains, list) 401 - memset(dom->staged_config, 0, sizeof(dom->staged_config)); 402 - } 400 + rdt_staged_configs_clear(); 403 401 404 402 while ((tok = strsep(&buf, "\n")) != NULL) { 405 403 resname = strim(strsep(&tok, ":")); ··· 441 445 } 442 446 443 447 out: 448 + rdt_staged_configs_clear(); 444 449 rdtgroup_kn_unlock(of->kn); 445 450 cpus_read_unlock(); 446 451 return ret ?: nbytes;
+1
arch/x86/kernel/cpu/resctrl/internal.h
··· 555 555 void rdt_domain_reconfigure_cdp(struct rdt_resource *r); 556 556 void __init thread_throttle_mode_init(void); 557 557 void __init mbm_config_rftype_init(const char *config); 558 + void rdt_staged_configs_clear(void); 558 559 559 560 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
+21 -4
arch/x86/kernel/cpu/resctrl/rdtgroup.c
··· 78 78 va_end(ap); 79 79 } 80 80 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 + 81 94 /* 82 95 * Trivial allocator for CLOSIDs. Since h/w only supports a small number, 83 96 * we can keep a bitmap of free CLOSIDs in a single integer. ··· 3120 3107 { 3121 3108 struct resctrl_schema *s; 3122 3109 struct rdt_resource *r; 3123 - int ret; 3110 + int ret = 0; 3111 + 3112 + rdt_staged_configs_clear(); 3124 3113 3125 3114 list_for_each_entry(s, &resctrl_schema_all, list) { 3126 3115 r = s->res; ··· 3134 3119 } else { 3135 3120 ret = rdtgroup_init_cat(s, rdtgrp->closid); 3136 3121 if (ret < 0) 3137 - return ret; 3122 + goto out; 3138 3123 } 3139 3124 3140 3125 ret = resctrl_arch_update_domains(r, rdtgrp->closid); 3141 3126 if (ret < 0) { 3142 3127 rdt_last_cmd_puts("Failed to initialize allocations\n"); 3143 - return ret; 3128 + goto out; 3144 3129 } 3145 3130 3146 3131 } 3147 3132 3148 3133 rdtgrp->mode = RDT_MODE_SHAREABLE; 3149 3134 3150 - return 0; 3135 + out: 3136 + rdt_staged_configs_clear(); 3137 + return ret; 3151 3138 } 3152 3139 3153 3140 static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,