From: Tony Luck
Now we populate each directory with a read/write (mode 0644) file
named "cpus". This is used to over-ride the resources available
to processes in the default resource group when running on specific
CPUs. Each "cpus" file reads as a cpumask showing which CPUs belong
to this resource group. Initially all online CPUs are assigned to
the default group. They can be added to other groups by writing a
cpumask to the "cpus" file in the directory for the resource group
(which will remove them from the previous group to which they were
assigned). CPU online/offline operations will delete CPUs that go
offline from whatever group they are in and add new CPUs to the
default group.
If there are CPUs assigned to a group when the directory is removed,
they are returned to the default group.
Signed-off-by: Fenghua Yu
Signed-off-by: Tony Luck
---
arch/x86/include/asm/intel_rdt.h | 5 ++
arch/x86/kernel/cpu/intel_rdt.c | 12 +++
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 127 +++
3 files changed, 144 insertions(+)
diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h
index 7eb8078..6ab31ba 100644
--- a/arch/x86/include/asm/intel_rdt.h
+++ b/arch/x86/include/asm/intel_rdt.h
@@ -9,13 +9,16 @@
* @kn:kernfs node
* @rdtgroup_list: linked list for all rdtgroups
* @closid:closid for this rdtgroup
+ * @cpu_mask: CPUs assigned to this rdtgroup
* @flags: status bits
* @waitcount: how many cpus expect to find this
+ * group when they acquire rdtgroup_mutex
*/
struct rdtgroup {
struct kernfs_node *kn;
struct list_headrdtgroup_list;
int closid;
+ struct cpumask cpu_mask;
int flags;
atomic_twaitcount;
};
@@ -148,6 +151,8 @@ union cpuid_0x10_1_edx {
unsigned int full;
};
+DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+
void rdt_cbm_update(void *arg);
struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
void rdtgroup_kn_unlock(struct kernfs_node *kn);
diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c
index 3d4a125..556a426 100644
--- a/arch/x86/kernel/cpu/intel_rdt.c
+++ b/arch/x86/kernel/cpu/intel_rdt.c
@@ -36,6 +36,8 @@
/* Mutex to protect rdtgroup access. */
DEFINE_MUTEX(rdtgroup_mutex);
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+
#define domain_init(name) LIST_HEAD_INIT(rdt_resources_all[name].domains)
struct rdt_resource rdt_resources_all[] = {
@@ -242,8 +244,11 @@ static int intel_rdt_online_cpu(unsigned int cpu)
struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
mutex_lock(&rdtgroup_mutex);
+ per_cpu(cpu_closid, cpu) = 0;
for_each_rdt_resource(r)
update_domain(cpu, r, 1);
+ /* The cpu is set in default rdtgroup after online. */
+ cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
state->closid = 0;
wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
mutex_unlock(&rdtgroup_mutex);
@@ -254,10 +259,17 @@ static int intel_rdt_online_cpu(unsigned int cpu)
static int intel_rdt_offline_cpu(unsigned int cpu)
{
struct rdt_resource *r;
+ struct rdtgroup *rdtgrp;
+ struct list_head *l;
mutex_lock(&rdtgroup_mutex);
for_each_rdt_resource(r)
update_domain(cpu, r, 0);
+ list_for_each(l, &rdt_all_groups) {
+ rdtgrp = list_entry(l, struct rdtgroup, rdtgroup_list);
+ if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
+ break;
+ }
mutex_unlock(&rdtgroup_mutex);
return 0;
diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
index 9e0044d..f2d7a3a 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -20,6 +20,7 @@
#define pr_fmt(fmt)KBUILD_MODNAME ": " fmt
+#include
#include
#include
#include
@@ -180,6 +181,117 @@ static struct kernfs_ops rdtgroup_kf_single_ops = {
.seq_show = rdtgroup_seqfile_show,
};
+static int rdtgroup_cpus_show(struct kernfs_open_file *of,
+ struct seq_file *s, void *v)
+{
+ struct rdtgroup *rdtgrp;
+ int ret = 0;
+
+ rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+ if (rdtgrp)
+ seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask));
+ else
+ ret = -ENOENT;
+ rdtgroup_kn_unlock(of->kn);
+
+ return ret;
+}
+
+static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes, loff_t off)
+{
+ struct rdtgroup *rdtgrp, *r;
+ cpumask_var_t tmpmask, newmask;
+ int ret, cpu;