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

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 <fenghua.yu@intel.com>
Cc: "Ravi V Shankar" <ravi.v.shankar@intel.com>
Cc: "Tony Luck" <tony.luck@intel.com>
Cc: "Shaohua Li" <shli@fb.com>
Cc: "Sai Prakhya" <sai.praneeth.prakhya@intel.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>
Cc: "Stephane Eranian" <eranian@google.com>
Cc: "Dave Hansen" <dave.hansen@intel.com>
Cc: "David Carrillo-Cisneros" <davidcc@google.com>
Cc: "Nilay Vaish" <nilayvaish@gmail.com>
Cc: "Vikas Shivappa" <vikas.shivappa@linux.intel.com>
Cc: "Ingo Molnar" <mingo@elte.hu>
Cc: "Borislav Petkov" <bp@suse.de>
Cc: "H. Peter Anvin" <h.peter.anvin@intel.com>
Link: http://lkml.kernel.org/r/1477692289-37412-4-git-send-email-fenghua.yu@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Fenghua Yu and committed by
Thomas Gleixner
5ff193fb 2264d9c7

+306 -2
+26
arch/x86/include/asm/intel_rdt.h
··· 1 1 #ifndef _ASM_X86_INTEL_RDT_H 2 2 #define _ASM_X86_INTEL_RDT_H 3 3 4 + #include <linux/jump_label.h> 5 + 6 + #define IA32_L3_QOS_CFG 0xc81 4 7 #define IA32_L3_CBM_BASE 0xc90 5 8 #define IA32_L2_CBM_BASE 0xd10 9 + 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); 6 28 7 29 /** 8 30 * struct rdt_resource - attributes of an RDT resource ··· 90 68 extern struct mutex rdtgroup_mutex; 91 69 92 70 extern struct rdt_resource rdt_resources_all[]; 71 + extern struct rdtgroup rdtgroup_default; 72 + DECLARE_STATIC_KEY_FALSE(rdt_enable_key); 73 + 74 + int __init rdtgroup_init(void); 93 75 94 76 enum { 95 77 RDT_RESOURCE_L3,
+1 -1
arch/x86/kernel/cpu/Makefile
··· 34 34 obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o 35 35 obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o 36 36 37 - obj-$(CONFIG_INTEL_RDT_A) += intel_rdt.o 37 + obj-$(CONFIG_INTEL_RDT_A) += intel_rdt.o intel_rdt_rdtgroup.o 38 38 39 39 obj-$(CONFIG_X86_MCE) += mcheck/ 40 40 obj-$(CONFIG_MTRR) += mtrr/
+7 -1
arch/x86/kernel/cpu/intel_rdt.c
··· 361 361 static int __init intel_rdt_late_init(void) 362 362 { 363 363 struct rdt_resource *r; 364 - int state; 364 + int state, ret; 365 365 366 366 if (!get_rdt_resources()) 367 367 return -ENODEV; ··· 371 371 intel_rdt_online_cpu, intel_rdt_offline_cpu); 372 372 if (state < 0) 373 373 return state; 374 + 375 + ret = rdtgroup_init(); 376 + if (ret) { 377 + cpuhp_remove_state(state); 378 + return ret; 379 + } 374 380 375 381 for_each_capable_rdt_resource(r) 376 382 pr_info("Intel RDT %s allocation detected\n", r->name);
+271
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
··· 1 + /* 2 + * User interface for Resource Alloction in Resource Director Technology(RDT) 3 + * 4 + * Copyright (C) 2016 Intel Corporation 5 + * 6 + * Author: Fenghua Yu <fenghua.yu@intel.com> 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 + }
+1
include/uapi/linux/magic.h
··· 57 57 #define CGROUP_SUPER_MAGIC 0x27e0eb 58 58 #define CGROUP2_SUPER_MAGIC 0x63677270 59 59 60 + #define RDTGROUP_SUPER_MAGIC 0x7655821 60 61 61 62 #define STACK_END_MAGIC 0x57AC6E9D 62 63