1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * User interface for Resource Allocation in Resource Director Technology(RDT)
4 *
5 * Copyright (C) 2016 Intel Corporation
6 *
7 * Author: Fenghua Yu <fenghua.yu@intel.com>
8 *
9 * More information about RDT be found in the Intel (R) x86 Architecture
10 * Software Developer Manual.
11 */
12
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15 #include <linux/cpu.h>
16 #include <linux/debugfs.h>
17 #include <linux/fs.h>
18 #include <linux/fs_parser.h>
19 #include <linux/sysfs.h>
20 #include <linux/kernfs.h>
21 #include <linux/resctrl.h>
22 #include <linux/seq_buf.h>
23 #include <linux/seq_file.h>
24 #include <linux/sched/signal.h>
25 #include <linux/sched/task.h>
26 #include <linux/slab.h>
27 #include <linux/task_work.h>
28 #include <linux/user_namespace.h>
29
30 #include <uapi/linux/magic.h>
31
32 #include <asm/msr.h>
33 #include "internal.h"
34
35 DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
36
37 DEFINE_STATIC_KEY_FALSE(rdt_mon_enable_key);
38
39 DEFINE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
40
41 /*
42 * This is safe against resctrl_arch_sched_in() called from __switch_to()
43 * because __switch_to() is executed with interrupts disabled. A local call
44 * from update_closid_rmid() is protected against __switch_to() because
45 * preemption is disabled.
46 */
resctrl_arch_sync_cpu_closid_rmid(void * info)47 void resctrl_arch_sync_cpu_closid_rmid(void *info)
48 {
49 struct resctrl_cpu_defaults *r = info;
50
51 if (r) {
52 this_cpu_write(pqr_state.default_closid, r->closid);
53 this_cpu_write(pqr_state.default_rmid, r->rmid);
54 }
55
56 /*
57 * We cannot unconditionally write the MSR because the current
58 * executing task might have its own closid selected. Just reuse
59 * the context switch code.
60 */
61 resctrl_arch_sched_in(current);
62 }
63
64 #define INVALID_CONFIG_INDEX UINT_MAX
65
66 /**
67 * mon_event_config_index_get - get the hardware index for the
68 * configurable event
69 * @evtid: event id.
70 *
71 * Return: 0 for evtid == QOS_L3_MBM_TOTAL_EVENT_ID
72 * 1 for evtid == QOS_L3_MBM_LOCAL_EVENT_ID
73 * INVALID_CONFIG_INDEX for invalid evtid
74 */
mon_event_config_index_get(u32 evtid)75 static inline unsigned int mon_event_config_index_get(u32 evtid)
76 {
77 switch (evtid) {
78 case QOS_L3_MBM_TOTAL_EVENT_ID:
79 return 0;
80 case QOS_L3_MBM_LOCAL_EVENT_ID:
81 return 1;
82 default:
83 /* Should never reach here */
84 return INVALID_CONFIG_INDEX;
85 }
86 }
87
resctrl_arch_mon_event_config_read(void * _config_info)88 void resctrl_arch_mon_event_config_read(void *_config_info)
89 {
90 struct resctrl_mon_config_info *config_info = _config_info;
91 unsigned int index;
92 u64 msrval;
93
94 index = mon_event_config_index_get(config_info->evtid);
95 if (index == INVALID_CONFIG_INDEX) {
96 pr_warn_once("Invalid event id %d\n", config_info->evtid);
97 return;
98 }
99 rdmsrq(MSR_IA32_EVT_CFG_BASE + index, msrval);
100
101 /* Report only the valid event configuration bits */
102 config_info->mon_config = msrval & MAX_EVT_CONFIG_BITS;
103 }
104
resctrl_arch_mon_event_config_write(void * _config_info)105 void resctrl_arch_mon_event_config_write(void *_config_info)
106 {
107 struct resctrl_mon_config_info *config_info = _config_info;
108 unsigned int index;
109
110 index = mon_event_config_index_get(config_info->evtid);
111 if (index == INVALID_CONFIG_INDEX) {
112 pr_warn_once("Invalid event id %d\n", config_info->evtid);
113 return;
114 }
115 wrmsrq(MSR_IA32_EVT_CFG_BASE + index, config_info->mon_config);
116 }
117
l3_qos_cfg_update(void * arg)118 static void l3_qos_cfg_update(void *arg)
119 {
120 bool *enable = arg;
121
122 wrmsrq(MSR_IA32_L3_QOS_CFG, *enable ? L3_QOS_CDP_ENABLE : 0ULL);
123 }
124
l2_qos_cfg_update(void * arg)125 static void l2_qos_cfg_update(void *arg)
126 {
127 bool *enable = arg;
128
129 wrmsrq(MSR_IA32_L2_QOS_CFG, *enable ? L2_QOS_CDP_ENABLE : 0ULL);
130 }
131
set_cache_qos_cfg(int level,bool enable)132 static int set_cache_qos_cfg(int level, bool enable)
133 {
134 void (*update)(void *arg);
135 struct rdt_ctrl_domain *d;
136 struct rdt_resource *r_l;
137 cpumask_var_t cpu_mask;
138 int cpu;
139
140 /* Walking r->domains, ensure it can't race with cpuhp */
141 lockdep_assert_cpus_held();
142
143 if (level == RDT_RESOURCE_L3)
144 update = l3_qos_cfg_update;
145 else if (level == RDT_RESOURCE_L2)
146 update = l2_qos_cfg_update;
147 else
148 return -EINVAL;
149
150 if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
151 return -ENOMEM;
152
153 r_l = &rdt_resources_all[level].r_resctrl;
154 list_for_each_entry(d, &r_l->ctrl_domains, hdr.list) {
155 if (r_l->cache.arch_has_per_cpu_cfg)
156 /* Pick all the CPUs in the domain instance */
157 for_each_cpu(cpu, &d->hdr.cpu_mask)
158 cpumask_set_cpu(cpu, cpu_mask);
159 else
160 /* Pick one CPU from each domain instance to update MSR */
161 cpumask_set_cpu(cpumask_any(&d->hdr.cpu_mask), cpu_mask);
162 }
163
164 /* Update QOS_CFG MSR on all the CPUs in cpu_mask */
165 on_each_cpu_mask(cpu_mask, update, &enable, 1);
166
167 free_cpumask_var(cpu_mask);
168
169 return 0;
170 }
171
172 /* Restore the qos cfg state when a domain comes online */
rdt_domain_reconfigure_cdp(struct rdt_resource * r)173 void rdt_domain_reconfigure_cdp(struct rdt_resource *r)
174 {
175 struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
176
177 if (!r->cdp_capable)
178 return;
179
180 if (r->rid == RDT_RESOURCE_L2)
181 l2_qos_cfg_update(&hw_res->cdp_enabled);
182
183 if (r->rid == RDT_RESOURCE_L3)
184 l3_qos_cfg_update(&hw_res->cdp_enabled);
185 }
186
cdp_enable(int level)187 static int cdp_enable(int level)
188 {
189 struct rdt_resource *r_l = &rdt_resources_all[level].r_resctrl;
190 int ret;
191
192 if (!r_l->alloc_capable)
193 return -EINVAL;
194
195 ret = set_cache_qos_cfg(level, true);
196 if (!ret)
197 rdt_resources_all[level].cdp_enabled = true;
198
199 return ret;
200 }
201
cdp_disable(int level)202 static void cdp_disable(int level)
203 {
204 struct rdt_hw_resource *r_hw = &rdt_resources_all[level];
205
206 if (r_hw->cdp_enabled) {
207 set_cache_qos_cfg(level, false);
208 r_hw->cdp_enabled = false;
209 }
210 }
211
resctrl_arch_set_cdp_enabled(enum resctrl_res_level l,bool enable)212 int resctrl_arch_set_cdp_enabled(enum resctrl_res_level l, bool enable)
213 {
214 struct rdt_hw_resource *hw_res = &rdt_resources_all[l];
215
216 if (!hw_res->r_resctrl.cdp_capable)
217 return -EINVAL;
218
219 if (enable)
220 return cdp_enable(l);
221
222 cdp_disable(l);
223
224 return 0;
225 }
226
resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)227 bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
228 {
229 return rdt_resources_all[l].cdp_enabled;
230 }
231
resctrl_arch_reset_all_ctrls(struct rdt_resource * r)232 void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
233 {
234 struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
235 struct rdt_hw_ctrl_domain *hw_dom;
236 struct msr_param msr_param;
237 struct rdt_ctrl_domain *d;
238 int i;
239
240 /* Walking r->domains, ensure it can't race with cpuhp */
241 lockdep_assert_cpus_held();
242
243 msr_param.res = r;
244 msr_param.low = 0;
245 msr_param.high = hw_res->num_closid;
246
247 /*
248 * Disable resource control for this resource by setting all
249 * CBMs in all ctrl_domains to the maximum mask value. Pick one CPU
250 * from each domain to update the MSRs below.
251 */
252 list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
253 hw_dom = resctrl_to_arch_ctrl_dom(d);
254
255 for (i = 0; i < hw_res->num_closid; i++)
256 hw_dom->ctrl_val[i] = resctrl_get_default_ctrl(r);
257 msr_param.dom = d;
258 smp_call_function_any(&d->hdr.cpu_mask, rdt_ctrl_update, &msr_param, 1);
259 }
260
261 return;
262 }
263