File Index
Files and directories
Sign in
FILE

rdtgroup.c

File preview with syntax highlighting.

linux-6.19.14/arch/x86/kernel/cpu/resctrl/rdtgroup.c C
  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
 35DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
 36
 37DEFINE_STATIC_KEY_FALSE(rdt_mon_enable_key);
 38
 39DEFINE_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 */
 47void 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 */
 75static 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
 88void 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
105void 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
118static 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
125static 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
132static 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 */
173void 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
187static 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
202static 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
212int 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
227bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
228{
229	return rdt_resources_all[l].cdp_enabled;
230}
231
232void 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}
~/ Read-only file preview.