Skip to content

Commit 5ff193f

Browse files
Fenghua YuKAGA-KOKO
authored andcommitted
x86/intel_rdt: Add basic resctrl filesystem support
Use kernfs as basis for our user interface filesystem. This patch supports mount/umount, and one mount parameter "cdp" to enable code/data prioritization (though all we do at this point is ensure that the system can support CDP). The file system is not populated yet in this patch. [ tglx: Fixed up a few nits and added cdp handling in case of error ] Signed-off-by: Fenghua Yu <[email protected]> Cc: "Ravi V Shankar" <[email protected]> Cc: "Tony Luck" <[email protected]> Cc: "Shaohua Li" <[email protected]> Cc: "Sai Prakhya" <[email protected]> Cc: "Peter Zijlstra" <[email protected]> Cc: "Stephane Eranian" <[email protected]> Cc: "Dave Hansen" <[email protected]> Cc: "David Carrillo-Cisneros" <[email protected]> Cc: "Nilay Vaish" <[email protected]> Cc: "Vikas Shivappa" <[email protected]> Cc: "Ingo Molnar" <[email protected]> Cc: "Borislav Petkov" <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 2264d9c commit 5ff193f

File tree

5 files changed

+306
-2
lines changed

5 files changed

+306
-2
lines changed

arch/x86/include/asm/intel_rdt.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
#ifndef _ASM_X86_INTEL_RDT_H
22
#define _ASM_X86_INTEL_RDT_H
33

4+
#include <linux/jump_label.h>
5+
6+
#define IA32_L3_QOS_CFG 0xc81
47
#define IA32_L3_CBM_BASE 0xc90
58
#define IA32_L2_CBM_BASE 0xd10
69

10+
#define L3_QOS_CDP_ENABLE 0x01ULL
11+
12+
/**
13+
* struct rdtgroup - store rdtgroup's data in resctrl file system.
14+
* @kn: kernfs node
15+
* @rdtgroup_list: linked list for all rdtgroups
16+
* @closid: closid for this rdtgroup
17+
*/
18+
struct rdtgroup {
19+
struct kernfs_node *kn;
20+
struct list_head rdtgroup_list;
21+
int closid;
22+
};
23+
24+
/* List of all resource groups */
25+
extern struct list_head rdt_all_groups;
26+
27+
int __init rdtgroup_init(void);
28+
729
/**
830
* struct rdt_resource - attributes of an RDT resource
931
* @enabled: Is this feature enabled on this machine
@@ -68,6 +90,10 @@ struct msr_param {
6890
extern struct mutex rdtgroup_mutex;
6991

7092
extern struct rdt_resource rdt_resources_all[];
93+
extern struct rdtgroup rdtgroup_default;
94+
DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
95+
96+
int __init rdtgroup_init(void);
7197

7298
enum {
7399
RDT_RESOURCE_L3,

arch/x86/kernel/cpu/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o
3434
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
3535
obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
3636

37-
obj-$(CONFIG_INTEL_RDT_A) += intel_rdt.o
37+
obj-$(CONFIG_INTEL_RDT_A) += intel_rdt.o intel_rdt_rdtgroup.o
3838

3939
obj-$(CONFIG_X86_MCE) += mcheck/
4040
obj-$(CONFIG_MTRR) += mtrr/

arch/x86/kernel/cpu/intel_rdt.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ static int intel_rdt_offline_cpu(unsigned int cpu)
361361
static int __init intel_rdt_late_init(void)
362362
{
363363
struct rdt_resource *r;
364-
int state;
364+
int state, ret;
365365

366366
if (!get_rdt_resources())
367367
return -ENODEV;
@@ -372,6 +372,12 @@ static int __init intel_rdt_late_init(void)
372372
if (state < 0)
373373
return state;
374374

375+
ret = rdtgroup_init();
376+
if (ret) {
377+
cpuhp_remove_state(state);
378+
return ret;
379+
}
380+
375381
for_each_capable_rdt_resource(r)
376382
pr_info("Intel RDT %s allocation detected\n", r->name);
377383

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
/*
2+
* User interface for Resource Alloction in Resource Director Technology(RDT)
3+
*
4+
* Copyright (C) 2016 Intel Corporation
5+
*
6+
* Author: Fenghua Yu <[email protected]>
7+
*
8+
* This program is free software; you can redistribute it and/or modify it
9+
* under the terms and conditions of the GNU General Public License,
10+
* version 2, as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15+
* more details.
16+
*
17+
* More information about RDT be found in the Intel (R) x86 Architecture
18+
* Software Developer Manual.
19+
*/
20+
21+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22+
23+
#include <linux/fs.h>
24+
#include <linux/sysfs.h>
25+
#include <linux/kernfs.h>
26+
#include <linux/slab.h>
27+
28+
#include <uapi/linux/magic.h>
29+
30+
#include <asm/intel_rdt.h>
31+
32+
DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
33+
struct kernfs_root *rdt_root;
34+
struct rdtgroup rdtgroup_default;
35+
LIST_HEAD(rdt_all_groups);
36+
37+
static void l3_qos_cfg_update(void *arg)
38+
{
39+
bool *enable = arg;
40+
41+
wrmsrl(IA32_L3_QOS_CFG, *enable ? L3_QOS_CDP_ENABLE : 0ULL);
42+
}
43+
44+
static int set_l3_qos_cfg(struct rdt_resource *r, bool enable)
45+
{
46+
cpumask_var_t cpu_mask;
47+
struct rdt_domain *d;
48+
int cpu;
49+
50+
if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
51+
return -ENOMEM;
52+
53+
list_for_each_entry(d, &r->domains, list) {
54+
/* Pick one CPU from each domain instance to update MSR */
55+
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
56+
}
57+
cpu = get_cpu();
58+
/* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */
59+
if (cpumask_test_cpu(cpu, cpu_mask))
60+
l3_qos_cfg_update(&enable);
61+
/* Update QOS_CFG MSR on all other cpus in cpu_mask. */
62+
smp_call_function_many(cpu_mask, l3_qos_cfg_update, &enable, 1);
63+
put_cpu();
64+
65+
free_cpumask_var(cpu_mask);
66+
67+
return 0;
68+
}
69+
70+
static int cdp_enable(void)
71+
{
72+
struct rdt_resource *r_l3data = &rdt_resources_all[RDT_RESOURCE_L3DATA];
73+
struct rdt_resource *r_l3code = &rdt_resources_all[RDT_RESOURCE_L3CODE];
74+
struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
75+
int ret;
76+
77+
if (!r_l3->capable || !r_l3data->capable || !r_l3code->capable)
78+
return -EINVAL;
79+
80+
ret = set_l3_qos_cfg(r_l3, true);
81+
if (!ret) {
82+
r_l3->enabled = false;
83+
r_l3data->enabled = true;
84+
r_l3code->enabled = true;
85+
}
86+
return ret;
87+
}
88+
89+
static void cdp_disable(void)
90+
{
91+
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
92+
93+
r->enabled = r->capable;
94+
95+
if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled) {
96+
rdt_resources_all[RDT_RESOURCE_L3DATA].enabled = false;
97+
rdt_resources_all[RDT_RESOURCE_L3CODE].enabled = false;
98+
set_l3_qos_cfg(r, false);
99+
}
100+
}
101+
102+
static int parse_rdtgroupfs_options(char *data)
103+
{
104+
char *token, *o = data;
105+
int ret = 0;
106+
107+
while ((token = strsep(&o, ",")) != NULL) {
108+
if (!*token)
109+
return -EINVAL;
110+
111+
if (!strcmp(token, "cdp"))
112+
ret = cdp_enable();
113+
}
114+
115+
return ret;
116+
}
117+
118+
static struct dentry *rdt_mount(struct file_system_type *fs_type,
119+
int flags, const char *unused_dev_name,
120+
void *data)
121+
{
122+
struct dentry *dentry;
123+
int ret;
124+
125+
mutex_lock(&rdtgroup_mutex);
126+
/*
127+
* resctrl file system can only be mounted once.
128+
*/
129+
if (static_branch_unlikely(&rdt_enable_key)) {
130+
dentry = ERR_PTR(-EBUSY);
131+
goto out;
132+
}
133+
134+
ret = parse_rdtgroupfs_options(data);
135+
if (ret) {
136+
dentry = ERR_PTR(ret);
137+
goto out_cdp;
138+
}
139+
140+
dentry = kernfs_mount(fs_type, flags, rdt_root,
141+
RDTGROUP_SUPER_MAGIC, NULL);
142+
if (IS_ERR(dentry))
143+
goto out_cdp;
144+
145+
static_branch_enable(&rdt_enable_key);
146+
goto out;
147+
148+
out_cdp:
149+
cdp_disable();
150+
out:
151+
mutex_unlock(&rdtgroup_mutex);
152+
153+
return dentry;
154+
}
155+
156+
static int reset_all_cbms(struct rdt_resource *r)
157+
{
158+
struct msr_param msr_param;
159+
cpumask_var_t cpu_mask;
160+
struct rdt_domain *d;
161+
int i, cpu;
162+
163+
if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
164+
return -ENOMEM;
165+
166+
msr_param.res = r;
167+
msr_param.low = 0;
168+
msr_param.high = r->num_closid;
169+
170+
/*
171+
* Disable resource control for this resource by setting all
172+
* CBMs in all domains to the maximum mask value. Pick one CPU
173+
* from each domain to update the MSRs below.
174+
*/
175+
list_for_each_entry(d, &r->domains, list) {
176+
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
177+
178+
for (i = 0; i < r->num_closid; i++)
179+
d->cbm[i] = r->max_cbm;
180+
}
181+
cpu = get_cpu();
182+
/* Update CBM on this cpu if it's in cpu_mask. */
183+
if (cpumask_test_cpu(cpu, cpu_mask))
184+
rdt_cbm_update(&msr_param);
185+
/* Update CBM on all other cpus in cpu_mask. */
186+
smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1);
187+
put_cpu();
188+
189+
free_cpumask_var(cpu_mask);
190+
191+
return 0;
192+
}
193+
194+
static void rdt_kill_sb(struct super_block *sb)
195+
{
196+
struct rdt_resource *r;
197+
198+
mutex_lock(&rdtgroup_mutex);
199+
200+
/*Put everything back to default values. */
201+
for_each_enabled_rdt_resource(r)
202+
reset_all_cbms(r);
203+
cdp_disable();
204+
static_branch_disable(&rdt_enable_key);
205+
kernfs_kill_sb(sb);
206+
mutex_unlock(&rdtgroup_mutex);
207+
}
208+
209+
static struct file_system_type rdt_fs_type = {
210+
.name = "resctrl",
211+
.mount = rdt_mount,
212+
.kill_sb = rdt_kill_sb,
213+
};
214+
215+
static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
216+
};
217+
218+
static int __init rdtgroup_setup_root(void)
219+
{
220+
rdt_root = kernfs_create_root(&rdtgroup_kf_syscall_ops,
221+
KERNFS_ROOT_CREATE_DEACTIVATED,
222+
&rdtgroup_default);
223+
if (IS_ERR(rdt_root))
224+
return PTR_ERR(rdt_root);
225+
226+
mutex_lock(&rdtgroup_mutex);
227+
228+
rdtgroup_default.closid = 0;
229+
list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
230+
231+
rdtgroup_default.kn = rdt_root->kn;
232+
kernfs_activate(rdtgroup_default.kn);
233+
234+
mutex_unlock(&rdtgroup_mutex);
235+
236+
return 0;
237+
}
238+
239+
/*
240+
* rdtgroup_init - rdtgroup initialization
241+
*
242+
* Setup resctrl file system including set up root, create mount point,
243+
* register rdtgroup filesystem, and initialize files under root directory.
244+
*
245+
* Return: 0 on success or -errno
246+
*/
247+
int __init rdtgroup_init(void)
248+
{
249+
int ret = 0;
250+
251+
ret = rdtgroup_setup_root();
252+
if (ret)
253+
return ret;
254+
255+
ret = sysfs_create_mount_point(fs_kobj, "resctrl");
256+
if (ret)
257+
goto cleanup_root;
258+
259+
ret = register_filesystem(&rdt_fs_type);
260+
if (ret)
261+
goto cleanup_mountpoint;
262+
263+
return 0;
264+
265+
cleanup_mountpoint:
266+
sysfs_remove_mount_point(fs_kobj, "resctrl");
267+
cleanup_root:
268+
kernfs_destroy_root(rdt_root);
269+
270+
return ret;
271+
}

include/uapi/linux/magic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#define CGROUP_SUPER_MAGIC 0x27e0eb
5858
#define CGROUP2_SUPER_MAGIC 0x63677270
5959

60+
#define RDTGROUP_SUPER_MAGIC 0x7655821
6061

6162
#define STACK_END_MAGIC 0x57AC6E9D
6263

0 commit comments

Comments
 (0)