Skip to contentSkip to conversation

Cqm3 patch series(along with MBM support)

PATCH In review Vikas Shivappa 5 participants 68 messages Jul 25, 2017 – Aug 2, 2017

Subsystems (8)
Documentation x86 BPF perf events +4 more subsystems
lore
Share & tools
lore
#0 lore raw

v2 cover Cqm3 patch series(along with MBM support)

Sending the V2 series to address all the feedback that was received in V1. Apart from that this series adds a patch from Reinette to fix a global declaration in existing RDT and also fixes some issues where the prq MSR was not updated when masks or tasks were moved in some cases and some cleanups.

Acknowledgements:
- Thanks to Thomas for all the feedback on the requirements and design.
- Thanks to Stephane Eranian <[email protected]> and David Carrillo-Cisneros <[email protected]> for going through all the churning during requirements and design phase and code reviews.

Patches are based on 4.12

Changes in V2 as per the feedback:
Thanks to Thomas and PeterZ for all the feedback and suggest a lot of improvements that can be done.
- Improved the RMID limbo list handling to not spend too much time in the IPIs.
- Fixed a lot of coding convention issues and added comments to better explain the code.
- Changed naming of the globals to better indicate the enabling and detecting of features and better organize init code.
- Changed closid to u32 instead of int.
- Made new patches to split the existing ones to make it more readable
- Added functions to contain the reuse code.
- Separated the monitor only related bits from the control and monitor structure to make it clear in the code that the monitor rdtgroup and the control groups are different.

Reinette Chatre (1):
x86/intel_rdt: Mark rdt_root and closid_alloc as static

Tony Luck (2):
x86/intel_rdt: Simplify info and base file lists x86/intel_rdt/mbm: Basic counting of MBM events (total and local)

Vikas Shivappa (25):
x86/perf/cqm: Wipe out perf based cqm x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring x86/intel_rdt: Introduce a common compile option for RDT x86/intel_rdt: Change file names to accommodate RDT monitor code x86/intel_rdt: Cleanup namespace to support RDT monitoring x86/intel_rdt: make rdt_resources_all more readable x86/intel_rdt/cqm: Add RDT monitoring initialization x86/intel_rdt/cqm: Add RMID(Resource monitoring ID) management x86/intel_rdt/cqm: Add info files for RDT monitoring x86/intel_rdt: Prepare for RDT monitoring mkdir support x86/intel_rdt/cqm: Add mkdir support for RDT monitoring x86/intel_rdt: Change closid type from int to u32 x86/intel_rdt/cqm: Add tasks file support x86/intel_rdt: Prepare to add RDT monitor cpus file support x86/intel_rdt/cqm: Add cpus file support x86/intel_rdt: Prepare for RDT monitor data support x86/intel_rdt/cqm: Add mon_data
x86/intel_rdt: Separate the ctrl bits from rmdir x86/intel_rdt/cqm: Add rmdir support x86/intel_rdt/cqm: Add mount,umount support x86/intel_rdt: Introduce rdt_enable_key for scheduling x86/intel_rdt/cqm: Add sched_in support x86/intel_rdt/cqm: Add hotcpu support x86/intel_rdt/mbm: Add mbm counter initialization x86/intel_rdt/mbm: Handle counter overflow

 Documentation/x86/intel_rdt_ui.txt          |  316 ++++-
 MAINTAINERS                                 |    2 +-
 arch/x86/Kconfig                            |   12 +-
 arch/x86/events/intel/Makefile              |    2 +-
 arch/x86/events/intel/cqm.c                 | 1766 ---------------------------
 arch/x86/include/asm/intel_rdt.h            |  286 -----
 arch/x86/include/asm/intel_rdt_common.h     |   27 -
 arch/x86/include/asm/intel_rdt_sched.h      |   88 ++
 arch/x86/kernel/cpu/Makefile                |    2 +-
 arch/x86/kernel/cpu/intel_rdt.c             |  217 +++-
 arch/x86/kernel/cpu/intel_rdt.h             |  425 +++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c |  341 ++++++
 arch/x86/kernel/cpu/intel_rdt_monitor.c     |  523 ++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c    | 1116 +++++++++++++----
 arch/x86/kernel/cpu/intel_rdt_schemata.c    |  286 -----
 arch/x86/kernel/process_32.c                |    2 +-
 arch/x86/kernel/process_64.c                |    2 +-
 include/linux/perf_event.h                  |   18 -
 include/linux/sched.h                       |    5 +-
 kernel/events/core.c                        |   11 +-
 kernel/trace/bpf_trace.c                    |    2 +-
 21 files changed, 2765 insertions(+), 2684 deletions(-)
 delete mode 100644 arch/x86/events/intel/cqm.c
 delete mode 100644 arch/x86/include/asm/intel_rdt.h
 delete mode 100644 arch/x86/include/asm/intel_rdt_common.h
 create mode 100644 arch/x86/include/asm/intel_rdt_sched.h
 create mode 100644 arch/x86/kernel/cpu/intel_rdt.h
 create mode 100644 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c
 create mode 100644 arch/x86/kernel/cpu/intel_rdt_monitor.c
 delete mode 100644 arch/x86/kernel/cpu/intel_rdt_schemata.c
Signature · 1 line
1.9.1
#1 lore raw

PATCH v2 1/28 x86/perf/cqm: Wipe out perf based cqm

'perf cqm' never worked due to the incompatibility between perf infrastructure and cqm hardware support. The hardware uses RMIDs to track the llc occupancy of tasks and these RMIDs are per package. This makes monitoring a hierarchy like cgroup along with monitoring of tasks separately difficult and several patches sent to lkml to fix them were NACKed. Further more, the following issues in the current perf cqm make it almost unusable:

1. No support to monitor the same group of tasks for which we do allocation using resctrl.

2. It gives random and inaccurate data (mostly 0s) once we run out of RMIDs due to issues in Recycling.

3. Recycling results in inaccuracy of data because we cannot guarantee that the RMID was stolen from a task when it was not pulling data into cache or even when it pulled the least data. Also for monitoring llc_occupancy, if we stop using an RMID_x and then start using an RMID_y after we reclaim an RMID from an other event, we miss accounting all the occupancy that was tagged to RMID_x at a later perf_count.

2. Recycling code makes the monitoring code complex including scheduling because the event can lose RMID any time. Since MBM counters count bandwidth for a period of time by taking snap shot of total bytes at two different times, recycling complicates the way we count MBM in a hierarchy. Also we need a spin lock while we do the processing to account for MBM counter overflow. We also currently use a spin lock in scheduling to prevent the RMID from being taken away.

4. Lack of support when we run different kind of event like task, system-wide and cgroup events together. Data mostly prints 0s. This is also because we can have only one RMID tied to a cpu as defined by the cqm hardware but a perf can at the same time tie multiple events during one sched_in.

5. No support of monitoring a group of tasks. There is partial support for cgroup but it does not work once there is a hierarchy of cgroups or if we want to monitor a task in a cgroup and the cgroup itself.

6. No support for monitoring tasks for the lifetime without perf overhead.

7. It reported the aggregate cache occupancy or memory bandwidth over all sockets. But most cloud and VMM based use cases want to know the individual per-socket usage.

---
 arch/x86/events/intel/Makefile          |    2 +-
 arch/x86/events/intel/cqm.c             | 1766 -------------------------------
 arch/x86/include/asm/intel_rdt_common.h |    2 -
 arch/x86/kernel/cpu/intel_rdt.c         |    8 +
 include/linux/perf_event.h              |   18 -
 kernel/events/core.c                    |   11 +-
 kernel/trace/bpf_trace.c                |    2 +-
 7 files changed, 11 insertions(+), 1798 deletions(-)
 delete mode 100644 arch/x86/events/intel/cqm.c
arch/x86/events/intel/Makefile +1 -1
index 06c2baa..e9d8520 100644
@@ -1,4 +1,4 @@
-obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o cqm.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= ds.o knc.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= lbr.o p4.o p6.o pt.o
 obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)	+= intel-rapl-perf.o
arch/x86/events/intel/cqm.c deleted +0 -1766

1,766 lines not on this page · raw message

arch/x86/include/asm/intel_rdt_common.h +0 -2
index b31081b..c953218 100644
@@ -7,7 +7,6 @@
  * struct intel_pqr_state - State cache for the PQR MSR
  * @rmid:		The cached Resource Monitoring ID
  * @closid:		The cached Class Of Service ID
- * @rmid_usecnt:	The usage counter for rmid
  *
  * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
  * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
@@ -19,7 +18,6 @@
 struct intel_pqr_state {
 	u32			rmid;
 	u32			closid;
-	int			rmid_usecnt;
 };
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
arch/x86/kernel/cpu/intel_rdt.c +8 -0
index 5b36646..989a997 100644
@@ -41,6 +41,14 @@
 DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
 
 /*
+ * The cached intel_pqr_state is strictly per CPU and can never be
+ * updated from a remote CPU. Functions which modify the state
+ * are called with interrupts disabled and no preemption, which
+ * is sufficient for the protection.
+ */
+DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
+
+/*
  * Used to store the max resource name width and max resource data width
  * to display the schemata in a tabular format
  */
include/linux/perf_event.h +0 -18
index 24a6358..7043d65 100644
@@ -139,14 +139,6 @@ struct hw_perf_event {
 			/* for tp_event->class */
 			struct list_head	tp_list;
 		};
-		struct { /* intel_cqm */
-			int			cqm_state;
-			u32			cqm_rmid;
-			int			is_group_event;
-			struct list_head	cqm_events_entry;
-			struct list_head	cqm_groups_entry;
-			struct list_head	cqm_group_entry;
-		};
 		struct { /* itrace */
 			int			itrace_started;
 		};
@@ -417,11 +409,6 @@ struct pmu {
 
 
 	/*
-	 * Return the count value for a counter.
-	 */
-	u64 (*count)			(struct perf_event *event); /*optional*/
-
-	/*
 	 * Set up pmu-private data structures for an AUX area
 	 */
 	void *(*setup_aux)		(int cpu, void **pages,
@@ -1109,11 +1096,6 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
 		__perf_event_task_sched_out(prev, next);
 }
 
-static inline u64 __perf_event_count(struct perf_event *event)
-{
-	return local64_read(&event->count) + atomic64_read(&event->child_count);
-}
-
 extern void perf_event_mmap(struct vm_area_struct *vma);
 extern struct perf_guest_info_callbacks *perf_guest_cbs;
 extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
kernel/events/core.c +1 -10
index 6c4e523..9d47b49 100644
@@ -3622,10 +3622,7 @@ static void __perf_event_read(void *info)
 
 static inline u64 perf_event_count(struct perf_event *event)
 {
-	if (event->pmu->count)
-		return event->pmu->count(event);
-
-	return __perf_event_count(event);
+	return local64_read(&event->count) + atomic64_read(&event->child_count);
 }
 
 /*
@@ -3662,12 +3659,6 @@ u64 perf_event_read_local(struct perf_event *event)
 	WARN_ON_ONCE(event->attr.inherit);
 
 	/*
-	 * It must not have a pmu::count method, those are not
-	 * NMI safe.
-	 */
-	WARN_ON_ONCE(event->pmu->count);
-
-	/*
 	 * If the event is currently on this CPU, its either a per-task event,
 	 * or local to this CPU. Furthermore it means its ACTIVE (otherwise
 	 * oncpu == -1).
kernel/trace/bpf_trace.c +1 -1
index 460a031..662ebcd 100644
@@ -253,7 +253,7 @@ const struct bpf_func_proto *bpf_get_trace_printk_proto(void)
 		return -EINVAL;
 
 	/* make sure event is local and doesn't have pmu::count */
-	if (unlikely(event->oncpu != cpu || event->pmu->count))
+	if (unlikely(event->oncpu != cpu))
 		return -EINVAL;
 
 	/*
Signature · 1 line
1.9.1
#2 lore raw

[tip:x86/cache] x86/perf/cqm: Wipe out perf based cqm

x86/perf/cqm: Wipe out perf based cqm
Commit-ID:  c39a0e2c8850f08249383f2425dbd8dbe4baad69
Gitweb:     http://git.kernel.org/tip/c39a0e2c8850f08249383f2425dbd8dbe4baad69
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:20 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:18 +0200

x86/perf/cqm: Wipe out perf based cqm

'perf cqm' never worked due to the incompatibility between perf infrastructure and cqm hardware support. The hardware uses RMIDs to track the llc occupancy of tasks and these RMIDs are per package. This makes monitoring a hierarchy like cgroup along with monitoring of tasks separately difficult and several patches sent to lkml to fix them were NACKed. Further more, the following issues in the current perf cqm make it almost unusable:

1. No support to monitor the same group of tasks for which we do allocation using resctrl.

2. It gives random and inaccurate data (mostly 0s) once we run out of RMIDs due to issues in Recycling.

3. Recycling results in inaccuracy of data because we cannot guarantee that the RMID was stolen from a task when it was not pulling data into cache or even when it pulled the least data. Also for monitoring llc_occupancy, if we stop using an RMID_x and then start using an RMID_y after we reclaim an RMID from an other event, we miss accounting all the occupancy that was tagged to RMID_x at a later perf_count.

2. Recycling code makes the monitoring code complex including scheduling because the event can lose RMID any time. Since MBM counters count bandwidth for a period of time by taking snap shot of total bytes at two different times, recycling complicates the way we count MBM in a hierarchy. Also we need a spin lock while we do the processing to account for MBM counter overflow. We also currently use a spin lock in scheduling to prevent the RMID from being taken away.

4. Lack of support when we run different kind of event like task, system-wide and cgroup events together. Data mostly prints 0s. This is also because we can have only one RMID tied to a cpu as defined by the cqm hardware but a perf can at the same time tie multiple events during one sched_in.

5. No support of monitoring a group of tasks. There is partial support for cgroup but it does not work once there is a hierarchy of cgroups or if we want to monitor a task in a cgroup and the cgroup itself.

6. No support for monitoring tasks for the lifetime without perf overhead.

7. It reported the aggregate cache occupancy or memory bandwidth over all sockets. But most cloud and VMM based use cases want to know the individual per-socket usage.

---
 arch/x86/events/intel/Makefile          |    2 +-
 arch/x86/events/intel/cqm.c             | 1766 -------------------------------
 arch/x86/include/asm/intel_rdt_common.h |    2 -
 arch/x86/kernel/cpu/intel_rdt.c         |    8 +
 include/linux/perf_event.h              |   18 -
 kernel/events/core.c                    |   14 +-
 6 files changed, 10 insertions(+), 1800 deletions(-)
arch/x86/events/intel/Makefile +1 -1
index 06c2baa..e9d8520 100644
@@ -1,4 +1,4 @@
-obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o cqm.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= ds.o knc.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= lbr.o p4.o p6.o pt.o
 obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)	+= intel-rapl-perf.o
arch/x86/events/intel/cqm.c deleted +0 -1766

1,766 lines not on this page · raw message

arch/x86/include/asm/intel_rdt_common.h +0 -2
index b31081b..c953218 100644
@@ -7,7 +7,6 @@
  * struct intel_pqr_state - State cache for the PQR MSR
  * @rmid:		The cached Resource Monitoring ID
  * @closid:		The cached Class Of Service ID
- * @rmid_usecnt:	The usage counter for rmid
  *
  * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
  * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
@@ -19,7 +18,6 @@
 struct intel_pqr_state {
 	u32			rmid;
 	u32			closid;
-	int			rmid_usecnt;
 };
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
arch/x86/kernel/cpu/intel_rdt.c +8 -0
index 5b36646..989a997 100644
@@ -41,6 +41,14 @@ DEFINE_MUTEX(rdtgroup_mutex);
 DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
 
 /*
+ * The cached intel_pqr_state is strictly per CPU and can never be
+ * updated from a remote CPU. Functions which modify the state
+ * are called with interrupts disabled and no preemption, which
+ * is sufficient for the protection.
+ */
+DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
+
+/*
  * Used to store the max resource name width and max resource data width
  * to display the schemata in a tabular format
  */
include/linux/perf_event.h +0 -18
index a3b873f..4572dba 100644
@@ -139,14 +139,6 @@ struct hw_perf_event {
 			/* for tp_event->class */
 			struct list_head	tp_list;
 		};
-		struct { /* intel_cqm */
-			int			cqm_state;
-			u32			cqm_rmid;
-			int			is_group_event;
-			struct list_head	cqm_events_entry;
-			struct list_head	cqm_groups_entry;
-			struct list_head	cqm_group_entry;
-		};
 		struct { /* itrace */
 			int			itrace_started;
 		};
@@ -417,11 +409,6 @@ struct pmu {
 
 
 	/*
-	 * Return the count value for a counter.
-	 */
-	u64 (*count)			(struct perf_event *event); /*optional*/
-
-	/*
 	 * Set up pmu-private data structures for an AUX area
 	 */
 	void *(*setup_aux)		(int cpu, void **pages,
@@ -1111,11 +1098,6 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
 		__perf_event_task_sched_out(prev, next);
 }
 
-static inline u64 __perf_event_count(struct perf_event *event)
-{
-	return local64_read(&event->count) + atomic64_read(&event->child_count);
-}
-
 extern void perf_event_mmap(struct vm_area_struct *vma);
 extern struct perf_guest_info_callbacks *perf_guest_cbs;
 extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
kernel/events/core.c +1 -13
index 426c2ff..6e17154 100644
@@ -3625,10 +3625,7 @@ unlock:
 
 static inline u64 perf_event_count(struct perf_event *event)
 {
-	if (event->pmu->count)
-		return event->pmu->count(event);
-
-	return __perf_event_count(event);
+	return local64_read(&event->count) + atomic64_read(&event->child_count);
 }
 
 /*
@@ -3659,15 +3656,6 @@ int perf_event_read_local(struct perf_event *event, u64 *value)
 		goto out;
 	}
 
-	/*
-	 * It must not have a pmu::count method, those are not
-	 * NMI safe.
-	 */
-	if (event->pmu->count) {
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
 	/* If this is a per-task event, it must be for current */
 	if ((event->attach_state & PERF_ATTACH_TASK) &&
 	    event->hw.target != current) {
#3 lore raw

PATCH v2 2/28 x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring

In reply to Vikas Shivappa

Add a description of resctrl based RDT(resource director technology) monitoring extension and its usage.

[Tony: Added descriptions for how monitoring and allocation are measured and some cleanups]

---
 Documentation/x86/intel_rdt_ui.txt | 316 ++++++++++++++++++++++++++++++++-----
 1 file changed, 278 insertions(+), 38 deletions(-)
Documentation/x86/intel_rdt_ui.txt +278 -38
index c491a1b..76f21e2 100644
@@ -6,8 +6,8 @@ Fenghua Yu <[email protected]>
 Tony Luck <[email protected]>
 Vikas Shivappa <[email protected]>
 
-This feature is enabled by the CONFIG_INTEL_RDT_A Kconfig and the
-X86 /proc/cpuinfo flag bits "rdt", "cat_l3" and "cdp_l3".
+This feature is enabled by the CONFIG_INTEL_RDT Kconfig and the
+X86 /proc/cpuinfo flag bits "rdt", "cqm", "cat_l3" and "cdp_l3".
 
 To use the feature mount the file system:
 
@@ -17,6 +17,13 @@ mount options are:
 
 "cdp": Enable code/data prioritization in L3 cache allocations.
 
+RDT features are orthogonal. A particular system may support only
+monitoring, only control, or both monitoring and control.
+
+The mount succeeds if either of allocation or monitoring is present, but
+only those files and directories supported by the system will be created.
+For more details on the behavior of the interface during monitoring
+and allocation, see the "Resource alloc and monitor groups" section.
 
 Info directory
 --------------
@@ -24,7 +31,12 @@ Info directory
 The 'info' directory contains information about the enabled
 resources. Each resource has its own subdirectory. The subdirectory
 names reflect the resource names.
-Cache resource(L3/L2)  subdirectory contains the following files:
+
+Each subdirectory contains the following files with respect to
+allocation:
+
+Cache resource(L3/L2)  subdirectory contains the following files
+related to allocation:
 
 "num_closids":  	The number of CLOSIDs which are valid for this
 			resource. The kernel uses the smallest number of
@@ -36,7 +48,8 @@ Cache resource(L3/L2)  subdirectory contains the following files:
 "min_cbm_bits": 	The minimum number of consecutive bits which
 			must be set when writing a mask.
 
-Memory bandwitdh(MB) subdirectory contains the following files:
+Memory bandwitdh(MB) subdirectory contains the following files
+with respect to allocation:
 
 "min_bandwidth":	The minimum memory bandwidth percentage which
 			user can request.
@@ -52,48 +65,152 @@ Memory bandwitdh(MB) subdirectory contains the following files:
 			non-linear. This field is purely informational
 			only.
 
-Resource groups
----------------
+If RDT monitoring is available there will be an "L3_MON" directory
+with the following files:
+
+"num_rmids":		The number of RMIDs available. This is the
+			upper bound for how many "CTRL_MON" + "MON"
+			groups can be created.
+
+"mon_features":	Lists the monitoring events if
+			monitoring is enabled for the resource.
+
+"max_threshold_occupancy":
+			Read/write file provides the largest value (in
+			bytes) at which a previously used LLC_occupancy
+			counter can be considered for re-use.
+
+
+Resource alloc and monitor groups
+---------------------------------
+
 Resource groups are represented as directories in the resctrl file
-system. The default group is the root directory. Other groups may be
-created as desired by the system administrator using the "mkdir(1)"
-command, and removed using "rmdir(1)".
+system.  The default group is the root directory which, immediately
+after mounting, owns all the tasks and cpus in the system and can make
+full use of all resources.
+
+On a system with RDT control features additional directories can be
+created in the root directory that specify different amounts of each
+resource (see "schemata" below). The root and these additional top level
+directories are referred to as "CTRL_MON" groups below.
+
+On a system with RDT monitoring the root directory and other top level
+directories contain a directory named "mon_groups" in which additional
+directories can be created to monitor subsets of tasks in the CTRL_MON
+group that is their ancestor. These are called "MON" groups in the rest
+of this document.
+
+Removing a directory will move all tasks and cpus owned by the group it
+represents to the parent. Removing one of the created CTRL_MON groups
+will automatically remove all MON groups below it.
+
+All groups contain the following files:
+
+"tasks":
+	Reading this file shows the list of all tasks that belong to
+	this group. Writing a task id to the file will add a task to the
+	group. If the group is a CTRL_MON group the task is removed from
+	whichever previous CTRL_MON group owned the task and also from
+	any MON group that owned the task. If the group is a MON group,
+	then the task must already belong to the CTRL_MON parent of this
+	group. The task is removed from any previous MON group.
+
+
+"cpus":
+	Reading this file shows a bitmask of the logical CPUs owned by
+	this group. Writing a mask to this file will add and remove
+	CPUs to/from this group. As with the tasks file a hierarchy is
+	maintained where MON groups may only include CPUs owned by the
+	parent CTRL_MON group.
+
+
+"cpus_list":
+	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
-There are three files associated with each group:
 
-"tasks": A list of tasks that belongs to this group. Tasks can be
-	added to a group by writing the task ID to the "tasks" file
-	(which will automatically remove them from the previous
-	group to which they belonged). New tasks created by fork(2)
-	and clone(2) are added to the same group as their parent.
-	If a pid is not in any sub partition, it is in root partition
-	(i.e. default partition).
+When control is enabled all CTRL_MON groups will also contain:
 
-"cpus": A bitmask of logical CPUs assigned to this group. Writing
-	a new mask can add/remove CPUs from this group. Added CPUs
-	are removed from their previous group. Removed ones are
-	given to the default (root) group. You cannot remove CPUs
-	from the default group.
+"schemata":
+	A list of all the resources available to this group.
+	Each resource has its own line and format - see below for details.
 
-"cpus_list": One or more CPU ranges of logical CPUs assigned to this
-	     group. Same rules apply like for the "cpus" file.
+When monitoring is enabled all MON groups will also contain:
 
-"schemata": A list of all the resources available to this group.
-	Each resource has its own line and format - see below for
-	details.
+"mon_data":
+	This contains a set of files organized by L3 domain and by
+	RDT event. E.g. on a system with two L3 domains there will
+	be subdirectories "mon_L3_00" and "mon_L3_01".	Each of these
+	directories have one file per event (e.g. "llc_occupancy",
+	"mbm_total_bytes", and "mbm_local_bytes"). In a MON group these
+	files provide a read out of the current value of the event for
+	all tasks in the group. In CTRL_MON groups these files provide
+	the sum for all tasks in the CTRL_MON group and all tasks in
+	MON groups. Please see example section for more details on usage.
 
-When a task is running the following rules define which resources
-are available to it:
+Resource allocation rules
+-------------------------
+When a task is running the following rules define which resources are
+available to it:
 
 1) If the task is a member of a non-default group, then the schemata
-for that group is used.
+   for that group is used.
 
 2) Else if the task belongs to the default group, but is running on a
-CPU that is assigned to some specific group, then the schemata for
-the CPU's group is used.
+   CPU that is assigned to some specific group, then the schemata for the
+   CPU's group is used.
 
 3) Otherwise the schemata for the default group is used.
 
+Resource monitoring rules
+-------------------------
+1) If a task is a member of a MON group, or non-default CTRL_MON group
+   then RDT events for the task will be reported in that group.
+
+2) If a task is a member of the default CTRL_MON group, but is running
+   on a CPU that is assigned to some specific group, then the RDT events
+   for the task will be reported in that group.
+
+3) Otherwise RDT events for the task will be reported in the root level
+   "mon_data" group.
+
+
+Notes on cache occupancy monitoring and control
+-----------------------------------------------
+When moving a task from one group to another you should remember that
+this only affects *new* cache allocations by the task. E.g. you may have
+a task in a monitor group showing 3 MB of cache occupancy. If you move
+to a new group and immediately check the occupancy of the old and new
+groups you will likely see that the old group is still showing 3 MB and
+the new group zero. When the task accesses locations still in cache from
+before the move, the h/w does not update any counters. On a busy system
+you will likely see the occupancy in the old group go down as cache lines
+are evicted and re-used while the occupancy in the new group rises as
+the task accesses memory and loads into the cache are counted based on
+membership in the new group.
+
+The same applies to cache allocation control. Moving a task to a group
+with a smaller cache partition will not evict any cache lines. The
+process may continue to use them from the old partition.
+
+Hardware uses CLOSid(Class of service ID) and an RMID(Resource monitoring ID)
+to identify a control group and a monitoring group respectively. Each of
+the resource groups are mapped to these IDs based on the kind of group. The
+number of CLOSid and RMID are limited by the hardware and hence the creation of
+a "CTRL_MON" directory may fail if we run out of either CLOSID or RMID
+and creation of "MON" group may fail if we run out of RMIDs.
+
+max_threshold_occupancy - generic concepts
+------------------------------------------
+
+Note that an RMID once freed may not be immediately available for use as
+the RMID is still tagged the cache lines of the previous user of RMID.
+Hence such RMIDs are placed on limbo list and checked back if the cache
+occupancy has gone down. If there is a time when system has a lot of
+limbo RMIDs but which are not ready to be used, user may see an -EBUSY
+during mkdir.
+
+max_threshold_occupancy is a user configurable value to determine the
+occupancy at which an RMID can be freed.
 
 Schemata files - general concepts
 ---------------------------------
@@ -143,22 +260,22 @@ SKUs. Using a high bandwidth and a low bandwidth setting on two threads
 sharing a core will result in both threads being throttled to use the
 low bandwidth.
 
-L3 details (code and data prioritization disabled)
---------------------------------------------------
+L3 schemata file details (code and data prioritization disabled)
+----------------------------------------------------------------
 With CDP disabled the L3 schemata format is:
 
 	L3:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 
-L3 details (CDP enabled via mount option to resctrl)
-----------------------------------------------------
+L3 schemata file details (CDP enabled via mount option to resctrl)
+------------------------------------------------------------------
 When CDP is enabled L3 control is split into two separate resources
 so you can specify independent masks for code and data like this:
 
 	L3data:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 	L3code:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 
-L2 details
-----------
+L2 schemata file details
+------------------------
 L2 cache does not support code and data prioritization, so the
 schemata format is always:
 
@@ -185,6 +302,8 @@ L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
 L3DATA:0=fffff;1=fffff;2=3c0;3=fffff
 L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
 
+Examples for RDT allocation usage:
+
 Example 1
 ---------
 On a two socket machine (one L3 cache per socket) with just four bits
@@ -410,3 +529,124 @@ void main(void)
 	/* code to read and write directory contents */
 	resctrl_release_lock(fd);
 }
+
+Examples for RDT Monitoring along with allocation usage:
+
+Reading monitored data
+----------------------
+Reading an event file (for ex: mon_data/mon_L3_00/llc_occupancy) would
+show the current snapshot of LLC occupancy of the corresponding MON
+group or CTRL_MON group.
+
+
+Example 1 (Monitor CTRL_MON group and subset of tasks in CTRL_MON group)
+---------
+On a two socket machine (one L3 cache per socket) with just four bits
+for cache bit masks
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p0 p1
+# echo "L3:0=3;1=c" > /sys/fs/resctrl/p0/schemata
+# echo "L3:0=3;1=3" > /sys/fs/resctrl/p1/schemata
+# echo 5678 > p1/tasks
+# echo 5679 > p1/tasks
+
+The default resource group is unmodified, so we have access to all parts
+of all caches (its schemata file reads "L3:0=f;1=f").
+
+Tasks that are under the control of group "p0" may only allocate from the
+"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
+Tasks in group "p1" use the "lower" 50% of cache on both sockets.
+
+Create monitor groups and assign a subset of tasks to each monitor group.
+
+# cd /sys/fs/resctrl/p1/mon_groups
+# mkdir m11 m12
+# echo 5678 > m11/tasks
+# echo 5679 > m12/tasks
+
+fetch data (data shown in bytes)
+
+# cat m11/mon_data/mon_L3_00/llc_occupancy
+16234000
+# cat m11/mon_data/mon_L3_01/llc_occupancy
+14789000
+# cat m12/mon_data/mon_L3_00/llc_occupancy
+16789000
+
+The parent ctrl_mon group shows the aggregated data.
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+31234000
+
+Example 2 (Monitor a task from its creation)
+---------
+On a two socket machine (one L3 cache per socket)
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p0 p1
+
+An RMID is allocated to the group once its created and hence the <cmd>
+below is monitored from its creation.
+
+# echo $$ > /sys/fs/resctrl/p1/tasks
+# <cmd>
+
+Fetch the data
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+31789000
+
+Example 3 (Monitor without CAT support or before creating CAT groups)
+---------
+
+Assume a system like HSW has only CQM and no CAT support. In this case
+the resctrl will still mount but cannot create CTRL_MON directories.
+But user can create different MON groups within the root group thereby
+able to monitor all tasks including kernel threads.
+
+This can also be used to profile jobs cache size footprint before being
+able to allocate them to different allocation groups.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir mon_groups/m01
+# mkdir mon_groups/m02
+
+# echo 3478 > /sys/fs/resctrl/mon_groups/m01/tasks
+# echo 2467 > /sys/fs/resctrl/mon_groups/m02/tasks
+
+Monitor the groups separately and also get per domain data. From the
+below its apparent that the tasks are mostly doing work on
+domain(socket) 0.
+
+# cat /sys/fs/resctrl/mon_groups/m01/mon_L3_00/llc_occupancy
+31234000
+# cat /sys/fs/resctrl/mon_groups/m01/mon_L3_01/llc_occupancy
+34555
+# cat /sys/fs/resctrl/mon_groups/m02/mon_L3_00/llc_occupancy
+31234000
+# cat /sys/fs/resctrl/mon_groups/m02/mon_L3_01/llc_occupancy
+32789
+
+
+Example 4 (Monitor real time tasks)
+-----------------------------------
+
+A single socket system which has real time tasks running on cores 4-7
+and non real time tasks on other cpus. We want to monitor the cache
+occupancy of the real time threads on these cores.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p1
+
+Move the cpus 4-7 over to p1
+# echo f0 > p0/cpus
+
+View the llc occupancy snapshot
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
+11234000
Signature · 1 line
1.9.1
#4 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring

x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring
Commit-ID:  1640ae9471ae41eb18d2b214f1f40af3c4ed3828
Gitweb:     http://git.kernel.org/tip/1640ae9471ae41eb18d2b214f1f40af3c4ed3828
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:21 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:19 +0200

x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring

Add a description of resctrl based RDT(resource director technology) monitoring extension and its usage.

[Tony: Added descriptions for how monitoring and allocation are measured and some cleanups]

---
 Documentation/x86/intel_rdt_ui.txt | 316 ++++++++++++++++++++++++++++++++-----
 1 file changed, 278 insertions(+), 38 deletions(-)
Documentation/x86/intel_rdt_ui.txt +278 -38
index c491a1b..76f21e2 100644
@@ -6,8 +6,8 @@ Fenghua Yu <[email protected]>
 Tony Luck <[email protected]>
 Vikas Shivappa <[email protected]>
 
-This feature is enabled by the CONFIG_INTEL_RDT_A Kconfig and the
-X86 /proc/cpuinfo flag bits "rdt", "cat_l3" and "cdp_l3".
+This feature is enabled by the CONFIG_INTEL_RDT Kconfig and the
+X86 /proc/cpuinfo flag bits "rdt", "cqm", "cat_l3" and "cdp_l3".
 
 To use the feature mount the file system:
 
@@ -17,6 +17,13 @@ mount options are:
 
 "cdp": Enable code/data prioritization in L3 cache allocations.
 
+RDT features are orthogonal. A particular system may support only
+monitoring, only control, or both monitoring and control.
+
+The mount succeeds if either of allocation or monitoring is present, but
+only those files and directories supported by the system will be created.
+For more details on the behavior of the interface during monitoring
+and allocation, see the "Resource alloc and monitor groups" section.
 
 Info directory
 --------------
@@ -24,7 +31,12 @@ Info directory
 The 'info' directory contains information about the enabled
 resources. Each resource has its own subdirectory. The subdirectory
 names reflect the resource names.
-Cache resource(L3/L2)  subdirectory contains the following files:
+
+Each subdirectory contains the following files with respect to
+allocation:
+
+Cache resource(L3/L2)  subdirectory contains the following files
+related to allocation:
 
 "num_closids":  	The number of CLOSIDs which are valid for this
 			resource. The kernel uses the smallest number of
@@ -36,7 +48,8 @@ Cache resource(L3/L2)  subdirectory contains the following files:
 "min_cbm_bits": 	The minimum number of consecutive bits which
 			must be set when writing a mask.
 
-Memory bandwitdh(MB) subdirectory contains the following files:
+Memory bandwitdh(MB) subdirectory contains the following files
+with respect to allocation:
 
 "min_bandwidth":	The minimum memory bandwidth percentage which
 			user can request.
@@ -52,48 +65,152 @@ Memory bandwitdh(MB) subdirectory contains the following files:
 			non-linear. This field is purely informational
 			only.
 
-Resource groups
----------------
+If RDT monitoring is available there will be an "L3_MON" directory
+with the following files:
+
+"num_rmids":		The number of RMIDs available. This is the
+			upper bound for how many "CTRL_MON" + "MON"
+			groups can be created.
+
+"mon_features":	Lists the monitoring events if
+			monitoring is enabled for the resource.
+
+"max_threshold_occupancy":
+			Read/write file provides the largest value (in
+			bytes) at which a previously used LLC_occupancy
+			counter can be considered for re-use.
+
+
+Resource alloc and monitor groups
+---------------------------------
+
 Resource groups are represented as directories in the resctrl file
-system. The default group is the root directory. Other groups may be
-created as desired by the system administrator using the "mkdir(1)"
-command, and removed using "rmdir(1)".
+system.  The default group is the root directory which, immediately
+after mounting, owns all the tasks and cpus in the system and can make
+full use of all resources.
+
+On a system with RDT control features additional directories can be
+created in the root directory that specify different amounts of each
+resource (see "schemata" below). The root and these additional top level
+directories are referred to as "CTRL_MON" groups below.
+
+On a system with RDT monitoring the root directory and other top level
+directories contain a directory named "mon_groups" in which additional
+directories can be created to monitor subsets of tasks in the CTRL_MON
+group that is their ancestor. These are called "MON" groups in the rest
+of this document.
+
+Removing a directory will move all tasks and cpus owned by the group it
+represents to the parent. Removing one of the created CTRL_MON groups
+will automatically remove all MON groups below it.
+
+All groups contain the following files:
+
+"tasks":
+	Reading this file shows the list of all tasks that belong to
+	this group. Writing a task id to the file will add a task to the
+	group. If the group is a CTRL_MON group the task is removed from
+	whichever previous CTRL_MON group owned the task and also from
+	any MON group that owned the task. If the group is a MON group,
+	then the task must already belong to the CTRL_MON parent of this
+	group. The task is removed from any previous MON group.
+
+
+"cpus":
+	Reading this file shows a bitmask of the logical CPUs owned by
+	this group. Writing a mask to this file will add and remove
+	CPUs to/from this group. As with the tasks file a hierarchy is
+	maintained where MON groups may only include CPUs owned by the
+	parent CTRL_MON group.
+
+
+"cpus_list":
+	Just like "cpus", only using ranges of CPUs instead of bitmasks.
 
-There are three files associated with each group:
 
-"tasks": A list of tasks that belongs to this group. Tasks can be
-	added to a group by writing the task ID to the "tasks" file
-	(which will automatically remove them from the previous
-	group to which they belonged). New tasks created by fork(2)
-	and clone(2) are added to the same group as their parent.
-	If a pid is not in any sub partition, it is in root partition
-	(i.e. default partition).
+When control is enabled all CTRL_MON groups will also contain:
 
-"cpus": A bitmask of logical CPUs assigned to this group. Writing
-	a new mask can add/remove CPUs from this group. Added CPUs
-	are removed from their previous group. Removed ones are
-	given to the default (root) group. You cannot remove CPUs
-	from the default group.
+"schemata":
+	A list of all the resources available to this group.
+	Each resource has its own line and format - see below for details.
 
-"cpus_list": One or more CPU ranges of logical CPUs assigned to this
-	     group. Same rules apply like for the "cpus" file.
+When monitoring is enabled all MON groups will also contain:
 
-"schemata": A list of all the resources available to this group.
-	Each resource has its own line and format - see below for
-	details.
+"mon_data":
+	This contains a set of files organized by L3 domain and by
+	RDT event. E.g. on a system with two L3 domains there will
+	be subdirectories "mon_L3_00" and "mon_L3_01".	Each of these
+	directories have one file per event (e.g. "llc_occupancy",
+	"mbm_total_bytes", and "mbm_local_bytes"). In a MON group these
+	files provide a read out of the current value of the event for
+	all tasks in the group. In CTRL_MON groups these files provide
+	the sum for all tasks in the CTRL_MON group and all tasks in
+	MON groups. Please see example section for more details on usage.
 
-When a task is running the following rules define which resources
-are available to it:
+Resource allocation rules
+-------------------------
+When a task is running the following rules define which resources are
+available to it:
 
 1) If the task is a member of a non-default group, then the schemata
-for that group is used.
+   for that group is used.
 
 2) Else if the task belongs to the default group, but is running on a
-CPU that is assigned to some specific group, then the schemata for
-the CPU's group is used.
+   CPU that is assigned to some specific group, then the schemata for the
+   CPU's group is used.
 
 3) Otherwise the schemata for the default group is used.
 
+Resource monitoring rules
+-------------------------
+1) If a task is a member of a MON group, or non-default CTRL_MON group
+   then RDT events for the task will be reported in that group.
+
+2) If a task is a member of the default CTRL_MON group, but is running
+   on a CPU that is assigned to some specific group, then the RDT events
+   for the task will be reported in that group.
+
+3) Otherwise RDT events for the task will be reported in the root level
+   "mon_data" group.
+
+
+Notes on cache occupancy monitoring and control
+-----------------------------------------------
+When moving a task from one group to another you should remember that
+this only affects *new* cache allocations by the task. E.g. you may have
+a task in a monitor group showing 3 MB of cache occupancy. If you move
+to a new group and immediately check the occupancy of the old and new
+groups you will likely see that the old group is still showing 3 MB and
+the new group zero. When the task accesses locations still in cache from
+before the move, the h/w does not update any counters. On a busy system
+you will likely see the occupancy in the old group go down as cache lines
+are evicted and re-used while the occupancy in the new group rises as
+the task accesses memory and loads into the cache are counted based on
+membership in the new group.
+
+The same applies to cache allocation control. Moving a task to a group
+with a smaller cache partition will not evict any cache lines. The
+process may continue to use them from the old partition.
+
+Hardware uses CLOSid(Class of service ID) and an RMID(Resource monitoring ID)
+to identify a control group and a monitoring group respectively. Each of
+the resource groups are mapped to these IDs based on the kind of group. The
+number of CLOSid and RMID are limited by the hardware and hence the creation of
+a "CTRL_MON" directory may fail if we run out of either CLOSID or RMID
+and creation of "MON" group may fail if we run out of RMIDs.
+
+max_threshold_occupancy - generic concepts
+------------------------------------------
+
+Note that an RMID once freed may not be immediately available for use as
+the RMID is still tagged the cache lines of the previous user of RMID.
+Hence such RMIDs are placed on limbo list and checked back if the cache
+occupancy has gone down. If there is a time when system has a lot of
+limbo RMIDs but which are not ready to be used, user may see an -EBUSY
+during mkdir.
+
+max_threshold_occupancy is a user configurable value to determine the
+occupancy at which an RMID can be freed.
 
 Schemata files - general concepts
 ---------------------------------
@@ -143,22 +260,22 @@ SKUs. Using a high bandwidth and a low bandwidth setting on two threads
 sharing a core will result in both threads being throttled to use the
 low bandwidth.
 
-L3 details (code and data prioritization disabled)
---------------------------------------------------
+L3 schemata file details (code and data prioritization disabled)
+----------------------------------------------------------------
 With CDP disabled the L3 schemata format is:
 
 	L3:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 
-L3 details (CDP enabled via mount option to resctrl)
-----------------------------------------------------
+L3 schemata file details (CDP enabled via mount option to resctrl)
+------------------------------------------------------------------
 When CDP is enabled L3 control is split into two separate resources
 so you can specify independent masks for code and data like this:
 
 	L3data:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 	L3code:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
 
-L2 details
-----------
+L2 schemata file details
+------------------------
 L2 cache does not support code and data prioritization, so the
 schemata format is always:
 
@@ -185,6 +302,8 @@ L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
 L3DATA:0=fffff;1=fffff;2=3c0;3=fffff
 L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
 
+Examples for RDT allocation usage:
+
 Example 1
 ---------
 On a two socket machine (one L3 cache per socket) with just four bits
@@ -410,3 +529,124 @@ void main(void)
 	/* code to read and write directory contents */
 	resctrl_release_lock(fd);
 }
+
+Examples for RDT Monitoring along with allocation usage:
+
+Reading monitored data
+----------------------
+Reading an event file (for ex: mon_data/mon_L3_00/llc_occupancy) would
+show the current snapshot of LLC occupancy of the corresponding MON
+group or CTRL_MON group.
+
+
+Example 1 (Monitor CTRL_MON group and subset of tasks in CTRL_MON group)
+---------
+On a two socket machine (one L3 cache per socket) with just four bits
+for cache bit masks
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p0 p1
+# echo "L3:0=3;1=c" > /sys/fs/resctrl/p0/schemata
+# echo "L3:0=3;1=3" > /sys/fs/resctrl/p1/schemata
+# echo 5678 > p1/tasks
+# echo 5679 > p1/tasks
+
+The default resource group is unmodified, so we have access to all parts
+of all caches (its schemata file reads "L3:0=f;1=f").
+
+Tasks that are under the control of group "p0" may only allocate from the
+"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
+Tasks in group "p1" use the "lower" 50% of cache on both sockets.
+
+Create monitor groups and assign a subset of tasks to each monitor group.
+
+# cd /sys/fs/resctrl/p1/mon_groups
+# mkdir m11 m12
+# echo 5678 > m11/tasks
+# echo 5679 > m12/tasks
+
+fetch data (data shown in bytes)
+
+# cat m11/mon_data/mon_L3_00/llc_occupancy
+16234000
+# cat m11/mon_data/mon_L3_01/llc_occupancy
+14789000
+# cat m12/mon_data/mon_L3_00/llc_occupancy
+16789000
+
+The parent ctrl_mon group shows the aggregated data.
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+31234000
+
+Example 2 (Monitor a task from its creation)
+---------
+On a two socket machine (one L3 cache per socket)
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p0 p1
+
+An RMID is allocated to the group once its created and hence the <cmd>
+below is monitored from its creation.
+
+# echo $$ > /sys/fs/resctrl/p1/tasks
+# <cmd>
+
+Fetch the data
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+31789000
+
+Example 3 (Monitor without CAT support or before creating CAT groups)
+---------
+
+Assume a system like HSW has only CQM and no CAT support. In this case
+the resctrl will still mount but cannot create CTRL_MON directories.
+But user can create different MON groups within the root group thereby
+able to monitor all tasks including kernel threads.
+
+This can also be used to profile jobs cache size footprint before being
+able to allocate them to different allocation groups.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir mon_groups/m01
+# mkdir mon_groups/m02
+
+# echo 3478 > /sys/fs/resctrl/mon_groups/m01/tasks
+# echo 2467 > /sys/fs/resctrl/mon_groups/m02/tasks
+
+Monitor the groups separately and also get per domain data. From the
+below its apparent that the tasks are mostly doing work on
+domain(socket) 0.
+
+# cat /sys/fs/resctrl/mon_groups/m01/mon_L3_00/llc_occupancy
+31234000
+# cat /sys/fs/resctrl/mon_groups/m01/mon_L3_01/llc_occupancy
+34555
+# cat /sys/fs/resctrl/mon_groups/m02/mon_L3_00/llc_occupancy
+31234000
+# cat /sys/fs/resctrl/mon_groups/m02/mon_L3_01/llc_occupancy
+32789
+
+
+Example 4 (Monitor real time tasks)
+-----------------------------------
+
+A single socket system which has real time tasks running on cores 4-7
+and non real time tasks on other cpus. We want to monitor the cache
+occupancy of the real time threads on these cores.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p1
+
+Move the cpus 4-7 over to p1
+# echo f0 > p0/cpus
+
+View the llc occupancy snapshot
+
+# cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
+11234000
#5 lore raw

PATCH v2 3/28 x86/intel_rdt: Introduce a common compile option for RDT

In reply to Vikas Shivappa

We currently have a CONFIG_RDT_A which is for RDT(Resource directory technology) allocation based resctrl filesystem interface. As a preparation to add support for RDT monitoring as well into the same resctrl filesystem, change the config option to be CONFIG_RDT which would include both RDT allocation and monitoring code.

No functional change.

---
 arch/x86/Kconfig                 | 12 ++++++------
 arch/x86/include/asm/intel_rdt.h |  4 ++--
 arch/x86/kernel/cpu/Makefile     |  2 +-
 include/linux/sched.h            |  2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)
arch/x86/Kconfig +6 -6
index 0efb4c9..4eac5ef 100644
@@ -416,16 +416,16 @@ config GOLDFISH
        def_bool y
        depends on X86_GOLDFISH
 
-config INTEL_RDT_A
-	bool "Intel Resource Director Technology Allocation support"
+config INTEL_RDT
+	bool "Intel Resource Director Technology support"
 	default n
 	depends on X86 && CPU_SUP_INTEL
 	select KERNFS
 	help
-	  Select to enable resource allocation which is a sub-feature of
-	  Intel Resource Director Technology(RDT). More information about
-	  RDT can be found in the Intel x86 Architecture Software
-	  Developer Manual.
+	  Select to enable resource allocation and monitoring which are
+	  sub-features of Intel Resource Director Technology(RDT). More
+	  information about RDT can be found in the Intel x86
+	  Architecture Software Developer Manual.
 
 	  Say N if unsure.
 
arch/x86/include/asm/intel_rdt.h +2 -2
index 597dc49..ae1efc3 100644
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_INTEL_RDT_H
 #define _ASM_X86_INTEL_RDT_H
 
-#ifdef CONFIG_INTEL_RDT_A
+#ifdef CONFIG_INTEL_RDT
 
 #include <linux/sched.h>
 #include <linux/kernfs.h>
@@ -282,5 +282,5 @@ static inline void intel_rdt_sched_in(void)
 
 static inline void intel_rdt_sched_in(void) {}
 
-#endif /* CONFIG_INTEL_RDT_A */
+#endif /* CONFIG_INTEL_RDT */
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/Makefile +1 -1
index 5200001..a576121 100644
@@ -32,7 +32,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT_A)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
include/linux/sched.h +1 -1
index 2b69fc6..9e31b3d 100644
@@ -864,7 +864,7 @@ struct task_struct {
 	/* cg_list protected by css_set_lock and tsk->alloc_lock: */
 	struct list_head		cg_list;
 #endif
-#ifdef CONFIG_INTEL_RDT_A
+#ifdef CONFIG_INTEL_RDT
 	int				closid;
 #endif
 #ifdef CONFIG_FUTEX
Signature · 1 line
1.9.1
#6 lore raw

[tip:x86/cache] x86/intel_rdt: Introduce a common compile option for RDT

x86/intel_rdt: Introduce a common compile option for RDT
Commit-ID:  f01d7d51f577b5dc0fa5919ab8a9228e2bf49f3e
Gitweb:     http://git.kernel.org/tip/f01d7d51f577b5dc0fa5919ab8a9228e2bf49f3e
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:22 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:19 +0200

x86/intel_rdt: Introduce a common compile option for RDT

We currently have a CONFIG_RDT_A which is for RDT(Resource directory technology) allocation based resctrl filesystem interface. As a preparation to add support for RDT monitoring as well into the same resctrl filesystem, change the config option to be CONFIG_RDT which would include both RDT allocation and monitoring code.

No functional change.

---
 arch/x86/Kconfig                 | 12 ++++++------
 arch/x86/include/asm/intel_rdt.h |  4 ++--
 arch/x86/kernel/cpu/Makefile     |  2 +-
 include/linux/sched.h            |  2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)
arch/x86/Kconfig +6 -6
index 781521b..b1abda7 100644
@@ -424,16 +424,16 @@ config GOLDFISH
        def_bool y
        depends on X86_GOLDFISH
 
-config INTEL_RDT_A
-	bool "Intel Resource Director Technology Allocation support"
+config INTEL_RDT
+	bool "Intel Resource Director Technology support"
 	default n
 	depends on X86 && CPU_SUP_INTEL
 	select KERNFS
 	help
-	  Select to enable resource allocation which is a sub-feature of
-	  Intel Resource Director Technology(RDT). More information about
-	  RDT can be found in the Intel x86 Architecture Software
-	  Developer Manual.
+	  Select to enable resource allocation and monitoring which are
+	  sub-features of Intel Resource Director Technology(RDT). More
+	  information about RDT can be found in the Intel x86
+	  Architecture Software Developer Manual.
 
 	  Say N if unsure.
 
arch/x86/include/asm/intel_rdt.h +2 -2
index 597dc49..ae1efc3 100644
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_INTEL_RDT_H
 #define _ASM_X86_INTEL_RDT_H
 
-#ifdef CONFIG_INTEL_RDT_A
+#ifdef CONFIG_INTEL_RDT
 
 #include <linux/sched.h>
 #include <linux/kernfs.h>
@@ -282,5 +282,5 @@ static inline void intel_rdt_sched_in(void)
 
 static inline void intel_rdt_sched_in(void) {}
 
-#endif /* CONFIG_INTEL_RDT_A */
+#endif /* CONFIG_INTEL_RDT */
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/Makefile +1 -1
index cdf8249..3622ca2 100644
@@ -33,7 +33,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT_A)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
include/linux/sched.h +1 -1
index 8337e2d..20b2ff2 100644
@@ -898,7 +898,7 @@ struct task_struct {
 	/* cg_list protected by css_set_lock and tsk->alloc_lock: */
 	struct list_head		cg_list;
 #endif
-#ifdef CONFIG_INTEL_RDT_A
+#ifdef CONFIG_INTEL_RDT
 	int				closid;
 #endif
 #ifdef CONFIG_FUTEX
#7 lore raw

PATCH v2 4/28 x86/intel_rdt: Change file names to accommodate RDT monitor code

In reply to Vikas Shivappa

Because the "perf cqm" and resctrl code were separately added and indivdually configurable, there seem to be separate context switch code and also things on global .h which are not really needed.

Move only the scheduling specific code and definitions to <asm/intel_rdt_sched.h> and the put all the other declarations to a local intel_rdt.h.

h/t to Reinette Chatre for pointing out that we should separate the public interfaces used by other parts of the kernel from private objects shared between the various files comprising RDT.

No functional change.

---
 MAINTAINERS                              |   2 +-
 arch/x86/include/asm/intel_rdt.h         | 286 -------------------------------
 arch/x86/include/asm/intel_rdt_common.h  |  25 ---
 arch/x86/include/asm/intel_rdt_sched.h   |  72 ++++++++
 arch/x86/kernel/cpu/intel_rdt.c          |   5 +-
 arch/x86/kernel/cpu/intel_rdt.h          | 243 ++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c |   4 +-
 arch/x86/kernel/cpu/intel_rdt_schemata.c |   2 +-
 arch/x86/kernel/process_32.c             |   2 +-
 arch/x86/kernel/process_64.c             |   2 +-
 10 files changed, 324 insertions(+), 319 deletions(-)
 delete mode 100644 arch/x86/include/asm/intel_rdt.h
 delete mode 100644 arch/x86/include/asm/intel_rdt_common.h
 create mode 100644 arch/x86/include/asm/intel_rdt_sched.h
 create mode 100644 arch/x86/kernel/cpu/intel_rdt.h
MAINTAINERS +1 -1
index 767e9d2..8388699 100644
@@ -10733,7 +10733,7 @@ M:	Fenghua Yu <[email protected]>
 L:	[email protected]
 S:	Supported
 F:	arch/x86/kernel/cpu/intel_rdt*
-F:	arch/x86/include/asm/intel_rdt*
+F:	arch/x86/include/asm/intel_rdt_sched.h
 F:	Documentation/x86/intel_rdt*
 
 READ-COPY UPDATE (RCU)
arch/x86/include/asm/intel_rdt.h deleted +0 -286

286 lines not on this page · raw message

arch/x86/include/asm/intel_rdt_common.h deleted +0 -25
deleted file mode 100644
index c953218..0000000
@@ -1,25 +0,0 @@
-#ifndef _ASM_X86_INTEL_RDT_COMMON_H
-#define _ASM_X86_INTEL_RDT_COMMON_H
-
-#define MSR_IA32_PQR_ASSOC	0x0c8f
-
-/**
- * struct intel_pqr_state - State cache for the PQR MSR
- * @rmid:		The cached Resource Monitoring ID
- * @closid:		The cached Class Of Service ID
- *
- * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
- * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
- *
- * The cache also helps to avoid pointless updates if the value does
- * not change.
- */
-struct intel_pqr_state {
-	u32			rmid;
-	u32			closid;
-};
-
-DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
-
-#endif /* _ASM_X86_INTEL_RDT_COMMON_H */
arch/x86/include/asm/intel_rdt_sched.h new file +72 -0

72 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt.c +3 -2
index 989a997..08872e9 100644
@@ -30,7 +30,8 @@
 #include <linux/cpuhotplug.h>
 
 #include <asm/intel-family.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
+#include "intel_rdt.h"
 
 #define MAX_MBA_BW	100u
 #define MBA_IS_LINEAR	0x4
@@ -455,7 +456,7 @@ static void clear_closid(int cpu)
 
 	per_cpu(cpu_closid, cpu) = 0;
 	state->closid = 0;
-	wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
+	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
 }
 
 static int intel_rdt_online_cpu(unsigned int cpu)
arch/x86/kernel/cpu/intel_rdt.h new file +243 -0

243 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +2 -2
index 9257bd9..fab8811 100644
@@ -32,8 +32,8 @@
 
 #include <uapi/linux/magic.h>
 
-#include <asm/intel_rdt.h>
-#include <asm/intel_rdt_common.h>
+#include <asm/intel_rdt_sched.h>
+#include "intel_rdt.h"
 
 DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
 struct kernfs_root *rdt_root;
arch/x86/kernel/cpu/intel_rdt_schemata.c +1 -1
index 406d7a6..8cef1c8 100644
@@ -26,7 +26,7 @@
 #include <linux/kernfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <asm/intel_rdt.h>
+#include "intel_rdt.h"
 
 /*
  * Check whether MBA bandwidth percentage value is correct. The value is
arch/x86/kernel/process_32.c +1 -1
index ffeae81..930aebc 100644
@@ -56,7 +56,7 @@
 #include <asm/debugreg.h>
 #include <asm/switch_to.h>
 #include <asm/vm86.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
 #include <asm/proto.h>
 
 void __show_regs(struct pt_regs *regs, int all)
arch/x86/kernel/process_64.c +1 -1
index b6840bf..063360e 100644
@@ -52,7 +52,7 @@
 #include <asm/switch_to.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/vdso.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
 #include <asm/unistd.h>
 #ifdef CONFIG_IA32_EMULATION
 /* Not included via unistd.h */
Signature · 1 line
1.9.1
#8 lore raw

[tip:x86/cache] x86/intel_rdt: Change file names to accommodate RDT monitor code

x86/intel_rdt: Change file names to accommodate RDT monitor code
Commit-ID:  0583020456cea9fcf43b84bb13a41eab059ae0a8
Gitweb:     http://git.kernel.org/tip/0583020456cea9fcf43b84bb13a41eab059ae0a8
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:23 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:19 +0200

x86/intel_rdt: Change file names to accommodate RDT monitor code

Because the "perf cqm" and resctrl code were separately added and indivdually configurable, there seem to be separate context switch code and also things on global .h which are not really needed.

Move only the scheduling specific code and definitions to <asm/intel_rdt_sched.h> and the put all the other declarations to a local intel_rdt.h.

h/t to Reinette Chatre for pointing out that we should separate the public interfaces used by other parts of the kernel from private objects shared between the various files comprising RDT.

No functional change.

---
 MAINTAINERS                                      |  2 +-
 arch/x86/include/asm/intel_rdt_common.h          | 25 --------
 arch/x86/include/asm/intel_rdt_sched.h           | 72 ++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt.c                  |  5 +-
 arch/x86/{include/asm => kernel/cpu}/intel_rdt.h | 43 --------------
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c         |  4 +-
 arch/x86/kernel/cpu/intel_rdt_schemata.c         |  2 +-
 arch/x86/kernel/process_32.c                     |  2 +-
 arch/x86/kernel/process_64.c                     |  2 +-
 9 files changed, 81 insertions(+), 76 deletions(-)
MAINTAINERS +1 -1
index f66488d..cbbc79a8 100644
@@ -11103,7 +11103,7 @@ M:	Fenghua Yu <[email protected]>
 L:	[email protected]
 S:	Supported
 F:	arch/x86/kernel/cpu/intel_rdt*
-F:	arch/x86/include/asm/intel_rdt*
+F:	arch/x86/include/asm/intel_rdt_sched.h
 F:	Documentation/x86/intel_rdt*
 
 READ-COPY UPDATE (RCU)
arch/x86/include/asm/intel_rdt_common.h deleted +0 -25
deleted file mode 100644
index c953218..0000000
@@ -1,25 +0,0 @@
-#ifndef _ASM_X86_INTEL_RDT_COMMON_H
-#define _ASM_X86_INTEL_RDT_COMMON_H
-
-#define MSR_IA32_PQR_ASSOC	0x0c8f
-
-/**
- * struct intel_pqr_state - State cache for the PQR MSR
- * @rmid:		The cached Resource Monitoring ID
- * @closid:		The cached Class Of Service ID
- *
- * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
- * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
- *
- * The cache also helps to avoid pointless updates if the value does
- * not change.
- */
-struct intel_pqr_state {
-	u32			rmid;
-	u32			closid;
-};
-
-DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
-
-#endif /* _ASM_X86_INTEL_RDT_COMMON_H */
arch/x86/include/asm/intel_rdt_sched.h new file +72 -0

72 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt.c +3 -2
index 989a997..08872e9 100644
@@ -30,7 +30,8 @@
 #include <linux/cpuhotplug.h>
 
 #include <asm/intel-family.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
+#include "intel_rdt.h"
 
 #define MAX_MBA_BW	100u
 #define MBA_IS_LINEAR	0x4
@@ -455,7 +456,7 @@ static void clear_closid(int cpu)
 
 	per_cpu(cpu_closid, cpu) = 0;
 	state->closid = 0;
-	wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
+	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
 }
 
 static int intel_rdt_online_cpu(unsigned int cpu)
arch/x86/kernel/cpu/intel_rdt.h renamed from arch/x86/include/asm/intel_rdt.h +0 -43

57 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +2 -2
index 9257bd9..fab8811 100644
@@ -32,8 +32,8 @@
 
 #include <uapi/linux/magic.h>
 
-#include <asm/intel_rdt.h>
-#include <asm/intel_rdt_common.h>
+#include <asm/intel_rdt_sched.h>
+#include "intel_rdt.h"
 
 DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
 struct kernfs_root *rdt_root;
arch/x86/kernel/cpu/intel_rdt_schemata.c +1 -1
index 406d7a6..8cef1c8 100644
@@ -26,7 +26,7 @@
 #include <linux/kernfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <asm/intel_rdt.h>
+#include "intel_rdt.h"
 
 /*
  * Check whether MBA bandwidth percentage value is correct. The value is
arch/x86/kernel/process_32.c +1 -1
index c6d6dc5..2280216 100644
@@ -56,7 +56,7 @@
 #include <asm/debugreg.h>
 #include <asm/switch_to.h>
 #include <asm/vm86.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
 #include <asm/proto.h>
 
 void __show_regs(struct pt_regs *regs, int all)
arch/x86/kernel/process_64.c +1 -1
index c3169be..77a35c8 100644
@@ -52,7 +52,7 @@
 #include <asm/switch_to.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/vdso.h>
-#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_sched.h>
 #include <asm/unistd.h>
 #ifdef CONFIG_IA32_EMULATION
 /* Not included via unistd.h */
#9 lore raw

PATCH v2 5/28 x86/intel_rdt: Mark rdt_root and closid_alloc as static

In reply to Vikas Shivappa

From: Reinette Chatre <[email protected]>

Sparse reports that both of these can be static.

Make it so.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +2 -2
index fab8811..3273e88 100644
@@ -36,7 +36,7 @@
 #include "intel_rdt.h"
 
 DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
-struct kernfs_root *rdt_root;
+static struct kernfs_root *rdt_root;
 struct rdtgroup rdtgroup_default;
 LIST_HEAD(rdt_all_groups);
 
@@ -75,7 +75,7 @@ static void closid_init(void)
 	closid_free_map &= ~1;
 }
 
-int closid_alloc(void)
+static int closid_alloc(void)
 {
 	int closid = ffs(closid_free_map);
 
Signature · 1 line
1.9.1
#10 lore raw

[tip:x86/cache] x86/intel_rdt: Mark rdt_root and closid_alloc as static

x86/intel_rdt: Mark rdt_root and closid_alloc as static
Commit-ID:  cb2200e967c65519ca6c5426644a49dca65f6294
Gitweb:     http://git.kernel.org/tip/cb2200e967c65519ca6c5426644a49dca65f6294
Author:     Reinette Chatre <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:24 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:20 +0200

x86/intel_rdt: Mark rdt_root and closid_alloc as static

Sparse reports that both of these can be static.

Make it so.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +2 -2
index fab8811..3273e88 100644
@@ -36,7 +36,7 @@
 #include "intel_rdt.h"
 
 DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
-struct kernfs_root *rdt_root;
+static struct kernfs_root *rdt_root;
 struct rdtgroup rdtgroup_default;
 LIST_HEAD(rdt_all_groups);
 
@@ -75,7 +75,7 @@ static void closid_init(void)
 	closid_free_map &= ~1;
 }
 
-int closid_alloc(void)
+static int closid_alloc(void)
 {
 	int closid = ffs(closid_free_map);
 
#11 lore raw

PATCH v2 6/28 x86/intel_rdt: Cleanup namespace to support RDT monitoring

In reply to Vikas Shivappa

Few of the data-structures have generic names although they are RDT allocation specific. Rename them to be allocation specific to accommodate RDT monitoring. E.g. s/enabled/alloc_enabled/

No functional change.

---
 arch/x86/include/asm/intel_rdt_sched.h   |  4 ++--
 arch/x86/kernel/cpu/intel_rdt.c          | 26 ++++++++++++-------------
 arch/x86/kernel/cpu/intel_rdt.h          | 18 ++++++++---------
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 33 ++++++++++++++++----------------
 arch/x86/kernel/cpu/intel_rdt_schemata.c |  8 ++++----
 5 files changed, 45 insertions(+), 44 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +2 -2
index 62a70bc..4dee77b 100644
@@ -27,7 +27,7 @@ struct intel_pqr_state {
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
 DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
  * intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
@@ -44,7 +44,7 @@ struct intel_pqr_state {
  */
 static inline void intel_rdt_sched_in(void)
 {
-	if (static_branch_likely(&rdt_enable_key)) {
+	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 		int closid;
 
arch/x86/kernel/cpu/intel_rdt.c +13 -13
index 08872e9..835e1ff 100644
@@ -173,8 +173,8 @@ static inline bool cache_alloc_hsw_probe(void)
 		r->default_ctrl = max_cbm;
 		r->cache.cbm_len = 20;
 		r->cache.min_cbm_bits = 2;
-		r->capable = true;
-		r->enabled = true;
+		r->alloc_capable = true;
+		r->alloc_enabled = true;
 
 		return true;
 	}
@@ -224,8 +224,8 @@ static bool rdt_get_mem_config(struct rdt_resource *r)
 	r->data_width = 3;
 	rdt_get_mba_infofile(r);
 
-	r->capable = true;
-	r->enabled = true;
+	r->alloc_capable = true;
+	r->alloc_enabled = true;
 
 	return true;
 }
@@ -242,8 +242,8 @@ static void rdt_get_cache_config(int idx, struct rdt_resource *r)
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
 	rdt_get_cache_infofile(r);
-	r->capable = true;
-	r->enabled = true;
+	r->alloc_capable = true;
+	r->alloc_enabled = true;
 }
 
 static void rdt_get_cdp_l3_config(int type)
@@ -255,12 +255,12 @@ static void rdt_get_cdp_l3_config(int type)
 	r->cache.cbm_len = r_l3->cache.cbm_len;
 	r->default_ctrl = r_l3->default_ctrl;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
-	r->capable = true;
+	r->alloc_capable = true;
 	/*
 	 * By default, CDP is disabled. CDP can be enabled by mount parameter
 	 * "cdp" during resctrl file system mount time.
 	 */
-	r->enabled = false;
+	r->alloc_enabled = false;
 }
 
 static int get_cache_id(int cpu, int level)
@@ -422,7 +422,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 
 	d->id = id;
 
-	if (domain_setup_ctrlval(r, d)) {
+	if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
 		kfree(d);
 		return;
 	}
@@ -464,7 +464,7 @@ static int intel_rdt_online_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		domain_add_cpu(cpu, r);
 	/* The cpu is set in default rdtgroup after online. */
 	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
@@ -480,7 +480,7 @@ static int intel_rdt_offline_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		domain_remove_cpu(cpu, r);
 	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
 		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
@@ -501,7 +501,7 @@ static __init void rdt_init_padding(void)
 	struct rdt_resource *r;
 	int cl;
 
-	for_each_capable_rdt_resource(r) {
+	for_each_alloc_capable_rdt_resource(r) {
 		cl = strlen(r->name);
 		if (cl > max_name_width)
 			max_name_width = cl;
@@ -565,7 +565,7 @@ static int __init intel_rdt_late_init(void)
 		return ret;
 	}
 
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		pr_info("Intel RDT %s allocation detected\n", r->name);
 
 	return 0;
arch/x86/kernel/cpu/intel_rdt.h +9 -9
index 0e4852d..29630af 100644
@@ -135,8 +135,8 @@ struct rdt_membw {
 
 /**
  * struct rdt_resource - attributes of an RDT resource
- * @enabled:		Is this feature enabled on this machine
- * @capable:		Is this feature available on this machine
+ * @alloc_enabled:	Is allocation enabled on this machine
+ * @alloc_capable:	Is allocation available on this machine
  * @name:		Name to use in "schemata" file
  * @num_closid:		Number of CLOSIDs available
  * @cache_level:	Which cache level defines scope of this resource
@@ -152,8 +152,8 @@ struct rdt_membw {
  * @parse_ctrlval:	Per resource function pointer to parse control values
  */
 struct rdt_resource {
-	bool			enabled;
-	bool			capable;
+	bool			alloc_enabled;
+	bool			alloc_capable;
 	char			*name;
 	int			num_closid;
 	int			cache_level;
@@ -181,7 +181,7 @@ struct rdt_resource {
 
 extern struct rdt_resource rdt_resources_all[];
 extern struct rdtgroup rdtgroup_default;
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 int __init rdtgroup_init(void);
 
@@ -196,15 +196,15 @@ enum {
 	RDT_NUM_RESOURCES,
 };
 
-#define for_each_capable_rdt_resource(r)				      \
+#define for_each_alloc_capable_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
-		if (r->capable)
+		if (r->alloc_capable)
 
-#define for_each_enabled_rdt_resource(r)				      \
+#define for_each_alloc_enabled_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
-		if (r->enabled)
+		if (r->alloc_enabled)
 
 /* CPUID.(EAX=10H, ECX=ResID=1).EAX */
 union cpuid_0x10_1_eax {
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +17 -16
index 3273e88..ce63d10 100644
@@ -35,7 +35,7 @@
 #include <asm/intel_rdt_sched.h>
 #include "intel_rdt.h"
 
-DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
+DEFINE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 static struct kernfs_root *rdt_root;
 struct rdtgroup rdtgroup_default;
 LIST_HEAD(rdt_all_groups);
@@ -66,7 +66,7 @@ static void closid_init(void)
 	int rdt_min_closid = 32;
 
 	/* Compute rdt_min_closid across all resources */
-	for_each_enabled_rdt_resource(r)
+	for_each_alloc_enabled_rdt_resource(r)
 		rdt_min_closid = min(rdt_min_closid, r->num_closid);
 
 	closid_free_map = BIT_MASK(rdt_min_closid) - 1;
@@ -638,7 +638,7 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
 		return PTR_ERR(kn_info);
 	kernfs_get(kn_info);
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		kn_subdir = kernfs_create_dir(kn_info, r->name,
 					      kn_info->mode, r);
 		if (IS_ERR(kn_subdir)) {
@@ -718,14 +718,15 @@ static int cdp_enable(void)
 	struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
 	int ret;
 
-	if (!r_l3->capable || !r_l3data->capable || !r_l3code->capable)
+	if (!r_l3->alloc_capable || !r_l3data->alloc_capable ||
+	    !r_l3code->alloc_capable)
 		return -EINVAL;
 
 	ret = set_l3_qos_cfg(r_l3, true);
 	if (!ret) {
-		r_l3->enabled = false;
-		r_l3data->enabled = true;
-		r_l3code->enabled = true;
+		r_l3->alloc_enabled = false;
+		r_l3data->alloc_enabled = true;
+		r_l3code->alloc_enabled = true;
 	}
 	return ret;
 }
@@ -734,11 +735,11 @@ static void cdp_disable(void)
 {
 	struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
 
-	r->enabled = r->capable;
+	r->alloc_enabled = r->alloc_capable;
 
-	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled) {
-		rdt_resources_all[RDT_RESOURCE_L3DATA].enabled = false;
-		rdt_resources_all[RDT_RESOURCE_L3CODE].enabled = false;
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled) {
+		rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled = false;
+		rdt_resources_all[RDT_RESOURCE_L3CODE].alloc_enabled = false;
 		set_l3_qos_cfg(r, false);
 	}
 }
@@ -834,7 +835,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 	/*
 	 * resctrl file system can only be mounted once.
 	 */
-	if (static_branch_unlikely(&rdt_enable_key)) {
+	if (static_branch_unlikely(&rdt_alloc_enable_key)) {
 		dentry = ERR_PTR(-EBUSY);
 		goto out;
 	}
@@ -858,7 +859,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 	if (IS_ERR(dentry))
 		goto out_destroy;
 
-	static_branch_enable(&rdt_enable_key);
+	static_branch_enable(&rdt_alloc_enable_key);
 	goto out;
 
 out_destroy:
@@ -986,11 +987,11 @@ static void rdt_kill_sb(struct super_block *sb)
 	mutex_lock(&rdtgroup_mutex);
 
 	/*Put everything back to default values. */
-	for_each_enabled_rdt_resource(r)
+	for_each_alloc_enabled_rdt_resource(r)
 		reset_all_ctrls(r);
 	cdp_disable();
 	rmdir_all_sub();
-	static_branch_disable(&rdt_enable_key);
+	static_branch_disable(&rdt_alloc_enable_key);
 	kernfs_kill_sb(sb);
 	mutex_unlock(&rdtgroup_mutex);
 }
@@ -1129,7 +1130,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 
 static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
 {
-	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled)
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled)
 		seq_puts(seq, ",cdp");
 	return 0;
 }
arch/x86/kernel/cpu/intel_rdt_schemata.c +4 -4
index 8cef1c8..952156c 100644
@@ -192,7 +192,7 @@ static int rdtgroup_parse_resource(char *resname, char *tok, int closid)
 {
 	struct rdt_resource *r;
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		if (!strcmp(resname, r->name) && closid < r->num_closid)
 			return parse_line(tok, r);
 	}
@@ -221,7 +221,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 
 	closid = rdtgrp->closid;
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		list_for_each_entry(dom, &r->domains, list)
 			dom->have_new_ctrl = false;
 	}
@@ -237,7 +237,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 			goto out;
 	}
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		ret = update_domains(r, closid);
 		if (ret)
 			goto out;
@@ -274,7 +274,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
 	if (rdtgrp) {
 		closid = rdtgrp->closid;
-		for_each_enabled_rdt_resource(r) {
+		for_each_alloc_enabled_rdt_resource(r) {
 			if (closid < r->num_closid)
 				show_doms(s, r, closid);
 		}
Signature · 1 line
1.9.1
#12 lore raw

[tip:x86/cache] x86/intel_rdt: Cleanup namespace to support RDT monitoring

x86/intel_rdt: Cleanup namespace to support RDT monitoring
Commit-ID:  1b5c0b7583173b787b5c93ff89838a950d0e23ff
Gitweb:     http://git.kernel.org/tip/1b5c0b7583173b787b5c93ff89838a950d0e23ff
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:25 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:20 +0200

x86/intel_rdt: Cleanup namespace to support RDT monitoring

Few of the data-structures have generic names although they are RDT allocation specific. Rename them to be allocation specific to accommodate RDT monitoring. E.g. s/enabled/alloc_enabled/

No functional change.

---
 arch/x86/include/asm/intel_rdt_sched.h   |  4 ++--
 arch/x86/kernel/cpu/intel_rdt.c          | 26 ++++++++++++-------------
 arch/x86/kernel/cpu/intel_rdt.h          | 18 ++++++++---------
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 33 ++++++++++++++++----------------
 arch/x86/kernel/cpu/intel_rdt_schemata.c |  8 ++++----
 5 files changed, 45 insertions(+), 44 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +2 -2
index 62a70bc..4dee77b 100644
@@ -27,7 +27,7 @@ struct intel_pqr_state {
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
 DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
  * intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
@@ -44,7 +44,7 @@ DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
  */
 static inline void intel_rdt_sched_in(void)
 {
-	if (static_branch_likely(&rdt_enable_key)) {
+	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 		int closid;
 
arch/x86/kernel/cpu/intel_rdt.c +13 -13
index 08872e9..835e1ff 100644
@@ -173,8 +173,8 @@ static inline bool cache_alloc_hsw_probe(void)
 		r->default_ctrl = max_cbm;
 		r->cache.cbm_len = 20;
 		r->cache.min_cbm_bits = 2;
-		r->capable = true;
-		r->enabled = true;
+		r->alloc_capable = true;
+		r->alloc_enabled = true;
 
 		return true;
 	}
@@ -224,8 +224,8 @@ static bool rdt_get_mem_config(struct rdt_resource *r)
 	r->data_width = 3;
 	rdt_get_mba_infofile(r);
 
-	r->capable = true;
-	r->enabled = true;
+	r->alloc_capable = true;
+	r->alloc_enabled = true;
 
 	return true;
 }
@@ -242,8 +242,8 @@ static void rdt_get_cache_config(int idx, struct rdt_resource *r)
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
 	rdt_get_cache_infofile(r);
-	r->capable = true;
-	r->enabled = true;
+	r->alloc_capable = true;
+	r->alloc_enabled = true;
 }
 
 static void rdt_get_cdp_l3_config(int type)
@@ -255,12 +255,12 @@ static void rdt_get_cdp_l3_config(int type)
 	r->cache.cbm_len = r_l3->cache.cbm_len;
 	r->default_ctrl = r_l3->default_ctrl;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
-	r->capable = true;
+	r->alloc_capable = true;
 	/*
 	 * By default, CDP is disabled. CDP can be enabled by mount parameter
 	 * "cdp" during resctrl file system mount time.
 	 */
-	r->enabled = false;
+	r->alloc_enabled = false;
 }
 
 static int get_cache_id(int cpu, int level)
@@ -422,7 +422,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 
 	d->id = id;
 
-	if (domain_setup_ctrlval(r, d)) {
+	if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
 		kfree(d);
 		return;
 	}
@@ -464,7 +464,7 @@ static int intel_rdt_online_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		domain_add_cpu(cpu, r);
 	/* The cpu is set in default rdtgroup after online. */
 	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
@@ -480,7 +480,7 @@ static int intel_rdt_offline_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		domain_remove_cpu(cpu, r);
 	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
 		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
@@ -501,7 +501,7 @@ static __init void rdt_init_padding(void)
 	struct rdt_resource *r;
 	int cl;
 
-	for_each_capable_rdt_resource(r) {
+	for_each_alloc_capable_rdt_resource(r) {
 		cl = strlen(r->name);
 		if (cl > max_name_width)
 			max_name_width = cl;
@@ -565,7 +565,7 @@ static int __init intel_rdt_late_init(void)
 		return ret;
 	}
 
-	for_each_capable_rdt_resource(r)
+	for_each_alloc_capable_rdt_resource(r)
 		pr_info("Intel RDT %s allocation detected\n", r->name);
 
 	return 0;
arch/x86/kernel/cpu/intel_rdt.h +9 -9
index 0e4852d..29630af 100644
@@ -135,8 +135,8 @@ struct rdt_membw {
 
 /**
  * struct rdt_resource - attributes of an RDT resource
- * @enabled:		Is this feature enabled on this machine
- * @capable:		Is this feature available on this machine
+ * @alloc_enabled:	Is allocation enabled on this machine
+ * @alloc_capable:	Is allocation available on this machine
  * @name:		Name to use in "schemata" file
  * @num_closid:		Number of CLOSIDs available
  * @cache_level:	Which cache level defines scope of this resource
@@ -152,8 +152,8 @@ struct rdt_membw {
  * @parse_ctrlval:	Per resource function pointer to parse control values
  */
 struct rdt_resource {
-	bool			enabled;
-	bool			capable;
+	bool			alloc_enabled;
+	bool			alloc_capable;
 	char			*name;
 	int			num_closid;
 	int			cache_level;
@@ -181,7 +181,7 @@ extern struct mutex rdtgroup_mutex;
 
 extern struct rdt_resource rdt_resources_all[];
 extern struct rdtgroup rdtgroup_default;
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 int __init rdtgroup_init(void);
 
@@ -196,15 +196,15 @@ enum {
 	RDT_NUM_RESOURCES,
 };
 
-#define for_each_capable_rdt_resource(r)				      \
+#define for_each_alloc_capable_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
-		if (r->capable)
+		if (r->alloc_capable)
 
-#define for_each_enabled_rdt_resource(r)				      \
+#define for_each_alloc_enabled_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
-		if (r->enabled)
+		if (r->alloc_enabled)
 
 /* CPUID.(EAX=10H, ECX=ResID=1).EAX */
 union cpuid_0x10_1_eax {
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +17 -16
index 3273e88..ce63d10 100644
@@ -35,7 +35,7 @@
 #include <asm/intel_rdt_sched.h>
 #include "intel_rdt.h"
 
-DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
+DEFINE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 static struct kernfs_root *rdt_root;
 struct rdtgroup rdtgroup_default;
 LIST_HEAD(rdt_all_groups);
@@ -66,7 +66,7 @@ static void closid_init(void)
 	int rdt_min_closid = 32;
 
 	/* Compute rdt_min_closid across all resources */
-	for_each_enabled_rdt_resource(r)
+	for_each_alloc_enabled_rdt_resource(r)
 		rdt_min_closid = min(rdt_min_closid, r->num_closid);
 
 	closid_free_map = BIT_MASK(rdt_min_closid) - 1;
@@ -638,7 +638,7 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
 		return PTR_ERR(kn_info);
 	kernfs_get(kn_info);
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		kn_subdir = kernfs_create_dir(kn_info, r->name,
 					      kn_info->mode, r);
 		if (IS_ERR(kn_subdir)) {
@@ -718,14 +718,15 @@ static int cdp_enable(void)
 	struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
 	int ret;
 
-	if (!r_l3->capable || !r_l3data->capable || !r_l3code->capable)
+	if (!r_l3->alloc_capable || !r_l3data->alloc_capable ||
+	    !r_l3code->alloc_capable)
 		return -EINVAL;
 
 	ret = set_l3_qos_cfg(r_l3, true);
 	if (!ret) {
-		r_l3->enabled = false;
-		r_l3data->enabled = true;
-		r_l3code->enabled = true;
+		r_l3->alloc_enabled = false;
+		r_l3data->alloc_enabled = true;
+		r_l3code->alloc_enabled = true;
 	}
 	return ret;
 }
@@ -734,11 +735,11 @@ static void cdp_disable(void)
 {
 	struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
 
-	r->enabled = r->capable;
+	r->alloc_enabled = r->alloc_capable;
 
-	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled) {
-		rdt_resources_all[RDT_RESOURCE_L3DATA].enabled = false;
-		rdt_resources_all[RDT_RESOURCE_L3CODE].enabled = false;
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled) {
+		rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled = false;
+		rdt_resources_all[RDT_RESOURCE_L3CODE].alloc_enabled = false;
 		set_l3_qos_cfg(r, false);
 	}
 }
@@ -834,7 +835,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 	/*
 	 * resctrl file system can only be mounted once.
 	 */
-	if (static_branch_unlikely(&rdt_enable_key)) {
+	if (static_branch_unlikely(&rdt_alloc_enable_key)) {
 		dentry = ERR_PTR(-EBUSY);
 		goto out;
 	}
@@ -858,7 +859,7 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 	if (IS_ERR(dentry))
 		goto out_destroy;
 
-	static_branch_enable(&rdt_enable_key);
+	static_branch_enable(&rdt_alloc_enable_key);
 	goto out;
 
 out_destroy:
@@ -986,11 +987,11 @@ static void rdt_kill_sb(struct super_block *sb)
 	mutex_lock(&rdtgroup_mutex);
 
 	/*Put everything back to default values. */
-	for_each_enabled_rdt_resource(r)
+	for_each_alloc_enabled_rdt_resource(r)
 		reset_all_ctrls(r);
 	cdp_disable();
 	rmdir_all_sub();
-	static_branch_disable(&rdt_enable_key);
+	static_branch_disable(&rdt_alloc_enable_key);
 	kernfs_kill_sb(sb);
 	mutex_unlock(&rdtgroup_mutex);
 }
@@ -1129,7 +1130,7 @@ out:
 
 static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
 {
-	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled)
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled)
 		seq_puts(seq, ",cdp");
 	return 0;
 }
arch/x86/kernel/cpu/intel_rdt_schemata.c +4 -4
index 8cef1c8..952156c 100644
@@ -192,7 +192,7 @@ static int rdtgroup_parse_resource(char *resname, char *tok, int closid)
 {
 	struct rdt_resource *r;
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		if (!strcmp(resname, r->name) && closid < r->num_closid)
 			return parse_line(tok, r);
 	}
@@ -221,7 +221,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 
 	closid = rdtgrp->closid;
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		list_for_each_entry(dom, &r->domains, list)
 			dom->have_new_ctrl = false;
 	}
@@ -237,7 +237,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 			goto out;
 	}
 
-	for_each_enabled_rdt_resource(r) {
+	for_each_alloc_enabled_rdt_resource(r) {
 		ret = update_domains(r, closid);
 		if (ret)
 			goto out;
@@ -274,7 +274,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
 	if (rdtgrp) {
 		closid = rdtgrp->closid;
-		for_each_enabled_rdt_resource(r) {
+		for_each_alloc_enabled_rdt_resource(r) {
 			if (closid < r->num_closid)
 				show_doms(s, r, closid);
 		}
#13 lore raw

PATCH v2 7/28 x86/intel_rdt: make rdt_resources_all more readable

In reply to Vikas Shivappa

Change the format of the global rdt_resources_all. This holds all the RDT resource structure initialization values. Make this more readable by using the format:

rdt_resources_all[] = {
	[<resource_index>] =
            {...
	    }
	...
}
---
 arch/x86/kernel/cpu/intel_rdt.c | 5 +++++
 1 file changed, 5 insertions(+)
arch/x86/kernel/cpu/intel_rdt.c +5 -0
index 835e1ff..98715c5 100644
@@ -63,6 +63,7 @@
 #define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains)
 
 struct rdt_resource rdt_resources_all[] = {
+	[RDT_RESOURCE_L3] =
 	{
 		.name			= "L3",
 		.domains		= domain_init(RDT_RESOURCE_L3),
@@ -77,6 +78,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L3DATA] =
 	{
 		.name			= "L3DATA",
 		.domains		= domain_init(RDT_RESOURCE_L3DATA),
@@ -91,6 +93,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L3CODE] =
 	{
 		.name			= "L3CODE",
 		.domains		= domain_init(RDT_RESOURCE_L3CODE),
@@ -105,6 +108,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L2] =
 	{
 		.name			= "L2",
 		.domains		= domain_init(RDT_RESOURCE_L2),
@@ -119,6 +123,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_MBA] =
 	{
 		.name			= "MB",
 		.domains		= domain_init(RDT_RESOURCE_MBA),
Signature · 1 line
1.9.1
#14 lore raw

[tip:x86/cache] x86/intel_rdt: Make rdt_resources_all more readable

x86/intel_rdt: Make rdt_resources_all more readable
Commit-ID:  dd131853f3fbc1c3aa051c34a2967c2f76309024
Gitweb:     http://git.kernel.org/tip/dd131853f3fbc1c3aa051c34a2967c2f76309024
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:26 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:20 +0200

x86/intel_rdt: Make rdt_resources_all more readable

Change the format of the global rdt_resources_all. This holds all the RDT resource structure initialization values. Make this more readable by using the format:

rdt_resources_all[] = {
	[<resource_index>] =
            {...
	    }
	...
}
---
 arch/x86/kernel/cpu/intel_rdt.c | 5 +++++
 1 file changed, 5 insertions(+)
arch/x86/kernel/cpu/intel_rdt.c +5 -0
index 835e1ff..98715c5 100644
@@ -63,6 +63,7 @@ cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
 #define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains)
 
 struct rdt_resource rdt_resources_all[] = {
+	[RDT_RESOURCE_L3] =
 	{
 		.name			= "L3",
 		.domains		= domain_init(RDT_RESOURCE_L3),
@@ -77,6 +78,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L3DATA] =
 	{
 		.name			= "L3DATA",
 		.domains		= domain_init(RDT_RESOURCE_L3DATA),
@@ -91,6 +93,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L3CODE] =
 	{
 		.name			= "L3CODE",
 		.domains		= domain_init(RDT_RESOURCE_L3CODE),
@@ -105,6 +108,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_L2] =
 	{
 		.name			= "L2",
 		.domains		= domain_init(RDT_RESOURCE_L2),
@@ -119,6 +123,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
 	},
+	[RDT_RESOURCE_MBA] =
 	{
 		.name			= "MB",
 		.domains		= domain_init(RDT_RESOURCE_MBA),
#15 lore raw

PATCH v2 8/28 x86/intel_rdt/cqm: Add RDT monitoring initialization

In reply to Vikas Shivappa

Add common data structures for RDT resource monitoring and perform RDT monitoring related data structure initializations which include setting up the RMID(Resource monitoring ID) lists and event list which the resource supports.

[tony: some cleanup to make adding MBM easier later, remove "cqm" from some names, make some data structure local to intel_rdt_monitor.c static. Add copyright header]

---
 arch/x86/kernel/cpu/Makefile            |   2 +-
 arch/x86/kernel/cpu/intel_rdt.c         |  46 ++++++++-
 arch/x86/kernel/cpu/intel_rdt.h         |  44 +++++++++
 arch/x86/kernel/cpu/intel_rdt_monitor.c | 161 ++++++++++++++++++++++++++++++++
 4 files changed, 248 insertions(+), 5 deletions(-)
 create mode 100644 arch/x86/kernel/cpu/intel_rdt_monitor.c
arch/x86/kernel/cpu/Makefile +1 -1
index a576121..81b0060 100644
@@ -32,7 +32,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o intel_rdt_monitor.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
arch/x86/kernel/cpu/intel_rdt.c +42 -4

88 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt.h +44 -0

87 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_monitor.c new file +161 -0

161 lines not on this page · raw message

Signature · 1 line
1.9.1
#16 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add RDT monitoring initialization

x86/intel_rdt/cqm: Add RDT monitoring initialization
Commit-ID:  6a445edce657810992594c7b9e679219aaf78ad9
Gitweb:     http://git.kernel.org/tip/6a445edce657810992594c7b9e679219aaf78ad9
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:27 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:21 +0200

x86/intel_rdt/cqm: Add RDT monitoring initialization

Add common data structures for RDT resource monitoring and perform RDT monitoring related data structure initializations which include setting up the RMID(Resource monitoring ID) lists and event list which the resource supports.

[ tony: some cleanup to make adding MBM easier later, remove "cqm" from
some names, make some data structure local to intel_rdt_monitor.c static. Add copyright header]

[ tglx: Made it readable ]

---
 arch/x86/kernel/cpu/Makefile            |   2 +-
 arch/x86/kernel/cpu/intel_rdt.c         |  41 +++++++-
 arch/x86/kernel/cpu/intel_rdt.h         |  44 +++++++++
 arch/x86/kernel/cpu/intel_rdt_monitor.c | 161 ++++++++++++++++++++++++++++++++
 4 files changed, 242 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/Makefile +1 -1
index 3622ca2..7584be0 100644
@@ -33,7 +33,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o intel_rdt_monitor.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
arch/x86/kernel/cpu/intel_rdt.c +36 -5

86 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt.h +44 -0

87 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_monitor.c new file +161 -0

161 lines not on this page · raw message

#17 lore raw

PATCH v2 9/28 x86/intel_rdt/cqm: Add RMID(Resource monitoring ID) management

In reply to Vikas Shivappa

Hardware uses RMID(Resource monitoring ID) to keep track of each of the RDT events associated with tasks. The number of RMIDs is dependent on the SKU and is enumerated via CPUID. We add support to manage the RMIDs which include managing the RMID allocation and reading LLC occupancy for an RMID.

RMID allocation is managed by keeping a free list which is initialized to all available RMIDs except for RMID 0 which is always reserved for root group. RMIDs goto a limbo list once they are
freed since the RMIDs are still tagged to cache lines of the tasks which were using them - thereby still having some occupancy. They continue to be in limbo list until the occupancy < threshold_occupancy. The threshold_occupancy is a user configurable value.
OS uses IA32_QM_CTR MSR to read the occupancy associated with an RMID after programming the IA32_EVENTSEL MSR with the RMID.

[Tony: Improved limbo search]

---
 arch/x86/kernel/cpu/intel_rdt.c         |  32 +++++
 arch/x86/kernel/cpu/intel_rdt.h         |   6 +
 arch/x86/kernel/cpu/intel_rdt_monitor.c | 213 ++++++++++++++++++++++++++++++++
 3 files changed, 251 insertions(+)
arch/x86/kernel/cpu/intel_rdt.c +32 -0
index 36e6454..fe6dc75 100644
@@ -320,6 +320,19 @@ static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
 		wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]);
 }
 
+struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
+{
+	struct rdt_domain *d;
+
+	list_for_each_entry(d, &r->domains, list) {
+		/* Find the domain that contains this CPU */
+		if (cpumask_test_cpu(cpu, &d->cpu_mask))
+			return d;
+	}
+
+	return NULL;
+}
+
 void rdt_ctrl_update(void *arg)
 {
 	struct msr_param *m = arg;
@@ -397,6 +410,19 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
 	return 0;
 }
 
+static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
+{
+	if (is_llc_occupancy_enabled()) {
+		d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid),
+					   sizeof(unsigned long),
+					   GFP_KERNEL);
+		if (!d->rmid_busy_llc)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
 /*
  * domain_add_cpu - Add a cpu to a resource's domain list.
  *
@@ -438,6 +464,11 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 	}
 
+	if (r->mon_capable && domain_setup_mon_state(r, d)) {
+		kfree(d);
+		return;
+	}
+
 	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
 }
@@ -456,6 +487,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 	cpumask_clear_cpu(cpu, &d->cpu_mask);
 	if (cpumask_empty(&d->cpu_mask)) {
 		kfree(d->ctrl_val);
+		kfree(d->rmid_busy_llc);
 		list_del(&d->list);
 		kfree(d);
 	}
arch/x86/kernel/cpu/intel_rdt.h +6 -0
index 993ab9d..35bf8eb 100644
@@ -19,6 +19,8 @@
 #define QOS_L3_OCCUP_EVENT_ID		0x01
 #define QOS_L3_MBM_TOTAL_EVENT_ID	0x02
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
+#define RMID_VAL_ERROR			BIT_ULL(63)
+#define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
 /**
  * struct mon_evt - Entry in the event list of a resource
@@ -98,6 +100,8 @@ struct rftype {
  * @list:	all instances of this resource
  * @id:		unique id for this instance
  * @cpu_mask:	which cpus share this resource
+ * @rmid_busy_llc:
+ *		bitmap of which limbo RMIDs are above threshold
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -106,6 +110,7 @@ struct rdt_domain {
 	struct list_head	list;
 	int			id;
 	struct cpumask		cpu_mask;
+	unsigned long		*rmid_busy_llc;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -282,6 +287,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 				char *buf, size_t nbytes, loff_t off);
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			   struct seq_file *s, void *v);
+struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +213 -0

227 lines not on this page · raw message

Signature · 1 line
1.9.1
#18 lore raw

Re: [PATCH 09/28] x86/intel_rdt/cqm: Add RMID(Resource monitoring ID) management

Quoted 16 lines · Vikas Shivappa

Hardware uses RMID(Resource monitoring ID) to keep track of each of the RDT events associated with tasks. The number of RMIDs is dependent on the SKU and is enumerated via CPUID. We add support to manage the RMIDs which include managing the RMID allocation and reading LLC occupancy for an RMID.

RMID allocation is managed by keeping a free list which is initialized to all available RMIDs except for RMID 0 which is always reserved for root group. RMIDs goto a limbo list once they are
freed since the RMIDs are still tagged to cache lines of the tasks which were using them - thereby still having some occupancy. They continue to be in limbo list until the occupancy < threshold_occupancy. The threshold_occupancy is a user configurable value.
OS uses IA32_QM_CTR MSR to read the occupancy associated with an RMID after programming the IA32_EVENTSEL MSR with the RMID.

Quoted 1 line

[Tony: Improved limbo search]

The search is smarter, but the smp function call problem per se persists. It's still more than 100us worstcase on a BDW box and it's going to be worse with the next generation.

Thanks,

tglx

#19 lore raw

Re: [PATCH 09/28] x86/intel_rdt/cqm: Add RMID(Resource monitoring ID) management

Quoted 17 lines · Thomas Gleixner
Quoted 16 lines · Vikas Shivappa

Hardware uses RMID(Resource monitoring ID) to keep track of each of the RDT events associated with tasks. The number of RMIDs is dependent on the SKU and is enumerated via CPUID. We add support to manage the RMIDs which include managing the RMID allocation and reading LLC occupancy for an RMID.

RMID allocation is managed by keeping a free list which is initialized to all available RMIDs except for RMID 0 which is always reserved for root group. RMIDs goto a limbo list once they are
freed since the RMIDs are still tagged to cache lines of the tasks which were using them - thereby still having some occupancy. They continue to be in limbo list until the occupancy < threshold_occupancy. The threshold_occupancy is a user configurable value.
OS uses IA32_QM_CTR MSR to read the occupancy associated with an RMID after programming the IA32_EVENTSEL MSR with the RMID.

Quoted 5 lines
Quoted 1 line

[Tony: Improved limbo search]

The search is smarter, but the smp function call problem per se persists. It's still more than 100us worstcase on a BDW box and it's going to be worse with the next generation

As an alternative we could have delayed worker threads(hence not in interrupt context) every 1s to check the limbo lists using the same optimized search with 1 bit per RMID.

When a mkdir tries to get RMID if no RMID is in free list and some are present in limbo we return -EBUSY and if both free and limbo lists are empty we return -ENOSPC.

If that is reasonable I can send an updated patch for the same.

Thanks,
Vikas

Quoted 5 lines

Thanks,

tglx

#20 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add RMID (Resource monitoring ID) management

In reply to Vikas Shivappa
x86/intel_rdt/cqm: Add RMID (Resource monitoring ID) management
Commit-ID:  edf6fa1c4a951b3a03e94b63e6483c5d9da3ab11
Gitweb:     http://git.kernel.org/tip/edf6fa1c4a951b3a03e94b63e6483c5d9da3ab11
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:28 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:21 +0200

x86/intel_rdt/cqm: Add RMID (Resource monitoring ID) management

Hardware uses RMID(Resource monitoring ID) to keep track of each of the RDT events associated with tasks. The number of RMIDs is dependent on the SKU and is enumerated via CPUID. We add support to manage the RMIDs which include managing the RMID allocation and reading LLC occupancy for an RMID.

RMID allocation is managed by keeping a free list which is initialized to all available RMIDs except for RMID 0 which is always reserved for root group. RMIDs goto a limbo list once they are
freed since the RMIDs are still tagged to cache lines of the tasks which were using them - thereby still having some occupancy. They continue to be in limbo list until the occupancy < threshold_occupancy. The threshold_occupancy is a user configurable value.
OS uses IA32_QM_CTR MSR to read the occupancy associated with an RMID after programming the IA32_EVENTSEL MSR with the RMID.

[Tony: Improved limbo search]

---
 arch/x86/kernel/cpu/intel_rdt.c         |  32 +++++
 arch/x86/kernel/cpu/intel_rdt.h         |   6 +
 arch/x86/kernel/cpu/intel_rdt_monitor.c | 213 ++++++++++++++++++++++++++++++++
 3 files changed, 251 insertions(+)
arch/x86/kernel/cpu/intel_rdt.c +32 -0
index cb520dd..d30830a 100644
@@ -320,6 +320,19 @@ cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
 		wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]);
 }
 
+struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
+{
+	struct rdt_domain *d;
+
+	list_for_each_entry(d, &r->domains, list) {
+		/* Find the domain that contains this CPU */
+		if (cpumask_test_cpu(cpu, &d->cpu_mask))
+			return d;
+	}
+
+	return NULL;
+}
+
 void rdt_ctrl_update(void *arg)
 {
 	struct msr_param *m = arg;
@@ -397,6 +410,19 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
 	return 0;
 }
 
+static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
+{
+	if (is_llc_occupancy_enabled()) {
+		d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid),
+					   sizeof(unsigned long),
+					   GFP_KERNEL);
+		if (!d->rmid_busy_llc)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
 /*
  * domain_add_cpu - Add a cpu to a resource's domain list.
  *
@@ -438,6 +464,11 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 	}
 
+	if (r->mon_capable && domain_setup_mon_state(r, d)) {
+		kfree(d);
+		return;
+	}
+
 	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
 }
@@ -456,6 +487,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 	cpumask_clear_cpu(cpu, &d->cpu_mask);
 	if (cpumask_empty(&d->cpu_mask)) {
 		kfree(d->ctrl_val);
+		kfree(d->rmid_busy_llc);
 		list_del(&d->list);
 		kfree(d);
 	}
arch/x86/kernel/cpu/intel_rdt.h +6 -0
index 993ab9d..35bf8eb 100644
@@ -19,6 +19,8 @@
 #define QOS_L3_OCCUP_EVENT_ID		0x01
 #define QOS_L3_MBM_TOTAL_EVENT_ID	0x02
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
+#define RMID_VAL_ERROR			BIT_ULL(63)
+#define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
 /**
  * struct mon_evt - Entry in the event list of a resource
@@ -98,6 +100,8 @@ struct rftype {
  * @list:	all instances of this resource
  * @id:		unique id for this instance
  * @cpu_mask:	which cpus share this resource
+ * @rmid_busy_llc:
+ *		bitmap of which limbo RMIDs are above threshold
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -106,6 +110,7 @@ struct rdt_domain {
 	struct list_head	list;
 	int			id;
 	struct cpumask		cpu_mask;
+	unsigned long		*rmid_busy_llc;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -282,6 +287,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 				char *buf, size_t nbytes, loff_t off);
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			   struct seq_file *s, void *v);
+struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +213 -0

227 lines not on this page · raw message

#21 lore raw

PATCH v2 10/28 x86/intel_rdt: Simplify info and base file lists

In reply to Vikas Shivappa

From: Tony luck <[email protected]>

The info directory files and base files need to be different for each resource like cache and Memory bandwidth. With in each resource, the files would be further different for monitoring and ctrl. This leads to a lot of different static array declarations given that we are adding resctrl monitoring.

Simplify this to one common list of files and then declare a set of flags to choose the files based on the resource, whether it is info or base and if it is control type file. This is as a preparation to include monitoring based info and base files.

No functional change.

[Vikas: Extended the flags to have few bits per category like resource, info/base etc]

---
 arch/x86/kernel/cpu/intel_rdt.c          |   7 +-
 arch/x86/kernel/cpu/intel_rdt.h          |  22 +++-
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 191 +++++++++++++++----------------
 3 files changed, 115 insertions(+), 105 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +5 -2
index fe6dc75..eab2467 100644
@@ -83,6 +83,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L3DATA] =
 	{
@@ -98,6 +99,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L3CODE] =
 	{
@@ -113,6 +115,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L2] =
 	{
@@ -128,6 +131,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_MBA] =
 	{
@@ -138,6 +142,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.cache_level		= 3,
 		.parse_ctrlval		= parse_bw,
 		.format_str		= "%d=%*d",
+		.fflags			= RFTYPE_RES_MB,
 	},
 };
 
@@ -233,7 +238,6 @@ static bool rdt_get_mem_config(struct rdt_resource *r)
 			return false;
 	}
 	r->data_width = 3;
-	rdt_get_mba_infofile(r);
 
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
@@ -252,7 +256,6 @@ static void rdt_get_cache_alloc_config(int idx, struct rdt_resource *r)
 	r->cache.cbm_len = eax.split.cbm_len + 1;
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
-	rdt_get_cache_infofile(r);
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
 }
arch/x86/kernel/cpu/intel_rdt.h +16 -6
index 35bf8eb..aecbe77 100644
@@ -62,6 +62,18 @@ struct rdtgroup {
 /* rftype.flags */
 #define RFTYPE_FLAGS_CPUS_LIST	1
 
+/*
+ * Define the file type flags for base and info directories.
+ */
+#define RFTYPE_INFO			BIT(0)
+#define RFTYPE_BASE			BIT(1)
+#define RF_CTRLSHIFT			4
+#define RFTYPE_CTRL			BIT(RF_CTRLSHIFT)
+#define RFTYPE_RES_CACHE		BIT(8)
+#define RFTYPE_RES_MB			BIT(9)
+#define RF_CTRL_INFO			(RFTYPE_INFO | RFTYPE_CTRL)
+#define RF_CTRL_BASE			(RFTYPE_BASE | RFTYPE_CTRL)
+
 /* List of all resource groups */
 extern struct list_head rdt_all_groups;
 
@@ -75,6 +87,7 @@ struct rdtgroup {
  * @mode:	Access mode
  * @kf_ops:	File operations
  * @flags:	File specific RFTYPE_FLAGS_* flags
+ * @fflags:	File specific RF_* or RFTYPE_* flags
  * @seq_show:	Show content of the file
  * @write:	Write to the file
  */
@@ -83,6 +96,7 @@ struct rftype {
 	umode_t			mode;
 	struct kernfs_ops	*kf_ops;
 	unsigned long		flags;
+	unsigned long		fflags;
 
 	int (*seq_show)(struct kernfs_open_file *of,
 			struct seq_file *sf, void *v);
@@ -181,13 +195,12 @@ static inline bool is_llc_occupancy_enabled(void)
  * @data_width:		Character width of data when displaying
  * @domains:		All domains for this resource
  * @cache:		Cache allocation related data
- * @info_files:		resctrl info files for the resource
- * @nr_info_files:	Number of info files
  * @format_str:		Per resource format string to show domain value
  * @parse_ctrlval:	Per resource function pointer to parse control values
  * @evt_list:			List of monitoring events
  * @num_rmid:			Number of RMIDs available
  * @mon_scale:			cqm counter * mon_scale = occupancy in bytes
+ * @fflags:			flags to choose base and info files
  */
 struct rdt_resource {
 	bool			alloc_enabled;
@@ -205,18 +218,15 @@ struct rdt_resource {
 	struct list_head	domains;
 	struct rdt_cache	cache;
 	struct rdt_membw	membw;
-	struct rftype		*info_files;
-	int			nr_info_files;
 	const char		*format_str;
 	int (*parse_ctrlval)	(char *buf, struct rdt_resource *r,
 				 struct rdt_domain *d);
 	struct list_head	evt_list;
 	int			num_rmid;
 	unsigned int		mon_scale;
+	unsigned long		fflags;
 };
 
-void rdt_get_cache_infofile(struct rdt_resource *r);
-void rdt_get_mba_infofile(struct rdt_resource *r);
 int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d);
 int parse_bw(char *buf, struct rdt_resource *r,  struct rdt_domain *d);
 
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +94 -97

276 lines not on this page · raw message

Signature · 1 line
1.9.1
#22 lore raw

Re: [PATCH 10/28] x86/intel_rdt: Simplify info and base file lists

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) · line 659

Quoted 13 lines · Vikas Shivappa
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +2 -9
 	for_each_alloc_enabled_rdt_resource(r) {
-		kn_subdir = kernfs_create_dir(kn_info, r->name,
-					      kn_info->mode, r);
-		if (IS_ERR(kn_subdir)) {
-			ret = PTR_ERR(kn_subdir);
-			goto out_destroy;
-		}
-		kernfs_get(kn_subdir);
-		ret = rdtgroup_kn_set_ugid(kn_subdir);
-		if (ret)
+		fflags =  r->fflags | RF_CTRL_INFO;
+		if (rdtgroup_mkdir_info_resdir(r, r->name, fflags))
 			goto out_destroy;

This returns uninitialized ret. Compiler warnins are overrated....

Thanks,

tglx

#23 lore raw

[tip:x86/cache] x86/intel_rdt: Simplify info and base file lists

In reply to Vikas Shivappa
x86/intel_rdt: Simplify info and base file lists
Commit-ID:  5dc1d5c6bac2cfe3420cf353dfb0ef2e543f7c10
Gitweb:     http://git.kernel.org/tip/5dc1d5c6bac2cfe3420cf353dfb0ef2e543f7c10
Author:     Tony luck <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:29 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:22 +0200

x86/intel_rdt: Simplify info and base file lists

The info directory files and base files need to be different for each resource like cache and Memory bandwidth. With in each resource, the files would be further different for monitoring and ctrl. This leads to a lot of different static array declarations given that we are adding resctrl monitoring.

Simplify this to one common list of files and then declare a set of flags to choose the files based on the resource, whether it is info or base and if it is control type file. This is as a preparation to include monitoring based info and base files.

No functional change.

[Vikas: Extended the flags to have few bits per category like resource,
info/base etc]

---
 arch/x86/kernel/cpu/intel_rdt.c          |   7 +-
 arch/x86/kernel/cpu/intel_rdt.h          |  22 +++-
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 187 +++++++++++++++----------------
 3 files changed, 112 insertions(+), 104 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +5 -2
index d30830a..7cae4ec 100644
@@ -83,6 +83,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L3DATA] =
 	{
@@ -98,6 +99,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L3CODE] =
 	{
@@ -113,6 +115,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_L2] =
 	{
@@ -128,6 +131,7 @@ struct rdt_resource rdt_resources_all[] = {
 		},
 		.parse_ctrlval		= parse_cbm,
 		.format_str		= "%d=%0*x",
+		.fflags			= RFTYPE_RES_CACHE,
 	},
 	[RDT_RESOURCE_MBA] =
 	{
@@ -138,6 +142,7 @@ struct rdt_resource rdt_resources_all[] = {
 		.cache_level		= 3,
 		.parse_ctrlval		= parse_bw,
 		.format_str		= "%d=%*d",
+		.fflags			= RFTYPE_RES_MB,
 	},
 };
 
@@ -233,7 +238,6 @@ static bool rdt_get_mem_config(struct rdt_resource *r)
 			return false;
 	}
 	r->data_width = 3;
-	rdt_get_mba_infofile(r);
 
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
@@ -252,7 +256,6 @@ static void rdt_get_cache_alloc_cfg(int idx, struct rdt_resource *r)
 	r->cache.cbm_len = eax.split.cbm_len + 1;
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
-	rdt_get_cache_infofile(r);
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
 }
arch/x86/kernel/cpu/intel_rdt.h +16 -6
index 35bf8eb..aecbe77 100644
@@ -62,6 +62,18 @@ struct rdtgroup {
 /* rftype.flags */
 #define RFTYPE_FLAGS_CPUS_LIST	1
 
+/*
+ * Define the file type flags for base and info directories.
+ */
+#define RFTYPE_INFO			BIT(0)
+#define RFTYPE_BASE			BIT(1)
+#define RF_CTRLSHIFT			4
+#define RFTYPE_CTRL			BIT(RF_CTRLSHIFT)
+#define RFTYPE_RES_CACHE		BIT(8)
+#define RFTYPE_RES_MB			BIT(9)
+#define RF_CTRL_INFO			(RFTYPE_INFO | RFTYPE_CTRL)
+#define RF_CTRL_BASE			(RFTYPE_BASE | RFTYPE_CTRL)
+
 /* List of all resource groups */
 extern struct list_head rdt_all_groups;
 
@@ -75,6 +87,7 @@ int __init rdtgroup_init(void);
  * @mode:	Access mode
  * @kf_ops:	File operations
  * @flags:	File specific RFTYPE_FLAGS_* flags
+ * @fflags:	File specific RF_* or RFTYPE_* flags
  * @seq_show:	Show content of the file
  * @write:	Write to the file
  */
@@ -83,6 +96,7 @@ struct rftype {
 	umode_t			mode;
 	struct kernfs_ops	*kf_ops;
 	unsigned long		flags;
+	unsigned long		fflags;
 
 	int (*seq_show)(struct kernfs_open_file *of,
 			struct seq_file *sf, void *v);
@@ -181,13 +195,12 @@ static inline bool is_llc_occupancy_enabled(void)
  * @data_width:		Character width of data when displaying
  * @domains:		All domains for this resource
  * @cache:		Cache allocation related data
- * @info_files:		resctrl info files for the resource
- * @nr_info_files:	Number of info files
  * @format_str:		Per resource format string to show domain value
  * @parse_ctrlval:	Per resource function pointer to parse control values
  * @evt_list:			List of monitoring events
  * @num_rmid:			Number of RMIDs available
  * @mon_scale:			cqm counter * mon_scale = occupancy in bytes
+ * @fflags:			flags to choose base and info files
  */
 struct rdt_resource {
 	bool			alloc_enabled;
@@ -205,18 +218,15 @@ struct rdt_resource {
 	struct list_head	domains;
 	struct rdt_cache	cache;
 	struct rdt_membw	membw;
-	struct rftype		*info_files;
-	int			nr_info_files;
 	const char		*format_str;
 	int (*parse_ctrlval)	(char *buf, struct rdt_resource *r,
 				 struct rdt_domain *d);
 	struct list_head	evt_list;
 	int			num_rmid;
 	unsigned int		mon_scale;
+	unsigned long		fflags;
 };
 
-void rdt_get_cache_infofile(struct rdt_resource *r);
-void rdt_get_mba_infofile(struct rdt_resource *r);
 int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d);
 int parse_bw(char *buf, struct rdt_resource *r,  struct rdt_domain *d);
 
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +91 -96

273 lines not on this page · raw message

#24 lore raw

PATCH v2 11/28 x86/intel_rdt/cqm: Add info files for RDT monitoring

In reply to Vikas Shivappa

Add info directory files specific to RDT monitoring.

num_rmids:
The number of RMIDs which are valid for the resource.

mon_features:
Lists the monitoring events if monitoring is enabled for the resource.

max_threshold_occupancy:
This is specific to llc_occupancy monitoring and is used to determine if an RMID can be reused. Provides an upper bound on the threshold and is shown to the user in bytes though the internal value will be rounded to the scaling factor supported by the h/w.

---
 arch/x86/kernel/cpu/intel_rdt.h          |  8 ++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 82 ++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)
arch/x86/kernel/cpu/intel_rdt.h +8 -0
index aecbe77..4051f5e 100644
@@ -68,10 +68,13 @@ struct rdtgroup {
 #define RFTYPE_INFO			BIT(0)
 #define RFTYPE_BASE			BIT(1)
 #define RF_CTRLSHIFT			4
+#define RF_MONSHIFT			5
 #define RFTYPE_CTRL			BIT(RF_CTRLSHIFT)
+#define RFTYPE_MON			BIT(RF_MONSHIFT)
 #define RFTYPE_RES_CACHE		BIT(8)
 #define RFTYPE_RES_MB			BIT(9)
 #define RF_CTRL_INFO			(RFTYPE_INFO | RFTYPE_CTRL)
+#define RF_MON_INFO			(RFTYPE_INFO | RFTYPE_MON)
 #define RF_CTRL_BASE			(RFTYPE_BASE | RFTYPE_CTRL)
 
 /* List of all resource groups */
@@ -264,6 +267,11 @@ enum {
 	     r++)							      \
 		if (r->alloc_enabled)
 
+#define for_each_mon_enabled_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++)							      \
+		if (r->mon_enabled)
+
 /* CPUID.(EAX=10H, ECX=ResID=1).EAX */
 union cpuid_0x10_1_eax {
 	struct {
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +82 -0

118 lines not on this page · raw message

Signature · 1 line
1.9.1
#25 lore raw

Re: [PATCH 11/28] x86/intel_rdt/cqm: Add info files for RDT monitoring

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) · line 741

Quoted 11 lines · Vikas Shivappa
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +7 -0
@@ -658,6 +732,14 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
 		if (rdtgroup_mkdir_info_resdir(r, r->name, fflags))
 			goto out_destroy;
 	}
+
+	for_each_mon_enabled_rdt_resource(r) {
+		fflags =  r->fflags | RF_MON_INFO;
+		sprintf(name, "%s_MON", r->name);
+		if (rdtgroup_mkdir_info_resdir(r, name, fflags))
+			goto out_destroy;
+	}

Copy and paste and still the compiler complains ....

#26 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add info files for RDT monitoring

In reply to Vikas Shivappa
x86/intel_rdt/cqm: Add info files for RDT monitoring
Commit-ID:  d4ab33201029913b594ae785a9665f45040396ab
Gitweb:     http://git.kernel.org/tip/d4ab33201029913b594ae785a9665f45040396ab
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:30 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:22 +0200

x86/intel_rdt/cqm: Add info files for RDT monitoring

Add info directory files specific to RDT monitoring.

num_rmids:
The number of RMIDs which are valid for the resource.

mon_features:
Lists the monitoring events if monitoring is enabled for the resource.

max_threshold_occupancy:
This is specific to llc_occupancy monitoring and is used to determine if an RMID can be reused. Provides an upper bound on the threshold and is shown to the user in bytes though the internal value will be rounded to the scaling factor supported by the h/w.

---
 arch/x86/kernel/cpu/intel_rdt.h          |  8 +++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 83 ++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
arch/x86/kernel/cpu/intel_rdt.h +8 -0
index aecbe77..4051f5e 100644
@@ -68,10 +68,13 @@ struct rdtgroup {
 #define RFTYPE_INFO			BIT(0)
 #define RFTYPE_BASE			BIT(1)
 #define RF_CTRLSHIFT			4
+#define RF_MONSHIFT			5
 #define RFTYPE_CTRL			BIT(RF_CTRLSHIFT)
+#define RFTYPE_MON			BIT(RF_MONSHIFT)
 #define RFTYPE_RES_CACHE		BIT(8)
 #define RFTYPE_RES_MB			BIT(9)
 #define RF_CTRL_INFO			(RFTYPE_INFO | RFTYPE_CTRL)
+#define RF_MON_INFO			(RFTYPE_INFO | RFTYPE_MON)
 #define RF_CTRL_BASE			(RFTYPE_BASE | RFTYPE_CTRL)
 
 /* List of all resource groups */
@@ -264,6 +267,11 @@ enum {
 	     r++)							      \
 		if (r->alloc_enabled)
 
+#define for_each_mon_enabled_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++)							      \
+		if (r->mon_enabled)
+
 /* CPUID.(EAX=10H, ECX=ResID=1).EAX */
 union cpuid_0x10_1_eax {
 	struct {
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +83 -0

119 lines not on this page · raw message

#27 lore raw

PATCH v2 12/28 x86/intel_rdt: Prepare for RDT monitoring mkdir support

In reply to Vikas Shivappa

Separate the ctrl mkdir code from the rest in order to prepare for adding support for RDT monitoring mkdir support as well.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 112 ++++++++++++++++++++++---------
 1 file changed, 80 insertions(+), 32 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +80 -32
index d121339..64d4963 100644
@@ -1083,46 +1083,35 @@ static void rdt_kill_sb(struct super_block *sb)
 	.kill_sb = rdt_kill_sb,
 };
 
-static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
-			  umode_t mode)
+static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
+			     struct kernfs_node *prgrp_kn,
+			     const char *name, umode_t mode,
+			     struct rdtgroup **r)
 {
-	struct rdtgroup *parent, *rdtgrp;
+	struct rdtgroup *prdtgrp, *rdtgrp;
 	struct kernfs_node *kn;
-	int ret, closid;
-
-	/* Only allow mkdir in the root directory */
-	if (parent_kn != rdtgroup_default.kn)
-		return -EPERM;
-
-	/* Do not accept '\n' to avoid unparsable situation. */
-	if (strchr(name, '\n'))
-		return -EINVAL;
+	uint files = 0;
+	int ret;
 
-	parent = rdtgroup_kn_lock_live(parent_kn);
-	if (!parent) {
+	prdtgrp = rdtgroup_kn_lock_live(prgrp_kn);
+	if (!prdtgrp) {
 		ret = -ENODEV;
 		goto out_unlock;
 	}
 
-	ret = closid_alloc();
-	if (ret < 0)
-		goto out_unlock;
-	closid = ret;
-
 	/* allocate the rdtgroup. */
 	rdtgrp = kzalloc(sizeof(*rdtgrp), GFP_KERNEL);
 	if (!rdtgrp) {
 		ret = -ENOSPC;
-		goto out_closid_free;
+		goto out_unlock;
 	}
-	rdtgrp->closid = closid;
-	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+	*r = rdtgrp;
 
 	/* kernfs creates the directory for rdtgrp */
-	kn = kernfs_create_dir(parent->kn, name, mode, rdtgrp);
+	kn = kernfs_create_dir(parent_kn, name, mode, rdtgrp);
 	if (IS_ERR(kn)) {
 		ret = PTR_ERR(kn);
-		goto out_cancel_ref;
+		goto out_free_rgrp;
 	}
 	rdtgrp->kn = kn;
 
@@ -1138,27 +1127,86 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	if (ret)
 		goto out_destroy;
 
-	ret = rdtgroup_add_files(kn, RF_CTRL_BASE);
+	files = RFTYPE_BASE | RFTYPE_CTRL;
+	ret = rdtgroup_add_files(kn, files);
 	if (ret)
 		goto out_destroy;
 
 	kernfs_activate(kn);
 
-	ret = 0;
-	goto out_unlock;
+	/*
+	 * The caller unlocks the prgrp_kn upon success.
+	 */
+	return 0;
 
 out_destroy:
 	kernfs_remove(rdtgrp->kn);
-out_cancel_ref:
-	list_del(&rdtgrp->rdtgroup_list);
+out_free_rgrp:
 	kfree(rdtgrp);
-out_closid_free:
-	closid_free(closid);
 out_unlock:
-	rdtgroup_kn_unlock(parent_kn);
+	rdtgroup_kn_unlock(prgrp_kn);
+	return ret;
+}
+
+static void mkdir_rdt_prepare_clean(struct rdtgroup *rgrp)
+{
+	kernfs_remove(rgrp->kn);
+	kfree(rgrp);
+}
+
+/*
+ * These are rdtgroups created under the root directory. Can be used
+ * to allocate resources.
+ */
+static int rdtgroup_mkdir_ctrl(struct kernfs_node *parent_kn,
+			       struct kernfs_node *prgrp_kn,
+			       const char *name, umode_t mode)
+{
+	struct rdtgroup *rdtgrp;
+	struct kernfs_node *kn;
+	u32 closid;
+	int ret;
+
+	ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, &rdtgrp);
+	if (ret)
+		return ret;
+
+	kn = rdtgrp->kn;
+	ret = closid_alloc();
+	if (ret < 0)
+		goto out_common_fail;
+	closid = ret;
+
+	rdtgrp->closid = closid;
+	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+
+	goto out_unlock;
+
+out_common_fail:
+	mkdir_rdt_prepare_clean(rdtgrp);
+out_unlock:
+	rdtgroup_kn_unlock(prgrp_kn);
 	return ret;
 }
 
+static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
+			  umode_t mode)
+{
+	/* Do not accept '\n' to avoid unparsable situation. */
+	if (strchr(name, '\n'))
+		return -EINVAL;
+
+	/*
+	 * If the parent directory is the root directory and RDT
+	 * allocation is supported, add a control rdtgroup.
+	 */
+	if (rdt_alloc_capable && parent_kn == rdtgroup_default.kn)
+		return rdtgroup_mkdir_ctrl(parent_kn, parent_kn, name,
+					       mode);
+
+	return -EPERM;
+}
+
 static int rdtgroup_rmdir(struct kernfs_node *kn)
 {
 	int ret, cpu, closid = rdtgroup_default.closid;
Signature · 1 line
1.9.1
#28 lore raw

[tip:x86/cache] x86/intel_rdt: Prepare for RDT monitoring mkdir support

x86/intel_rdt: Prepare for RDT monitoring mkdir support
Commit-ID:  65b4f403057e32da73c36e33d403890173c4c324
Gitweb:     http://git.kernel.org/tip/65b4f403057e32da73c36e33d403890173c4c324
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:31 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:23 +0200

x86/intel_rdt: Prepare for RDT monitoring mkdir support

Separate the ctrl mkdir code from the rest in order to prepare for adding support for RDT monitoring mkdir support as well.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 111 ++++++++++++++++++++++---------
 1 file changed, 79 insertions(+), 32 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +79 -32
index 14489a5..b3c901a 100644
@@ -1082,46 +1082,35 @@ static struct file_system_type rdt_fs_type = {
 	.kill_sb = rdt_kill_sb,
 };
 
-static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
-			  umode_t mode)
+static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
+			     struct kernfs_node *prgrp_kn,
+			     const char *name, umode_t mode,
+			     struct rdtgroup **r)
 {
-	struct rdtgroup *parent, *rdtgrp;
+	struct rdtgroup *prdtgrp, *rdtgrp;
 	struct kernfs_node *kn;
-	int ret, closid;
-
-	/* Only allow mkdir in the root directory */
-	if (parent_kn != rdtgroup_default.kn)
-		return -EPERM;
-
-	/* Do not accept '\n' to avoid unparsable situation. */
-	if (strchr(name, '\n'))
-		return -EINVAL;
+	uint files = 0;
+	int ret;
 
-	parent = rdtgroup_kn_lock_live(parent_kn);
-	if (!parent) {
+	prdtgrp = rdtgroup_kn_lock_live(prgrp_kn);
+	if (!prdtgrp) {
 		ret = -ENODEV;
 		goto out_unlock;
 	}
 
-	ret = closid_alloc();
-	if (ret < 0)
-		goto out_unlock;
-	closid = ret;
-
 	/* allocate the rdtgroup. */
 	rdtgrp = kzalloc(sizeof(*rdtgrp), GFP_KERNEL);
 	if (!rdtgrp) {
 		ret = -ENOSPC;
-		goto out_closid_free;
+		goto out_unlock;
 	}
-	rdtgrp->closid = closid;
-	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+	*r = rdtgrp;
 
 	/* kernfs creates the directory for rdtgrp */
-	kn = kernfs_create_dir(parent->kn, name, mode, rdtgrp);
+	kn = kernfs_create_dir(parent_kn, name, mode, rdtgrp);
 	if (IS_ERR(kn)) {
 		ret = PTR_ERR(kn);
-		goto out_cancel_ref;
+		goto out_free_rgrp;
 	}
 	rdtgrp->kn = kn;
 
@@ -1137,27 +1126,85 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	if (ret)
 		goto out_destroy;
 
-	ret = rdtgroup_add_files(kn, RF_CTRL_BASE);
+	files = RFTYPE_BASE | RFTYPE_CTRL;
+	ret = rdtgroup_add_files(kn, files);
 	if (ret)
 		goto out_destroy;
 
 	kernfs_activate(kn);
 
-	ret = 0;
-	goto out_unlock;
+	/*
+	 * The caller unlocks the prgrp_kn upon success.
+	 */
+	return 0;
 
 out_destroy:
 	kernfs_remove(rdtgrp->kn);
-out_cancel_ref:
-	list_del(&rdtgrp->rdtgroup_list);
+out_free_rgrp:
 	kfree(rdtgrp);
-out_closid_free:
-	closid_free(closid);
 out_unlock:
-	rdtgroup_kn_unlock(parent_kn);
+	rdtgroup_kn_unlock(prgrp_kn);
+	return ret;
+}
+
+static void mkdir_rdt_prepare_clean(struct rdtgroup *rgrp)
+{
+	kernfs_remove(rgrp->kn);
+	kfree(rgrp);
+}
+
+/*
+ * These are rdtgroups created under the root directory. Can be used
+ * to allocate resources.
+ */
+static int rdtgroup_mkdir_ctrl(struct kernfs_node *parent_kn,
+			       struct kernfs_node *prgrp_kn,
+			       const char *name, umode_t mode)
+{
+	struct rdtgroup *rdtgrp;
+	struct kernfs_node *kn;
+	u32 closid;
+	int ret;
+
+	ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, &rdtgrp);
+	if (ret)
+		return ret;
+
+	kn = rdtgrp->kn;
+	ret = closid_alloc();
+	if (ret < 0)
+		goto out_common_fail;
+	closid = ret;
+
+	rdtgrp->closid = closid;
+	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+
+	goto out_unlock;
+
+out_common_fail:
+	mkdir_rdt_prepare_clean(rdtgrp);
+out_unlock:
+	rdtgroup_kn_unlock(prgrp_kn);
 	return ret;
 }
 
+static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
+			  umode_t mode)
+{
+	/* Do not accept '\n' to avoid unparsable situation. */
+	if (strchr(name, '\n'))
+		return -EINVAL;
+
+	/*
+	 * If the parent directory is the root directory and RDT
+	 * allocation is supported, add a control rdtgroup.
+	 */
+	if (rdt_alloc_capable && parent_kn == rdtgroup_default.kn)
+		return rdtgroup_mkdir_ctrl(parent_kn, parent_kn, name, mode);
+
+	return -EPERM;
+}
+
 static int rdtgroup_rmdir(struct kernfs_node *kn)
 {
 	int ret, cpu, closid = rdtgroup_default.closid;
#29 lore raw

PATCH v2 13/28 x86/intel_rdt/cqm: Add mkdir support for RDT monitoring

In reply to Vikas Shivappa

Resource control groups can be created using mkdir in resctrl fs(rdtgroup). In order to extend the resctrl interface to support monitoring the control groups, extend the current mkdir to support resource monitoring also.

This allows the rdtgroup created under the root directory to be able to both control and monitor resources (ctrl_mon group). The ctrl_mon groups are associated with one CLOSID like the legacy rdtgroups and one RMID(Resource monitoring ID) as well. Hardware uses RMID to track the resource usage. Once either of the CLOSID or RMID are exhausted, the mkdir fails with -ENOSPC. If there are RMIDs in limbo list but not free an -EBUSY is returned. User can also monitor a subset of the ctrl_mon rdtgroup's tasks/cpus using the monitor groups. The monitor groups are created using mkdir under the "mon_groups" directory in every ctrl_mon group.

[Merged tony's code:
Removed a lot of common mkdir code, a fix to handling of the list of the child rdtgroups and some cleanups in list traversal. Also the changes to have similar alloc and free for CLOS/RMID and return -EBUSY when RMIDs are in limbo and not free]

---
 arch/x86/kernel/cpu/intel_rdt.h          |  26 ++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 134 +++++++++++++++++++++++++++++--
 2 files changed, 152 insertions(+), 8 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +26 -0
index 4051f5e..e8fb08f 100644
@@ -37,6 +37,25 @@ struct mon_evt {
 extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
+
+enum rdt_group_type {
+	RDTCTRL_GROUP = 0,
+	RDTMON_GROUP,
+	RDT_NUM_GROUP,
+};
+
+/**
+ * struct mongroup - store mon group's data in resctrl fs.
+ * @parent:			parent rdtgrp
+ * @crdtgrp_list:		child rdtgroup node list
+ * @rmid:			rmid for this rdtgroup
+ */
+struct mongroup {
+	struct rdtgroup		*parent;
+	struct list_head	crdtgrp_list;
+	u32			rmid;
+};
+
 /**
  * struct rdtgroup - store rdtgroup's data in resctrl file system.
  * @kn:				kernfs node
@@ -46,6 +65,9 @@ struct mon_evt {
  * @flags:			status bits
  * @waitcount:			how many cpus expect to find this
  *				group when they acquire rdtgroup_mutex
+ * @type:			indicates type of this rdtgroup - either
+ *				monitor only or ctrl_mon group
+ * @mon:			mongroup related data
  */
 struct rdtgroup {
 	struct kernfs_node	*kn;
@@ -54,6 +76,8 @@ struct rdtgroup {
 	struct cpumask		cpu_mask;
 	int			flags;
 	atomic_t		waitcount;
+	enum rdt_group_type	type;
+	struct mongroup		mon;
 };
 
 /* rdtgroup.flags */
@@ -306,6 +330,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			   struct seq_file *s, void *v);
 struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
+int alloc_rmid(void);
+void free_rmid(u32 rmid);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +126 -8

210 lines not on this page · raw message

Signature · 1 line
1.9.1
#30 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add mkdir support for RDT monitoring

x86/intel_rdt/cqm: Add mkdir support for RDT monitoring
Commit-ID:  c7d9aac6131148abe29ed1dc6bd73ad1213d1f56
Gitweb:     http://git.kernel.org/tip/c7d9aac6131148abe29ed1dc6bd73ad1213d1f56
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:32 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:23 +0200

x86/intel_rdt/cqm: Add mkdir support for RDT monitoring

Resource control groups can be created using mkdir in resctrl fs(rdtgroup). In order to extend the resctrl interface to support monitoring the control groups, extend the current mkdir to support resource monitoring also.

This allows the rdtgroup created under the root directory to be able to both control and monitor resources (ctrl_mon group). The ctrl_mon groups are associated with one CLOSID like the legacy rdtgroups and one RMID(Resource monitoring ID) as well. Hardware uses RMID to track the resource usage. Once either of the CLOSID or RMID are exhausted, the mkdir fails with -ENOSPC. If there are RMIDs in limbo list but not free an -EBUSY is returned. User can also monitor a subset of the ctrl_mon rdtgroup's tasks/cpus using the monitor groups. The monitor groups are created using mkdir under the "mon_groups" directory in every ctrl_mon group.

[Merged Tony's code: Removed a lot of common mkdir code, a fix to handling of the list of the child rdtgroups and some cleanups in list traversal. Also the changes to have similar alloc and free for CLOS/RMID and return -EBUSY when RMIDs are in limbo and not free]

---
 arch/x86/kernel/cpu/intel_rdt.h          |  26 ++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 133 +++++++++++++++++++++++++++++--
 2 files changed, 151 insertions(+), 8 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +26 -0
index 4051f5e..e8fb08f 100644
@@ -37,6 +37,25 @@ extern unsigned int intel_cqm_threshold;
 extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
+
+enum rdt_group_type {
+	RDTCTRL_GROUP = 0,
+	RDTMON_GROUP,
+	RDT_NUM_GROUP,
+};
+
+/**
+ * struct mongroup - store mon group's data in resctrl fs.
+ * @parent:			parent rdtgrp
+ * @crdtgrp_list:		child rdtgroup node list
+ * @rmid:			rmid for this rdtgroup
+ */
+struct mongroup {
+	struct rdtgroup		*parent;
+	struct list_head	crdtgrp_list;
+	u32			rmid;
+};
+
 /**
  * struct rdtgroup - store rdtgroup's data in resctrl file system.
  * @kn:				kernfs node
@@ -46,6 +65,9 @@ extern unsigned int rdt_mon_features;
  * @flags:			status bits
  * @waitcount:			how many cpus expect to find this
  *				group when they acquire rdtgroup_mutex
+ * @type:			indicates type of this rdtgroup - either
+ *				monitor only or ctrl_mon group
+ * @mon:			mongroup related data
  */
 struct rdtgroup {
 	struct kernfs_node	*kn;
@@ -54,6 +76,8 @@ struct rdtgroup {
 	struct cpumask		cpu_mask;
 	int			flags;
 	atomic_t		waitcount;
+	enum rdt_group_type	type;
+	struct mongroup		mon;
 };
 
 /* rdtgroup.flags */
@@ -306,6 +330,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			   struct seq_file *s, void *v);
 struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
+int alloc_rmid(void);
+void free_rmid(u32 rmid);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +125 -8

207 lines not on this page · raw message

#31 lore raw

PATCH v2 14/28 x86/intel_rdt: Change closid type from int to u32

In reply to Vikas Shivappa

OS associates a CLOSid(Class of service id) to a task by writing the high 32 bits of per CPU IA32_PQR_ASSOC MSR when a task is scheduled in. CPUID.(EAX=10H, ECX=1):EDX[15:0] enumerates the max CLOSID supported and it is zero indexed. Hence change the type to u32 from int.

---
 arch/x86/include/asm/intel_rdt_sched.h   | 2 +-
 arch/x86/kernel/cpu/intel_rdt.h          | 2 +-
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +-
 include/linux/sched.h                    | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +1 -1
index 4dee77b..1d8d45a 100644
@@ -46,7 +46,7 @@ static inline void intel_rdt_sched_in(void)
 {
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-		int closid;
+		u32 closid;
 
 		/*
 		 * If this task has a closid assigned, use it.
arch/x86/kernel/cpu/intel_rdt.h +1 -1
index e8fb08f..b2a2de3 100644
@@ -72,7 +72,7 @@ struct mongroup {
 struct rdtgroup {
 	struct kernfs_node	*kn;
 	struct list_head	rdtgroup_list;
-	int			closid;
+	u32			closid;
 	struct cpumask		cpu_mask;
 	int			flags;
 	atomic_t		waitcount;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +1 -1
index cfb2a89..843a131 100644
@@ -77,7 +77,7 @@ static void closid_init(void)
 
 static int closid_alloc(void)
 {
-	int closid = ffs(closid_free_map);
+	u32 closid = ffs(closid_free_map);
 
 	if (closid == 0)
 		return -ENOSPC;
include/linux/sched.h +1 -1
index 9e31b3d..b8d0d5c 100644
@@ -865,7 +865,7 @@ struct task_struct {
 	struct list_head		cg_list;
 #endif
 #ifdef CONFIG_INTEL_RDT
-	int				closid;
+	u32				closid;
 #endif
 #ifdef CONFIG_FUTEX
 	struct robust_list_head __user	*robust_list;
Signature · 1 line
1.9.1
#32 lore raw

[tip:x86/cache] x86/intel_rdt: Change closid type from int to u32

x86/intel_rdt: Change closid type from int to u32
Commit-ID:  0734ded1abee9439b0c5d7b62af1ead78aab895b
Gitweb:     http://git.kernel.org/tip/0734ded1abee9439b0c5d7b62af1ead78aab895b
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:33 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:24 +0200

x86/intel_rdt: Change closid type from int to u32

OS associates a CLOSid(Class of service id) to a task by writing the high 32 bits of per CPU IA32_PQR_ASSOC MSR when a task is scheduled in. CPUID.(EAX=10H, ECX=1):EDX[15:0] enumerates the max CLOSID supported and it is zero indexed. Hence change the type to u32 from int.

---
 arch/x86/include/asm/intel_rdt_sched.h   | 2 +-
 arch/x86/kernel/cpu/intel_rdt.h          | 2 +-
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +-
 include/linux/sched.h                    | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +1 -1
index 4dee77b..1d8d45a 100644
@@ -46,7 +46,7 @@ static inline void intel_rdt_sched_in(void)
 {
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-		int closid;
+		u32 closid;
 
 		/*
 		 * If this task has a closid assigned, use it.
arch/x86/kernel/cpu/intel_rdt.h +1 -1
index e8fb08f..b2a2de3 100644
@@ -72,7 +72,7 @@ struct mongroup {
 struct rdtgroup {
 	struct kernfs_node	*kn;
 	struct list_head	rdtgroup_list;
-	int			closid;
+	u32			closid;
 	struct cpumask		cpu_mask;
 	int			flags;
 	atomic_t		waitcount;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +1 -1
index bee9f88..8404054 100644
@@ -77,7 +77,7 @@ static void closid_init(void)
 
 static int closid_alloc(void)
 {
-	int closid = ffs(closid_free_map);
+	u32 closid = ffs(closid_free_map);
 
 	if (closid == 0)
 		return -ENOSPC;
include/linux/sched.h +1 -1
index 20b2ff2..8839fd0 100644
@@ -899,7 +899,7 @@ struct task_struct {
 	struct list_head		cg_list;
 #endif
 #ifdef CONFIG_INTEL_RDT
-	int				closid;
+	u32				closid;
 #endif
 #ifdef CONFIG_FUTEX
 	struct robust_list_head __user	*robust_list;
#33 lore raw

PATCH v2 15/28 x86/intel_rdt/cqm: Add tasks file support

In reply to Vikas Shivappa

The root directory, ctrl_mon and monitor groups are populated with a read/write file named "tasks". When read, it shows all the task IDs assigned to the resource group.

Tasks can be added to groups by writing the PID to the file. A task can be present in one "ctrl_mon" group "and" one "monitor" group. IOW a PID_x can be seen in a ctrl_mon group and a monitor group at the same time. When a task is added to a ctrl_mon group, it is automatically removed from the previous ctrl_mon group where it belonged. Similarly if a task is moved to a monitor group it is removed from the previous monitor group . Also since the monitor groups can only have subset of tasks of parent ctrl_mon group, a task can be moved to a monitor group only if its already present in the parent ctrl_mon group.

Task membership is indicated by a new field in the task_struct "u32 rmid" which holds the RMID for the task. RMID=0 is reserved for the default root group where the tasks belong to at mount.

[tony: zero the rmid if rdtgroup was deleted when task was being moved]

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 19 +++++++++++++++++--
 include/linux/sched.h                    |  1 +
 2 files changed, 18 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +17 -2
index 843a131..d02596e9 100644
@@ -314,6 +314,7 @@ static void move_myself(struct callback_head *head)
 	if (atomic_dec_and_test(&rdtgrp->waitcount) &&
 	    (rdtgrp->flags & RDT_DELETED)) {
 		current->closid = 0;
+		current->rmid = 0;
 		kfree(rdtgrp);
 	}
 
@@ -352,7 +353,20 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
 		atomic_dec(&rdtgrp->waitcount);
 		kfree(callback);
 	} else {
-		tsk->closid = rdtgrp->closid;
+		/*
+		 * For ctrl_mon groups move both closid and rmid.
+		 * For monitor groups, can move the tasks only from
+		 * their parent CTRL group.
+		 */
+		if (rdtgrp->type == RDTCTRL_GROUP) {
+			tsk->closid = rdtgrp->closid;
+			tsk->rmid = rdtgrp->mon.rmid;
+		} else if (rdtgrp->type == RDTMON_GROUP) {
+			if (rdtgrp->mon.parent->closid == tsk->closid)
+				tsk->rmid = rdtgrp->mon.rmid;
+			else
+				ret = -EINVAL;
+		}
 	}
 	return ret;
 }
@@ -432,7 +446,8 @@ static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
 
 	rcu_read_lock();
 	for_each_process_thread(p, t) {
-		if (t->closid == r->closid)
+		if ((r->type == RDTCTRL_GROUP && t->closid == r->closid) ||
+		    (r->type == RDTMON_GROUP && t->rmid == r->mon.rmid))
 			seq_printf(s, "%d\n", t->pid);
 	}
 	rcu_read_unlock();
include/linux/sched.h +1 -0
index b8d0d5c..cc47923 100644
@@ -866,6 +866,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_INTEL_RDT
 	u32				closid;
+	u32				rmid;
 #endif
 #ifdef CONFIG_FUTEX
 	struct robust_list_head __user	*robust_list;
Signature · 1 line
1.9.1
#34 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add tasks file support

x86/intel_rdt/cqm: Add tasks file support
Commit-ID:  d6aaba615a482ce7d3ec218cf7b8d02d0d5753b8
Gitweb:     http://git.kernel.org/tip/d6aaba615a482ce7d3ec218cf7b8d02d0d5753b8
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:34 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:24 +0200

x86/intel_rdt/cqm: Add tasks file support

The root directory, ctrl_mon and monitor groups are populated with a read/write file named "tasks". When read, it shows all the task IDs assigned to the resource group.

Tasks can be added to groups by writing the PID to the file. A task can be present in one "ctrl_mon" group "and" one "monitor" group. IOW a PID_x can be seen in a ctrl_mon group and a monitor group at the same time. When a task is added to a ctrl_mon group, it is automatically removed from the previous ctrl_mon group where it belonged. Similarly if a task is moved to a monitor group it is removed from the previous monitor group . Also since the monitor groups can only have subset of tasks of parent ctrl_mon group, a task can be moved to a monitor group only if its already present in the parent ctrl_mon group.

Task membership is indicated by a new field in the task_struct "u32 rmid" which holds the RMID for the task. RMID=0 is reserved for the default root group where the tasks belong to at mount.

[tony: zero the rmid if rdtgroup was deleted when task was being moved]

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 19 +++++++++++++++++--
 include/linux/sched.h                    |  1 +
 2 files changed, 18 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +17 -2
index 8404054..aedad1d 100644
@@ -314,6 +314,7 @@ static void move_myself(struct callback_head *head)
 	if (atomic_dec_and_test(&rdtgrp->waitcount) &&
 	    (rdtgrp->flags & RDT_DELETED)) {
 		current->closid = 0;
+		current->rmid = 0;
 		kfree(rdtgrp);
 	}
 
@@ -352,7 +353,20 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
 		atomic_dec(&rdtgrp->waitcount);
 		kfree(callback);
 	} else {
-		tsk->closid = rdtgrp->closid;
+		/*
+		 * For ctrl_mon groups move both closid and rmid.
+		 * For monitor groups, can move the tasks only from
+		 * their parent CTRL group.
+		 */
+		if (rdtgrp->type == RDTCTRL_GROUP) {
+			tsk->closid = rdtgrp->closid;
+			tsk->rmid = rdtgrp->mon.rmid;
+		} else if (rdtgrp->type == RDTMON_GROUP) {
+			if (rdtgrp->mon.parent->closid == tsk->closid)
+				tsk->rmid = rdtgrp->mon.rmid;
+			else
+				ret = -EINVAL;
+		}
 	}
 	return ret;
 }
@@ -432,7 +446,8 @@ static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
 
 	rcu_read_lock();
 	for_each_process_thread(p, t) {
-		if (t->closid == r->closid)
+		if ((r->type == RDTCTRL_GROUP && t->closid == r->closid) ||
+		    (r->type == RDTMON_GROUP && t->rmid == r->mon.rmid))
 			seq_printf(s, "%d\n", t->pid);
 	}
 	rcu_read_unlock();
include/linux/sched.h +1 -0
index 8839fd0..067a41a 100644
@@ -900,6 +900,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_INTEL_RDT
 	u32				closid;
+	u32				rmid;
 #endif
 #ifdef CONFIG_FUTEX
 	struct robust_list_head __user	*robust_list;
#35 lore raw

PATCH v2 16/28 x86/intel_rdt: Prepare to add RDT monitor cpus file support

In reply to Vikas Shivappa

Separate the ctrl cpus file handling from the generic cpus file handling and convert the per cpu closid from u32 to a struct which will be used later to add rmid to the same struct. Also cleanup some name space.

---
 arch/x86/include/asm/intel_rdt_sched.h   |   4 +-
 arch/x86/kernel/cpu/intel_rdt.c          |   6 +-
 arch/x86/kernel/cpu/intel_rdt.h          |   2 -
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 103 +++++++++++++++++--------------
 4 files changed, 62 insertions(+), 53 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +2 -2
index 1d8d45a..2c704d2 100644
@@ -26,7 +26,7 @@ struct intel_pqr_state {
 };
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
-DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+DECLARE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
@@ -54,7 +54,7 @@ static inline void intel_rdt_sched_in(void)
 		 */
 		closid = current->closid;
 		if (closid == 0)
-			closid = this_cpu_read(cpu_closid);
+			closid = this_cpu_read(rdt_cpu_default.closid);
 
 		if (closid != state->closid) {
 			state->closid = closid;
arch/x86/kernel/cpu/intel_rdt.c +3 -3
index eab2467..cd48ec9 100644
@@ -39,8 +39,6 @@
 /* Mutex to protect rdtgroup access. */
 DEFINE_MUTEX(rdtgroup_mutex);
 
-DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-
 /*
  * The cached intel_pqr_state is strictly per CPU and can never be
  * updated from a remote CPU. Functions which modify the state
@@ -49,6 +47,8 @@
  */
 DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
 
+DEFINE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
+
 /*
  * Used to store the max resource name width and max resource data width
  * to display the schemata in a tabular format
@@ -500,7 +500,7 @@ static void clear_closid(int cpu)
 {
 	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 
-	per_cpu(cpu_closid, cpu) = 0;
+	per_cpu(rdt_cpu_default.closid, cpu) = 0;
 	state->closid = 0;
 	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
 }
arch/x86/kernel/cpu/intel_rdt.h +0 -2
index b2a2de3..6f07047 100644
@@ -320,8 +320,6 @@ enum {
 	unsigned int full;
 };
 
-DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-
 void rdt_ctrl_update(void *arg);
 struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
 void rdtgroup_kn_unlock(struct kernfs_node *kn);
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +57 -46

154 lines not on this page · raw message

Signature · 1 line
1.9.1
#36 lore raw

Re: [PATCH 16/28] x86/intel_rdt: Prepare to add RDT monitor cpus file support

arch/x86/kernel/cpu/intel_rdt.c line 50

Quoted 8 lines · Vikas Shivappa

/*
* The cached intel_pqr_state is strictly per CPU and can never be
* updated from a remote CPU. Functions which modify the state

arch/x86/kernel/cpu/intel_rdt.c +1 -0
@@ -49,6 +47,8 @@
  */
 DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
 
+DEFINE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);

Cacheline wise this is suboptimal. You have to touch two cachelines on each context switch (at least for read).

If you make that:

struct intel_pqr_state {
	u32		default_cosid;
	u32		default_rmid;
	u32		cur_cosid;
	u32		cur_rmid;
};

DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);

then it's all together and you spare one cache line.

Thanks,

tglx

#37 lore raw

Re: [PATCH 16/28] x86/intel_rdt: Prepare to add RDT monitor cpus file support

Quoted 22 lines · Thomas Gleixner

arch/x86/kernel/cpu/intel_rdt.c line 50

Quoted 8 lines · Vikas Shivappa

/*
* The cached intel_pqr_state is strictly per CPU and can never be
* updated from a remote CPU. Functions which modify the state

arch/x86/kernel/cpu/intel_rdt.c +1 -0
@@ -49,6 +47,8 @@
  */
 DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
 
+DEFINE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);

Cacheline wise this is suboptimal. You have to touch two cachelines on each context switch (at least for read).

If you make that:

struct intel_pqr_state {
	u32		default_cosid;
	u32		default_rmid;
	u32		cur_cosid;
	u32		cur_rmid;
};
Quoted 3 lines

DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);

then it's all together and you spare one cache line.

Will fix..

Thanks,
Vikas

Quoted 5 lines

Thanks,

tglx

#38 lore raw

[tip:x86/cache] x86/intel_rdt: Prepare to add RDT monitor cpus file support

In reply to Vikas Shivappa
x86/intel_rdt: Prepare to add RDT monitor cpus file support
Commit-ID:  b09d981b3f346690dafa3e4ebedfcf3e44b68e83
Gitweb:     http://git.kernel.org/tip/b09d981b3f346690dafa3e4ebedfcf3e44b68e83
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:35 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:25 +0200

x86/intel_rdt: Prepare to add RDT monitor cpus file support

Separate the ctrl cpus file handling from the generic cpus file handling and convert the per cpu closid from u32 to a struct which will be used later to add rmid to the same struct. Also cleanup some name space.

---
 arch/x86/include/asm/intel_rdt_sched.h   |   4 +-
 arch/x86/kernel/cpu/intel_rdt.c          |   6 +-
 arch/x86/kernel/cpu/intel_rdt.h          |   2 -
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 103 +++++++++++++++++--------------
 4 files changed, 62 insertions(+), 53 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +2 -2
index 1d8d45a..2c704d2 100644
@@ -26,7 +26,7 @@ struct intel_pqr_state {
 };
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
-DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+DECLARE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
@@ -54,7 +54,7 @@ static inline void intel_rdt_sched_in(void)
 		 */
 		closid = current->closid;
 		if (closid == 0)
-			closid = this_cpu_read(cpu_closid);
+			closid = this_cpu_read(rdt_cpu_default.closid);
 
 		if (closid != state->closid) {
 			state->closid = closid;
arch/x86/kernel/cpu/intel_rdt.c +3 -3
index 7cae4ec..303b085 100644
@@ -39,8 +39,6 @@
 /* Mutex to protect rdtgroup access. */
 DEFINE_MUTEX(rdtgroup_mutex);
 
-DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-
 /*
  * The cached intel_pqr_state is strictly per CPU and can never be
  * updated from a remote CPU. Functions which modify the state
@@ -49,6 +47,8 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
  */
 DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
 
+DEFINE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
+
 /*
  * Used to store the max resource name width and max resource data width
  * to display the schemata in a tabular format
@@ -500,7 +500,7 @@ static void clear_closid(int cpu)
 {
 	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 
-	per_cpu(cpu_closid, cpu) = 0;
+	per_cpu(rdt_cpu_default.closid, cpu) = 0;
 	state->closid = 0;
 	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
 }
arch/x86/kernel/cpu/intel_rdt.h +0 -2
index b2a2de3..6f07047 100644
@@ -320,8 +320,6 @@ union cpuid_0x10_x_edx {
 	unsigned int full;
 };
 
-DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
-
 void rdt_ctrl_update(void *arg);
 struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
 void rdtgroup_kn_unlock(struct kernfs_node *kn);
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +57 -46

154 lines not on this page · raw message

#39 lore raw

PATCH v2 17/28 x86/intel_rdt/cqm: Add cpus file support

In reply to Vikas Shivappa

The cpus file is extended to support resource monitoring. This is used to over-ride the RMID of the default group when running on specific CPUs. It works similar to the resource control. The "cpus" and "cpus_list" file is present in default group, ctrl_mon groups and monitor groups.

Each "cpus" file or cpu_list file reads a cpumask or list showing which CPUs belong to the resource group. By default all online cpus belong to the default root group. A CPU can be present in one "ctrl_mon" and one "monitor" group simultaneously. They can be added to a resource group by writing the CPU to the file. When a CPU is added to a ctrl_mon group it is automatically removed from the previous ctrl_mon group. A CPU can be added to a monitor group only if it is present in the parent ctrl_mon group and when a CPU is added to a monitor group, it is automatically removed from the previous monitor group. When CPUs go offline, they are automatically removed from the ctrl_mon and monitor groups.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 110 ++++++++++++++++++++++++++-----
 1 file changed, 93 insertions(+), 17 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +93 -17
index 7f8f52d..abc06ea 100644
@@ -181,15 +181,17 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
 /*
  * This is safe against intel_rdt_sched_in() called from __switch_to()
  * because __switch_to() is executed with interrupts disabled. A local call
- * from update_closid() is proteced against __switch_to() because
+ * from update_closid_rmid() is proteced against __switch_to() because
  * preemption is disabled.
  */
-static void update_cpu_closid(void *info)
+static void update_cpu_closid_rmid(void *info)
 {
 	struct rdtgroup *r = info;
 
-	if (r)
+	if (r) {
 		this_cpu_write(rdt_cpu_default.closid, r->closid);
+		this_cpu_write(rdt_cpu_default.rmid, r->mon.rmid);
+	}
 
 	/*
 	 * We cannot unconditionally write the MSR because the current
@@ -205,20 +207,72 @@ static void update_cpu_closid(void *info)
  * Per task closids/rmids must have been set up before calling this function.
  */
 static void
-update_closid(const struct cpumask *cpu_mask, struct rdtgroup *r)
+update_closid_rmid(const struct cpumask *cpu_mask, struct rdtgroup *r)
 {
 	int cpu = get_cpu();
 
 	if (cpumask_test_cpu(cpu, cpu_mask))
-		update_cpu_closid(r);
-	smp_call_function_many(cpu_mask, update_cpu_closid, r, 1);
+		update_cpu_closid_rmid(r);
+	smp_call_function_many(cpu_mask, update_cpu_closid_rmid, r, 1);
 	put_cpu();
 }
 
+static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
+			  cpumask_var_t tmpmask)
+{
+	struct rdtgroup *prgrp = rdtgrp->mon.parent, *crgrp;
+	struct list_head *head;
+
+	/* Check whether cpus belong to parent ctrl group */
+	cpumask_andnot(tmpmask, newmask, &prgrp->cpu_mask);
+	if (cpumask_weight(tmpmask))
+		return -EINVAL;
+
+	/* Check whether cpus are dropped from this group */
+	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
+	if (cpumask_weight(tmpmask)) {
+		/* Give any dropped cpus to parent rdtgroup */
+		cpumask_or(&prgrp->cpu_mask, &prgrp->cpu_mask, tmpmask);
+		update_closid_rmid(tmpmask, prgrp);
+	}
+
+	/*
+	 * If we added cpus, remove them from previous group that owned them
+	 * and update per-cpu rmid
+	 */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
+	if (cpumask_weight(tmpmask)) {
+		head = &prgrp->mon.crdtgrp_list;
+		list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
+			if (crgrp == rdtgrp)
+				continue;
+			cpumask_andnot(&crgrp->cpu_mask, &crgrp->cpu_mask,
+				       tmpmask);
+		}
+		update_closid_rmid(tmpmask, rdtgrp);
+	}
+
+	/* Done pushing/pulling - update this group with new mask */
+	cpumask_copy(&rdtgrp->cpu_mask, newmask);
+
+	return 0;
+}
+
+static void cpumask_rdtgrp_clear(struct rdtgroup *r, struct cpumask *m)
+{
+	struct rdtgroup *crgrp;
+
+	cpumask_andnot(&r->cpu_mask, &r->cpu_mask, m);
+	/* update the child mon group masks as well*/
+	list_for_each_entry(crgrp, &r->mon.crdtgrp_list, mon.crdtgrp_list)
+		cpumask_and(&crgrp->cpu_mask, &r->cpu_mask, &crgrp->cpu_mask);
+}
+
 static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
-			   cpumask_var_t tmpmask)
+			   cpumask_var_t tmpmask, cpumask_var_t tmpmask1)
 {
-	struct rdtgroup *r;
+	struct rdtgroup *r, *crgrp;
+	struct list_head *head;
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
@@ -230,33 +284,47 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 		/* Give any dropped cpus to rdtgroup_default */
 		cpumask_or(&rdtgroup_default.cpu_mask,
 			   &rdtgroup_default.cpu_mask, tmpmask);
-		update_closid(tmpmask, &rdtgroup_default);
+		update_closid_rmid(tmpmask, &rdtgroup_default);
 	}
 
 	/*
-	 * If we added cpus, remove them from previous group that owned them
-	 * and update per-cpu closid
+	 * If we added cpus, remove them from previous group and
+	 * the prev group's child groups that owned them
+	 * and update per-cpu closid/rmid.
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
 	if (cpumask_weight(tmpmask)) {
 		list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
 			if (r == rdtgrp)
 				continue;
-			cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask);
+			cpumask_and(tmpmask1, &r->cpu_mask, tmpmask);
+			if (cpumask_weight(tmpmask1))
+				cpumask_rdtgrp_clear(r, tmpmask1);
 		}
-		update_closid(tmpmask, rdtgrp);
+		update_closid_rmid(tmpmask, rdtgrp);
 	}
 
 	/* Done pushing/pulling - update this group with new mask */
 	cpumask_copy(&rdtgrp->cpu_mask, newmask);
 
+	/*
+	 * Clear child mon group masks since there is a new parent mask
+	 * now and update the rmid for the cpus the child lost.
+	 */
+	head = &rdtgrp->mon.crdtgrp_list;
+	list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
+		cpumask_and(tmpmask, &rdtgrp->cpu_mask, &crgrp->cpu_mask);
+		update_closid_rmid(tmpmask, rdtgrp);
+		cpumask_clear(&crgrp->cpu_mask);
+	}
+
 	return 0;
 }
 
 static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 				   char *buf, size_t nbytes, loff_t off)
 {
-	cpumask_var_t tmpmask, newmask;
+	cpumask_var_t tmpmask, newmask, tmpmask1;
 	struct rdtgroup *rdtgrp;
 	int ret;
 
@@ -269,6 +337,11 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 		free_cpumask_var(tmpmask);
 		return -ENOMEM;
 	}
+	if (!zalloc_cpumask_var(&tmpmask1, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		free_cpumask_var(newmask);
+		return -ENOMEM;
+	}
 
 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
 	if (!rdtgrp) {
@@ -292,7 +365,9 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 	}
 
 	if (rdtgrp->type == RDTCTRL_GROUP)
-		ret = cpus_ctrl_write(rdtgrp, newmask, tmpmask);
+		ret = cpus_ctrl_write(rdtgrp, newmask, tmpmask, tmpmask1);
+	else if (rdtgrp->type == RDTMON_GROUP)
+		ret = cpus_mon_write(rdtgrp, newmask, tmpmask);
 	else
 		ret = -EINVAL;
 
@@ -300,6 +375,7 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 	rdtgroup_kn_unlock(of->kn);
 	free_cpumask_var(tmpmask);
 	free_cpumask_var(newmask);
+	free_cpumask_var(tmpmask1);
 
 	return ret ?: nbytes;
 }
@@ -1114,7 +1190,7 @@ static void rmdir_all_sub(void)
 	}
 	/* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
 	get_online_cpus();
-	update_closid(cpu_online_mask, &rdtgroup_default);
+	update_closid_rmid(cpu_online_mask, &rdtgroup_default);
 	put_online_cpus();
 
 	kernfs_remove(kn_info);
@@ -1377,7 +1453,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 	 * task running on them.
 	 */
 	cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
-	update_closid(tmpmask, NULL);
+	update_closid_rmid(tmpmask, NULL);
 
 	rdtgrp->flags = RDT_DELETED;
 	closid_free(rdtgrp->closid);
Signature · 1 line
1.9.1
#40 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add cpus file support

x86/intel_rdt/cqm: Add cpus file support
Commit-ID:  a9fcf8627dc01049c390023bbb0323db3c785b91
Gitweb:     http://git.kernel.org/tip/a9fcf8627dc01049c390023bbb0323db3c785b91
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:36 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:25 +0200

x86/intel_rdt/cqm: Add cpus file support

The cpus file is extended to support resource monitoring. This is used to over-ride the RMID of the default group when running on specific CPUs. It works similar to the resource control. The "cpus" and "cpus_list" file is present in default group, ctrl_mon groups and monitor groups.

Each "cpus" file or cpu_list file reads a cpumask or list showing which CPUs belong to the resource group. By default all online cpus belong to the default root group. A CPU can be present in one "ctrl_mon" and one "monitor" group simultaneously. They can be added to a resource group by writing the CPU to the file. When a CPU is added to a ctrl_mon group it is automatically removed from the previous ctrl_mon group. A CPU can be added to a monitor group only if it is present in the parent ctrl_mon group and when a CPU is added to a monitor group, it is automatically removed from the previous monitor group. When CPUs go offline, they are automatically removed from the ctrl_mon and monitor groups.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 110 ++++++++++++++++++++++++++-----
 1 file changed, 93 insertions(+), 17 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +93 -17
index d11f462..89457bb 100644
@@ -181,15 +181,17 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
 /*
  * This is safe against intel_rdt_sched_in() called from __switch_to()
  * because __switch_to() is executed with interrupts disabled. A local call
- * from update_closid() is proteced against __switch_to() because
+ * from update_closid_rmid() is proteced against __switch_to() because
  * preemption is disabled.
  */
-static void update_cpu_closid(void *info)
+static void update_cpu_closid_rmid(void *info)
 {
 	struct rdtgroup *r = info;
 
-	if (r)
+	if (r) {
 		this_cpu_write(rdt_cpu_default.closid, r->closid);
+		this_cpu_write(rdt_cpu_default.rmid, r->mon.rmid);
+	}
 
 	/*
 	 * We cannot unconditionally write the MSR because the current
@@ -205,20 +207,72 @@ static void update_cpu_closid(void *info)
  * Per task closids/rmids must have been set up before calling this function.
  */
 static void
-update_closid(const struct cpumask *cpu_mask, struct rdtgroup *r)
+update_closid_rmid(const struct cpumask *cpu_mask, struct rdtgroup *r)
 {
 	int cpu = get_cpu();
 
 	if (cpumask_test_cpu(cpu, cpu_mask))
-		update_cpu_closid(r);
-	smp_call_function_many(cpu_mask, update_cpu_closid, r, 1);
+		update_cpu_closid_rmid(r);
+	smp_call_function_many(cpu_mask, update_cpu_closid_rmid, r, 1);
 	put_cpu();
 }
 
+static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
+			  cpumask_var_t tmpmask)
+{
+	struct rdtgroup *prgrp = rdtgrp->mon.parent, *crgrp;
+	struct list_head *head;
+
+	/* Check whether cpus belong to parent ctrl group */
+	cpumask_andnot(tmpmask, newmask, &prgrp->cpu_mask);
+	if (cpumask_weight(tmpmask))
+		return -EINVAL;
+
+	/* Check whether cpus are dropped from this group */
+	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
+	if (cpumask_weight(tmpmask)) {
+		/* Give any dropped cpus to parent rdtgroup */
+		cpumask_or(&prgrp->cpu_mask, &prgrp->cpu_mask, tmpmask);
+		update_closid_rmid(tmpmask, prgrp);
+	}
+
+	/*
+	 * If we added cpus, remove them from previous group that owned them
+	 * and update per-cpu rmid
+	 */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
+	if (cpumask_weight(tmpmask)) {
+		head = &prgrp->mon.crdtgrp_list;
+		list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
+			if (crgrp == rdtgrp)
+				continue;
+			cpumask_andnot(&crgrp->cpu_mask, &crgrp->cpu_mask,
+				       tmpmask);
+		}
+		update_closid_rmid(tmpmask, rdtgrp);
+	}
+
+	/* Done pushing/pulling - update this group with new mask */
+	cpumask_copy(&rdtgrp->cpu_mask, newmask);
+
+	return 0;
+}
+
+static void cpumask_rdtgrp_clear(struct rdtgroup *r, struct cpumask *m)
+{
+	struct rdtgroup *crgrp;
+
+	cpumask_andnot(&r->cpu_mask, &r->cpu_mask, m);
+	/* update the child mon group masks as well*/
+	list_for_each_entry(crgrp, &r->mon.crdtgrp_list, mon.crdtgrp_list)
+		cpumask_and(&crgrp->cpu_mask, &r->cpu_mask, &crgrp->cpu_mask);
+}
+
 static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
-			   cpumask_var_t tmpmask)
+			   cpumask_var_t tmpmask, cpumask_var_t tmpmask1)
 {
-	struct rdtgroup *r;
+	struct rdtgroup *r, *crgrp;
+	struct list_head *head;
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
@@ -230,33 +284,47 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 		/* Give any dropped cpus to rdtgroup_default */
 		cpumask_or(&rdtgroup_default.cpu_mask,
 			   &rdtgroup_default.cpu_mask, tmpmask);
-		update_closid(tmpmask, &rdtgroup_default);
+		update_closid_rmid(tmpmask, &rdtgroup_default);
 	}
 
 	/*
-	 * If we added cpus, remove them from previous group that owned them
-	 * and update per-cpu closid
+	 * If we added cpus, remove them from previous group and
+	 * the prev group's child groups that owned them
+	 * and update per-cpu closid/rmid.
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
 	if (cpumask_weight(tmpmask)) {
 		list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
 			if (r == rdtgrp)
 				continue;
-			cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask);
+			cpumask_and(tmpmask1, &r->cpu_mask, tmpmask);
+			if (cpumask_weight(tmpmask1))
+				cpumask_rdtgrp_clear(r, tmpmask1);
 		}
-		update_closid(tmpmask, rdtgrp);
+		update_closid_rmid(tmpmask, rdtgrp);
 	}
 
 	/* Done pushing/pulling - update this group with new mask */
 	cpumask_copy(&rdtgrp->cpu_mask, newmask);
 
+	/*
+	 * Clear child mon group masks since there is a new parent mask
+	 * now and update the rmid for the cpus the child lost.
+	 */
+	head = &rdtgrp->mon.crdtgrp_list;
+	list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
+		cpumask_and(tmpmask, &rdtgrp->cpu_mask, &crgrp->cpu_mask);
+		update_closid_rmid(tmpmask, rdtgrp);
+		cpumask_clear(&crgrp->cpu_mask);
+	}
+
 	return 0;
 }
 
 static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 				   char *buf, size_t nbytes, loff_t off)
 {
-	cpumask_var_t tmpmask, newmask;
+	cpumask_var_t tmpmask, newmask, tmpmask1;
 	struct rdtgroup *rdtgrp;
 	int ret;
 
@@ -269,6 +337,11 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 		free_cpumask_var(tmpmask);
 		return -ENOMEM;
 	}
+	if (!zalloc_cpumask_var(&tmpmask1, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		free_cpumask_var(newmask);
+		return -ENOMEM;
+	}
 
 	rdtgrp = rdtgroup_kn_lock_live(of->kn);
 	if (!rdtgrp) {
@@ -292,7 +365,9 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 	}
 
 	if (rdtgrp->type == RDTCTRL_GROUP)
-		ret = cpus_ctrl_write(rdtgrp, newmask, tmpmask);
+		ret = cpus_ctrl_write(rdtgrp, newmask, tmpmask, tmpmask1);
+	else if (rdtgrp->type == RDTMON_GROUP)
+		ret = cpus_mon_write(rdtgrp, newmask, tmpmask);
 	else
 		ret = -EINVAL;
 
@@ -300,6 +375,7 @@ unlock:
 	rdtgroup_kn_unlock(of->kn);
 	free_cpumask_var(tmpmask);
 	free_cpumask_var(newmask);
+	free_cpumask_var(tmpmask1);
 
 	return ret ?: nbytes;
 }
@@ -1113,7 +1189,7 @@ static void rmdir_all_sub(void)
 	}
 	/* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
 	get_online_cpus();
-	update_closid(cpu_online_mask, &rdtgroup_default);
+	update_closid_rmid(cpu_online_mask, &rdtgroup_default);
 	put_online_cpus();
 
 	kernfs_remove(kn_info);
@@ -1374,7 +1450,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 	 * task running on them.
 	 */
 	cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
-	update_closid(tmpmask, NULL);
+	update_closid_rmid(tmpmask, NULL);
 
 	rdtgrp->flags = RDT_DELETED;
 	closid_free(rdtgrp->closid);
#41 lore raw

PATCH v2 18/28 x86/intel_rdt: Prepare for RDT monitor data support

In reply to Vikas Shivappa

Rename the intel_rdt_schemata file to intel_rdt_ctrlmondata as we now want to add support for RDT monitoring data for the events that are supported in later patches.

---
 arch/x86/kernel/cpu/Makefile                |   2 +-
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 286 ++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_schemata.c    | 286 ----------------------------
 3 files changed, 287 insertions(+), 287 deletions(-)
 create mode 100644 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c
 delete mode 100644 arch/x86/kernel/cpu/intel_rdt_schemata.c
arch/x86/kernel/cpu/Makefile +1 -1
index 81b0060..1245f98 100644
@@ -32,7 +32,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o intel_rdt_monitor.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_monitor.o intel_rdt_ctrlmondata.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c new file +286 -0

286 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_schemata.c deleted +0 -286

286 lines not on this page · raw message

Signature · 1 line
1.9.1
#42 lore raw

[tip:x86/cache] x86/intel_rdt: Prepare for RDT monitor data support

x86/intel_rdt: Prepare for RDT monitor data support
Commit-ID:  90c403e83101c87ee9e6df8c8d30ea8628ff8bfc
Gitweb:     http://git.kernel.org/tip/90c403e83101c87ee9e6df8c8d30ea8628ff8bfc
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:37 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:25 +0200

x86/intel_rdt: Prepare for RDT monitor data support

Rename the intel_rdt_schemata file to intel_rdt_ctrlmondata as we now want to add support for RDT monitoring data for the events that are supported in later patches.

---
 arch/x86/kernel/cpu/Makefile                                          | 2 +-
 arch/x86/kernel/cpu/{intel_rdt_schemata.c => intel_rdt_ctrlmondata.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/Makefile +1 -1
index 7584be0..e17942c 100644
@@ -33,7 +33,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o intel_rdt_monitor.o
+obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_monitor.o intel_rdt_ctrlmondata.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c renamed from arch/x86/kernel/cpu/intel_rdt_schemata.c +0 -0
similarity index 100%
rename from arch/x86/kernel/cpu/intel_rdt_schemata.c
rename to arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c
#43 lore raw

PATCH v2 19/28 x86/intel_rdt/cqm: Add mon_data

In reply to Vikas Shivappa

Add a mon_data directory for the root rdtgroup and all other rdtgroups. The directory holds all of the monitored data for all domains and events of all resources being monitored.

The mon_data itself has a list of directories in the format mon_<domain_name>_<domain_id>. Each of these subdirectories contain one file per event in the mode "0444". Reading the file displays a snapshot of the monitored data for the event the file represents.

For ex, on a 2 socket Broadwell with llc_occupancy being monitored the mon_data contents look as below:

$ ls /sys/fs/resctrl/p1/mon_data/
mon_L3_00
mon_L3_01

Each domain directory has one file per event:

$ ls /sys/fs/resctrl/p1/mon_data/mon_L3_00/
llc_occupancy

To read current llc_occupancy of ctrl_mon group p1

$ cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
33789096

[This patch idea is based on Tony's sample patches to organise data in a per domain directory and have one file per event (and use the fp->priv to store mon data bits)]

---
 arch/x86/kernel/cpu/intel_rdt.c             |   9 +-
 arch/x86/kernel/cpu/intel_rdt.h             |  29 ++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c |  55 ++++++++++-
 arch/x86/kernel/cpu/intel_rdt_monitor.c     |  49 ++++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c    | 145 ++++++++++++++++++++++++++++
 5 files changed, 284 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +7 -2
index cd48ec9..81d1cd3 100644
@@ -71,6 +71,7 @@
 struct rdt_resource rdt_resources_all[] = {
 	[RDT_RESOURCE_L3] =
 	{
+		.rid			= RDT_RESOURCE_L3,
 		.name			= "L3",
 		.domains		= domain_init(RDT_RESOURCE_L3),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -87,6 +88,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L3DATA] =
 	{
+		.rid			= RDT_RESOURCE_L3DATA,
 		.name			= "L3DATA",
 		.domains		= domain_init(RDT_RESOURCE_L3DATA),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -103,6 +105,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L3CODE] =
 	{
+		.rid			= RDT_RESOURCE_L3CODE,
 		.name			= "L3CODE",
 		.domains		= domain_init(RDT_RESOURCE_L3CODE),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -119,6 +122,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L2] =
 	{
+		.rid			= RDT_RESOURCE_L2,
 		.name			= "L2",
 		.domains		= domain_init(RDT_RESOURCE_L2),
 		.msr_base		= IA32_L2_CBM_BASE,
@@ -135,6 +139,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_MBA] =
 	{
+		.rid			= RDT_RESOURCE_MBA,
 		.name			= "MB",
 		.domains		= domain_init(RDT_RESOURCE_MBA),
 		.msr_base		= IA32_MBA_THRTL_BASE,
@@ -362,8 +367,8 @@ void rdt_ctrl_update(void *arg)
  * caller, return the first domain whose id is bigger than the input id.
  * The domain list is sorted by id in ascending order.
  */
-static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
-					  struct list_head **pos)
+struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
+				   struct list_head **pos)
 {
 	struct rdt_domain *d;
 	struct list_head *l;
arch/x86/kernel/cpu/intel_rdt.h +29 -0
index 6f07047..7fcaa5f 100644
@@ -33,6 +33,27 @@ struct mon_evt {
 	struct list_head	list;
 };
 
+/**
+ * struct mon_data_bits - Monitoring details for each event file
+ * @rid:               Resource id associated with the event file.
+ * @evtid:             Event id associated with the event file
+ * @domid:             The domain to which the event file belongs
+ */
+union mon_data_bits {
+	void *priv;
+	struct {
+		unsigned int rid	: 10;
+		unsigned int evtid	: 8;
+		unsigned int domid	: 14;
+	} u;
+};
+
+struct rmid_read {
+	struct rdtgroup		*rgrp;
+	int			evtid;
+	u64			val;
+};
+
 extern unsigned int intel_cqm_threshold;
 extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
@@ -46,11 +67,13 @@ enum rdt_group_type {
 
 /**
  * struct mongroup - store mon group's data in resctrl fs.
+ * @mon_data_kn		kernlfs node for the mon_data directory
  * @parent:			parent rdtgrp
  * @crdtgrp_list:		child rdtgroup node list
  * @rmid:			rmid for this rdtgroup
  */
 struct mongroup {
+	struct kernfs_node	*mon_data_kn;
 	struct rdtgroup		*parent;
 	struct list_head	crdtgrp_list;
 	u32			rmid;
@@ -209,6 +232,7 @@ static inline bool is_llc_occupancy_enabled(void)
 
 /**
  * struct rdt_resource - attributes of an RDT resource
+ * @rid:		The index of the resource
  * @alloc_enabled:	Is allocation enabled on this machine
  * @mon_enabled:		Is monitoring enabled for this feature
  * @alloc_capable:	Is allocation available on this machine
@@ -230,6 +254,7 @@ static inline bool is_llc_occupancy_enabled(void)
  * @fflags:			flags to choose base and info files
  */
 struct rdt_resource {
+	int			rid;
 	bool			alloc_enabled;
 	bool			mon_enabled;
 	bool			alloc_capable;
@@ -323,6 +348,8 @@ enum {
 void rdt_ctrl_update(void *arg);
 struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
 void rdtgroup_kn_unlock(struct kernfs_node *kn);
+struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
+				   struct list_head **pos);
 ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 				char *buf, size_t nbytes, loff_t off);
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
@@ -331,5 +358,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 int alloc_rmid(void);
 void free_rmid(u32 rmid);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
+void mon_event_count(void *info);
+int rdtgroup_mondata_show(struct seq_file *m, void *arg);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +54 -1

64 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_monitor.c +49 -0

55 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +145 -0

169 lines not on this page · raw message

Signature · 1 line
1.9.1
#44 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add mon_data

x86/intel_rdt/cqm: Add mon_data
Commit-ID:  d89b7379015fc561060a4094676d143e6ed264e7
Gitweb:     http://git.kernel.org/tip/d89b7379015fc561060a4094676d143e6ed264e7
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:38 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:26 +0200

x86/intel_rdt/cqm: Add mon_data

Add a mon_data directory for the root rdtgroup and all other rdtgroups. The directory holds all of the monitored data for all domains and events of all resources being monitored.

The mon_data itself has a list of directories in the format mon_<domain_name>_<domain_id>. Each of these subdirectories contain one file per event in the mode "0444". Reading the file displays a snapshot of the monitored data for the event the file represents.

For ex, on a 2 socket Broadwell with llc_occupancy being monitored the mon_data contents look as below:

$ ls /sys/fs/resctrl/p1/mon_data/
mon_L3_00
mon_L3_01

Each domain directory has one file per event:

$ ls /sys/fs/resctrl/p1/mon_data/mon_L3_00/
llc_occupancy

To read current llc_occupancy of ctrl_mon group p1

$ cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
33789096

[This patch idea is based on Tony's sample patches to organise data in a per domain directory and have one file per event (and use the fp->priv to store mon data bits)]

---
 arch/x86/kernel/cpu/intel_rdt.c             |   9 +-
 arch/x86/kernel/cpu/intel_rdt.h             |  29 ++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c |  55 ++++++++++-
 arch/x86/kernel/cpu/intel_rdt_monitor.c     |  49 ++++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c    | 145 ++++++++++++++++++++++++++++
 5 files changed, 284 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +7 -2
index 303b085..050ea15 100644
@@ -71,6 +71,7 @@ cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
 struct rdt_resource rdt_resources_all[] = {
 	[RDT_RESOURCE_L3] =
 	{
+		.rid			= RDT_RESOURCE_L3,
 		.name			= "L3",
 		.domains		= domain_init(RDT_RESOURCE_L3),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -87,6 +88,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L3DATA] =
 	{
+		.rid			= RDT_RESOURCE_L3DATA,
 		.name			= "L3DATA",
 		.domains		= domain_init(RDT_RESOURCE_L3DATA),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -103,6 +105,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L3CODE] =
 	{
+		.rid			= RDT_RESOURCE_L3CODE,
 		.name			= "L3CODE",
 		.domains		= domain_init(RDT_RESOURCE_L3CODE),
 		.msr_base		= IA32_L3_CBM_BASE,
@@ -119,6 +122,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_L2] =
 	{
+		.rid			= RDT_RESOURCE_L2,
 		.name			= "L2",
 		.domains		= domain_init(RDT_RESOURCE_L2),
 		.msr_base		= IA32_L2_CBM_BASE,
@@ -135,6 +139,7 @@ struct rdt_resource rdt_resources_all[] = {
 	},
 	[RDT_RESOURCE_MBA] =
 	{
+		.rid			= RDT_RESOURCE_MBA,
 		.name			= "MB",
 		.domains		= domain_init(RDT_RESOURCE_MBA),
 		.msr_base		= IA32_MBA_THRTL_BASE,
@@ -362,8 +367,8 @@ void rdt_ctrl_update(void *arg)
  * caller, return the first domain whose id is bigger than the input id.
  * The domain list is sorted by id in ascending order.
  */
-static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
-					  struct list_head **pos)
+struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
+				   struct list_head **pos)
 {
 	struct rdt_domain *d;
 	struct list_head *l;
arch/x86/kernel/cpu/intel_rdt.h +29 -0
index 6f07047..7fcaa5f 100644
@@ -33,6 +33,27 @@ struct mon_evt {
 	struct list_head	list;
 };
 
+/**
+ * struct mon_data_bits - Monitoring details for each event file
+ * @rid:               Resource id associated with the event file.
+ * @evtid:             Event id associated with the event file
+ * @domid:             The domain to which the event file belongs
+ */
+union mon_data_bits {
+	void *priv;
+	struct {
+		unsigned int rid	: 10;
+		unsigned int evtid	: 8;
+		unsigned int domid	: 14;
+	} u;
+};
+
+struct rmid_read {
+	struct rdtgroup		*rgrp;
+	int			evtid;
+	u64			val;
+};
+
 extern unsigned int intel_cqm_threshold;
 extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
@@ -46,11 +67,13 @@ enum rdt_group_type {
 
 /**
  * struct mongroup - store mon group's data in resctrl fs.
+ * @mon_data_kn		kernlfs node for the mon_data directory
  * @parent:			parent rdtgrp
  * @crdtgrp_list:		child rdtgroup node list
  * @rmid:			rmid for this rdtgroup
  */
 struct mongroup {
+	struct kernfs_node	*mon_data_kn;
 	struct rdtgroup		*parent;
 	struct list_head	crdtgrp_list;
 	u32			rmid;
@@ -209,6 +232,7 @@ static inline bool is_llc_occupancy_enabled(void)
 
 /**
  * struct rdt_resource - attributes of an RDT resource
+ * @rid:		The index of the resource
  * @alloc_enabled:	Is allocation enabled on this machine
  * @mon_enabled:		Is monitoring enabled for this feature
  * @alloc_capable:	Is allocation available on this machine
@@ -230,6 +254,7 @@ static inline bool is_llc_occupancy_enabled(void)
  * @fflags:			flags to choose base and info files
  */
 struct rdt_resource {
+	int			rid;
 	bool			alloc_enabled;
 	bool			mon_enabled;
 	bool			alloc_capable;
@@ -323,6 +348,8 @@ union cpuid_0x10_x_edx {
 void rdt_ctrl_update(void *arg);
 struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
 void rdtgroup_kn_unlock(struct kernfs_node *kn);
+struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
+				   struct list_head **pos);
 ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 				char *buf, size_t nbytes, loff_t off);
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
@@ -331,5 +358,7 @@ struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
 int alloc_rmid(void);
 void free_rmid(u32 rmid);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
+void mon_event_count(void *info);
+int rdtgroup_mondata_show(struct seq_file *m, void *arg);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +54 -1

64 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_monitor.c +49 -0

55 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +145 -0

169 lines not on this page · raw message

#45 lore raw

PATCH v2 20/28 x86/intel_rdt: Separate the ctrl bits from rmdir

In reply to Vikas Shivappa

Re-factor the code to separate the ctrl group removal from the rmdir to prepare to add RDT monitoring group removal.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 48 ++++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 15 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +33 -15
index 8f9b54e..59251592 100644
@@ -1568,20 +1568,10 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	return -EPERM;
 }
 
-static int rdtgroup_rmdir(struct kernfs_node *kn)
+static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
+			       cpumask_var_t tmpmask)
 {
-	int ret, cpu, closid = rdtgroup_default.closid;
-	struct rdtgroup *rdtgrp;
-	cpumask_var_t tmpmask;
-
-	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
-		return -ENOMEM;
-
-	rdtgrp = rdtgroup_kn_lock_live(kn);
-	if (!rdtgrp) {
-		ret = -EPERM;
-		goto out;
-	}
+	int cpu;
 
 	/* Give any tasks back to the default group */
 	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
@@ -1592,7 +1582,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 
 	/* Update per cpu closid of the moved CPUs first */
 	for_each_cpu(cpu, &rdtgrp->cpu_mask)
-		per_cpu(rdt_cpu_default.closid, cpu) = closid;
+		per_cpu(rdt_cpu_default.closid, cpu) = rdtgroup_default.closid;
 	/*
 	 * Update the MSR on moved CPUs and CPUs which have moved
 	 * task running on them.
@@ -1610,7 +1600,35 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 	 */
 	kernfs_get(kn);
 	kernfs_remove(rdtgrp->kn);
-	ret = 0;
+
+	return 0;
+}
+
+static int rdtgroup_rmdir(struct kernfs_node *kn)
+{
+	struct kernfs_node *parent_kn = kn->parent;
+	struct rdtgroup *rdtgrp;
+	cpumask_var_t tmpmask;
+	int ret = 0;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+
+	rdtgrp = rdtgroup_kn_lock_live(kn);
+	if (!rdtgrp) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/*
+	 * If the rdtgroup is a ctrl_mon group and parent directory
+	 * is the root directory, remove the ctrl group.
+	 */
+	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn)
+		ret = rdtgroup_rmdir_ctrl(kn, rdtgrp, tmpmask);
+	else
+		ret = -EPERM;
+
 out:
 	rdtgroup_kn_unlock(kn);
 	free_cpumask_var(tmpmask);
Signature · 1 line
1.9.1
#46 lore raw

[tip:x86/cache] x86/intel_rdt: Separate the ctrl bits from rmdir

x86/intel_rdt: Separate the ctrl bits from rmdir
Commit-ID:  f9049547f7e72377049d717354b2f56f36a5854a
Gitweb:     http://git.kernel.org/tip/f9049547f7e72377049d717354b2f56f36a5854a
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:39 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:26 +0200

x86/intel_rdt: Separate the ctrl bits from rmdir

Re-factor the code to separate the ctrl group removal from the rmdir to prepare to add RDT monitoring group removal.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 48 ++++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 15 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +33 -15
index 59de36d..3b62287 100644
@@ -1565,20 +1565,10 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	return -EPERM;
 }
 
-static int rdtgroup_rmdir(struct kernfs_node *kn)
+static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
+			       cpumask_var_t tmpmask)
 {
-	int ret, cpu, closid = rdtgroup_default.closid;
-	struct rdtgroup *rdtgrp;
-	cpumask_var_t tmpmask;
-
-	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
-		return -ENOMEM;
-
-	rdtgrp = rdtgroup_kn_lock_live(kn);
-	if (!rdtgrp) {
-		ret = -EPERM;
-		goto out;
-	}
+	int cpu;
 
 	/* Give any tasks back to the default group */
 	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
@@ -1589,7 +1579,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 
 	/* Update per cpu closid of the moved CPUs first */
 	for_each_cpu(cpu, &rdtgrp->cpu_mask)
-		per_cpu(rdt_cpu_default.closid, cpu) = closid;
+		per_cpu(rdt_cpu_default.closid, cpu) = rdtgroup_default.closid;
 	/*
 	 * Update the MSR on moved CPUs and CPUs which have moved
 	 * task running on them.
@@ -1607,7 +1597,35 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 	 */
 	kernfs_get(kn);
 	kernfs_remove(rdtgrp->kn);
-	ret = 0;
+
+	return 0;
+}
+
+static int rdtgroup_rmdir(struct kernfs_node *kn)
+{
+	struct kernfs_node *parent_kn = kn->parent;
+	struct rdtgroup *rdtgrp;
+	cpumask_var_t tmpmask;
+	int ret = 0;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+
+	rdtgrp = rdtgroup_kn_lock_live(kn);
+	if (!rdtgrp) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/*
+	 * If the rdtgroup is a ctrl_mon group and parent directory
+	 * is the root directory, remove the ctrl group.
+	 */
+	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn)
+		ret = rdtgroup_rmdir_ctrl(kn, rdtgrp, tmpmask);
+	else
+		ret = -EPERM;
+
 out:
 	rdtgroup_kn_unlock(kn);
 	free_cpumask_var(tmpmask);
#47 lore raw

PATCH v2 21/28 x86/intel_rdt/cqm: Add rmdir support

In reply to Vikas Shivappa

Resource groups (ctrl_mon and monitor groups) are represented by directories in resctrl fs. Add support to remove the directories.

When a ctrl_mon directory is removed all the cpus and tasks are assigned back to the root rdtgroup. When a monitor group is removed the cpus and tasks are returned to the parent control group.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 90 ++++++++++++++++++++++++++++++--
 1 file changed, 86 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +86 -4
index 59251592..a5e6d60 100644
@@ -1131,6 +1131,18 @@ static int reset_all_ctrls(struct rdt_resource *r)
 	return 0;
 }
 
+static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_alloc_capable &&
+		(r->type == RDTCTRL_GROUP) && (t->closid == r->closid));
+}
+
+static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_mon_capable &&
+		(r->type == RDTMON_GROUP) && (t->rmid == r->mon.rmid));
+}
+
 /*
  * Move tasks from one to the other group. If @from is NULL, then all tasks
  * in the systems are moved unconditionally (used for teardown).
@@ -1146,8 +1158,11 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
 
 	read_lock(&tasklist_lock);
 	for_each_process_thread(p, t) {
-		if (!from || t->closid == from->closid) {
+		if (!from || is_closid_match(t, from) ||
+		    is_rmid_match(t, from)) {
 			t->closid = to->closid;
+			t->rmid = to->mon.rmid;
+
 #ifdef CONFIG_SMP
 			/*
 			 * This is safe on x86 w/o barriers as the ordering
@@ -1166,6 +1181,19 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
 	read_unlock(&tasklist_lock);
 }
 
+static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
+{
+	struct rdtgroup *sentry, *stmp;
+	struct list_head *head;
+
+	head = &rdtgrp->mon.crdtgrp_list;
+	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		free_rmid(sentry->mon.rmid);
+		list_del(&sentry->mon.crdtgrp_list);
+		kfree(sentry);
+	}
+}
+
 /*
  * Forcibly remove all of subdirectories under root.
  */
@@ -1568,6 +1596,44 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	return -EPERM;
 }
 
+static int rdtgroup_rmdir_mon(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
+			      cpumask_var_t tmpmask)
+{
+	struct rdtgroup *prdtgrp = rdtgrp->mon.parent;
+	int cpu;
+
+	/* Give any tasks back to the parent group */
+	rdt_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
+
+	/* Update per cpu rmid of the moved CPUs first */
+	for_each_cpu(cpu, &rdtgrp->cpu_mask)
+		per_cpu(rdt_cpu_default.rmid, cpu) = prdtgrp->mon.rmid;
+	/*
+	 * Update the MSR on moved CPUs and CPUs which have moved
+	 * task running on them.
+	 */
+	cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
+	update_closid_rmid(tmpmask, NULL);
+
+	rdtgrp->flags = RDT_DELETED;
+	free_rmid(rdtgrp->mon.rmid);
+
+	/*
+	 * Remove the rdtgrp from the parent ctrl_mon group's list
+	 */
+	WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
+	list_del(&rdtgrp->mon.crdtgrp_list);
+
+	/*
+	 * one extra hold on this, will drop when we kfree(rdtgrp)
+	 * in rdtgroup_kn_unlock()
+	 */
+	kernfs_get(kn);
+	kernfs_remove(rdtgrp->kn);
+
+	return 0;
+}
+
 static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 			       cpumask_var_t tmpmask)
 {
@@ -1580,9 +1646,12 @@ static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 	cpumask_or(&rdtgroup_default.cpu_mask,
 		   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
 
-	/* Update per cpu closid of the moved CPUs first */
-	for_each_cpu(cpu, &rdtgrp->cpu_mask)
+	/* Update per cpu closid and rmid of the moved CPUs first */
+	for_each_cpu(cpu, &rdtgrp->cpu_mask) {
 		per_cpu(rdt_cpu_default.closid, cpu) = rdtgroup_default.closid;
+		per_cpu(rdt_cpu_default.rmid, cpu) = rdtgroup_default.mon.rmid;
+	}
+
 	/*
 	 * Update the MSR on moved CPUs and CPUs which have moved
 	 * task running on them.
@@ -1592,6 +1661,13 @@ static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 
 	rdtgrp->flags = RDT_DELETED;
 	closid_free(rdtgrp->closid);
+	free_rmid(rdtgrp->mon.rmid);
+
+	/*
+	 * Free all the child monitor group rmids.
+	 */
+	free_all_child_rdtgrp(rdtgrp);
+
 	list_del(&rdtgrp->rdtgroup_list);
 
 	/*
@@ -1622,10 +1698,16 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 
 	/*
 	 * If the rdtgroup is a ctrl_mon group and parent directory
-	 * is the root directory, remove the ctrl group.
+	 * is the root directory, remove the ctrl_mon group.
+	 *
+	 * If the rdtgroup is a mon group and parent directory
+	 * is a valid "mon_groups" directory, remove the mon group.
 	 */
 	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn)
 		ret = rdtgroup_rmdir_ctrl(kn, rdtgrp, tmpmask);
+	else if (rdtgrp->type == RDTMON_GROUP &&
+		 is_mon_groups(parent_kn, kn->name))
+		ret = rdtgroup_rmdir_mon(kn, rdtgrp, tmpmask);
 	else
 		ret = -EPERM;
 
Signature · 1 line
1.9.1
#48 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add rmdir support

x86/intel_rdt/cqm: Add rmdir support
Commit-ID:  f3cbeacaa06e2b8c2f3ce8531e9aa3fe1f2762cd
Gitweb:     http://git.kernel.org/tip/f3cbeacaa06e2b8c2f3ce8531e9aa3fe1f2762cd
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:40 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:27 +0200

x86/intel_rdt/cqm: Add rmdir support

Resource groups (ctrl_mon and monitor groups) are represented by directories in resctrl fs. Add support to remove the directories.

When a ctrl_mon directory is removed all the cpus and tasks are assigned back to the root rdtgroup. When a monitor group is removed the cpus and tasks are returned to the parent control group.

---
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 90 ++++++++++++++++++++++++++++++--
 1 file changed, 86 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +86 -4
index 3b62287..e619081 100644
@@ -1130,6 +1130,18 @@ static int reset_all_ctrls(struct rdt_resource *r)
 	return 0;
 }
 
+static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_alloc_capable &&
+		(r->type == RDTCTRL_GROUP) && (t->closid == r->closid));
+}
+
+static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_mon_capable &&
+		(r->type == RDTMON_GROUP) && (t->rmid == r->mon.rmid));
+}
+
 /*
  * Move tasks from one to the other group. If @from is NULL, then all tasks
  * in the systems are moved unconditionally (used for teardown).
@@ -1145,8 +1157,11 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
 
 	read_lock(&tasklist_lock);
 	for_each_process_thread(p, t) {
-		if (!from || t->closid == from->closid) {
+		if (!from || is_closid_match(t, from) ||
+		    is_rmid_match(t, from)) {
 			t->closid = to->closid;
+			t->rmid = to->mon.rmid;
+
 #ifdef CONFIG_SMP
 			/*
 			 * This is safe on x86 w/o barriers as the ordering
@@ -1165,6 +1180,19 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
 	read_unlock(&tasklist_lock);
 }
 
+static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp)
+{
+	struct rdtgroup *sentry, *stmp;
+	struct list_head *head;
+
+	head = &rdtgrp->mon.crdtgrp_list;
+	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
+		free_rmid(sentry->mon.rmid);
+		list_del(&sentry->mon.crdtgrp_list);
+		kfree(sentry);
+	}
+}
+
 /*
  * Forcibly remove all of subdirectories under root.
  */
@@ -1565,6 +1593,44 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	return -EPERM;
 }
 
+static int rdtgroup_rmdir_mon(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
+			      cpumask_var_t tmpmask)
+{
+	struct rdtgroup *prdtgrp = rdtgrp->mon.parent;
+	int cpu;
+
+	/* Give any tasks back to the parent group */
+	rdt_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
+
+	/* Update per cpu rmid of the moved CPUs first */
+	for_each_cpu(cpu, &rdtgrp->cpu_mask)
+		per_cpu(rdt_cpu_default.rmid, cpu) = prdtgrp->mon.rmid;
+	/*
+	 * Update the MSR on moved CPUs and CPUs which have moved
+	 * task running on them.
+	 */
+	cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
+	update_closid_rmid(tmpmask, NULL);
+
+	rdtgrp->flags = RDT_DELETED;
+	free_rmid(rdtgrp->mon.rmid);
+
+	/*
+	 * Remove the rdtgrp from the parent ctrl_mon group's list
+	 */
+	WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
+	list_del(&rdtgrp->mon.crdtgrp_list);
+
+	/*
+	 * one extra hold on this, will drop when we kfree(rdtgrp)
+	 * in rdtgroup_kn_unlock()
+	 */
+	kernfs_get(kn);
+	kernfs_remove(rdtgrp->kn);
+
+	return 0;
+}
+
 static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 			       cpumask_var_t tmpmask)
 {
@@ -1577,9 +1643,12 @@ static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 	cpumask_or(&rdtgroup_default.cpu_mask,
 		   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
 
-	/* Update per cpu closid of the moved CPUs first */
-	for_each_cpu(cpu, &rdtgrp->cpu_mask)
+	/* Update per cpu closid and rmid of the moved CPUs first */
+	for_each_cpu(cpu, &rdtgrp->cpu_mask) {
 		per_cpu(rdt_cpu_default.closid, cpu) = rdtgroup_default.closid;
+		per_cpu(rdt_cpu_default.rmid, cpu) = rdtgroup_default.mon.rmid;
+	}
+
 	/*
 	 * Update the MSR on moved CPUs and CPUs which have moved
 	 * task running on them.
@@ -1589,6 +1658,13 @@ static int rdtgroup_rmdir_ctrl(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
 
 	rdtgrp->flags = RDT_DELETED;
 	closid_free(rdtgrp->closid);
+	free_rmid(rdtgrp->mon.rmid);
+
+	/*
+	 * Free all the child monitor group rmids.
+	 */
+	free_all_child_rdtgrp(rdtgrp);
+
 	list_del(&rdtgrp->rdtgroup_list);
 
 	/*
@@ -1619,10 +1695,16 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
 
 	/*
 	 * If the rdtgroup is a ctrl_mon group and parent directory
-	 * is the root directory, remove the ctrl group.
+	 * is the root directory, remove the ctrl_mon group.
+	 *
+	 * If the rdtgroup is a mon group and parent directory
+	 * is a valid "mon_groups" directory, remove the mon group.
 	 */
 	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn)
 		ret = rdtgroup_rmdir_ctrl(kn, rdtgrp, tmpmask);
+	else if (rdtgrp->type == RDTMON_GROUP &&
+		 is_mon_groups(parent_kn, kn->name))
+		ret = rdtgroup_rmdir_mon(kn, rdtgrp, tmpmask);
 	else
 		ret = -EPERM;
 
#49 lore raw

PATCH v2 22/28 x86/intel_rdt/cqm: Add mount,umount support

In reply to Vikas Shivappa

Add monitoring support during mount and unmount. Since root directory is a "ctrl_mon" directory which can control and monitor resources create the "mon_groups" directory which can hold monitor groups and a "mon_data" directory which would hold all monitoring data like the rest of resource groups.

The mount succeeds if either of monitoring or control/allocation is enabled. If only monitoring is enabled user can still create monitor groups under the "/sys/fs/resctrl/mon_groups/" and any mkdir under root would fail. If only control/allocation is enabled all of the monitoring related directories/files would not exist and resctrl would work in legacy mode.

---
 arch/x86/kernel/cpu/intel_rdt.h          |  4 +++
 arch/x86/kernel/cpu/intel_rdt_monitor.c  |  1 +
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 61 +++++++++++++++++++++++++++++---
 3 files changed, 62 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +4 -0
index 7fcaa5f..92a5d30 100644
@@ -22,6 +22,8 @@
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -59,6 +61,8 @@ struct rmid_read {
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
 
+DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
+
 enum rdt_group_type {
 	RDTCTRL_GROUP = 0,
 	RDTMON_GROUP,
arch/x86/kernel/cpu/intel_rdt_monitor.c +1 -0
index f8f06f5..6ae5cf5 100644
@@ -343,6 +343,7 @@ void mon_event_count(void *info)
 		}
 	}
 }
+
 static int dom_data_init(struct rdt_resource *r)
 {
 	struct rmid_entry *entry = NULL;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +57 -4

121 lines not on this page · raw message

Signature · 1 line
1.9.1
#50 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add mount,umount support

x86/intel_rdt/cqm: Add mount,umount support
Commit-ID:  4af4a88e0c9246990f95c88eeba781265f27c58e
Gitweb:     http://git.kernel.org/tip/4af4a88e0c9246990f95c88eeba781265f27c58e
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:41 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:27 +0200

x86/intel_rdt/cqm: Add mount,umount support

Add monitoring support during mount and unmount. Since root directory is a "ctrl_mon" directory which can control and monitor resources create the "mon_groups" directory which can hold monitor groups and a "mon_data" directory which would hold all monitoring data like the rest of resource groups.

The mount succeeds if either of monitoring or control/allocation is enabled. If only monitoring is enabled user can still create monitor groups under the "/sys/fs/resctrl/mon_groups/" and any mkdir under root would fail. If only control/allocation is enabled all of the monitoring related directories/files would not exist and resctrl would work in legacy mode.

---
 arch/x86/kernel/cpu/intel_rdt.h          |  4 +++
 arch/x86/kernel/cpu/intel_rdt_monitor.c  |  1 +
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 61 +++++++++++++++++++++++++++++---
 3 files changed, 62 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +4 -0
index 7fcaa5f..92a5d30 100644
@@ -22,6 +22,8 @@
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -59,6 +61,8 @@ extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
 
+DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
+
 enum rdt_group_type {
 	RDTCTRL_GROUP = 0,
 	RDTMON_GROUP,
arch/x86/kernel/cpu/intel_rdt_monitor.c +1 -0
index f8f06f5..6ae5cf5 100644
@@ -343,6 +343,7 @@ void mon_event_count(void *info)
 		}
 	}
 }
+
 static int dom_data_init(struct rdt_resource *r)
 {
 	struct rmid_entry *entry = NULL;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +57 -4

121 lines not on this page · raw message

#51 lore raw

PATCH v2 23/28 x86/intel_rdt: Introduce rdt_enable_key for scheduling

In reply to Vikas Shivappa

Introduce the usage of rdt_enable_key in sched_in code as a preparation to add RDT monitoring support for sched_in.

---
 arch/x86/include/asm/intel_rdt_sched.h | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +10 -2
index 2c704d2..8c5be01 100644
@@ -27,10 +27,12 @@ struct intel_pqr_state {
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
 DECLARE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
+
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
- * intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
+ * __intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
  *
  * Following considerations are made so that this has minimal impact
  * on scheduler hot path:
@@ -42,7 +44,7 @@ struct intel_pqr_state {
  *
  * Must be called with preemption disabled.
  */
-static inline void intel_rdt_sched_in(void)
+static inline void __intel_rdt_sched_in(void)
 {
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
@@ -63,6 +65,12 @@ static inline void intel_rdt_sched_in(void)
 	}
 }
 
+static inline void intel_rdt_sched_in(void)
+{
+	if (static_branch_likely(&rdt_enable_key))
+		__intel_rdt_sched_in();
+}
+
 #else
 
 static inline void intel_rdt_sched_in(void) {}
Signature · 1 line
1.9.1
#52 lore raw

[tip:x86/cache] x86/intel_rdt: Introduce rdt_enable_key for scheduling

x86/intel_rdt: Introduce rdt_enable_key for scheduling
Commit-ID:  4be6c078428b08d1a948cc09faca8f1326231866
Gitweb:     http://git.kernel.org/tip/4be6c078428b08d1a948cc09faca8f1326231866
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:42 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:27 +0200

x86/intel_rdt: Introduce rdt_enable_key for scheduling

Introduce the usage of rdt_enable_key in sched_in code as a preparation to add RDT monitoring support for sched_in.

---
 arch/x86/include/asm/intel_rdt_sched.h | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +10 -2
index 2c704d2..8c5be01 100644
@@ -27,10 +27,12 @@ struct intel_pqr_state {
 
 DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
 DECLARE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
+
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
 
 /*
- * intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
+ * __intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
  *
  * Following considerations are made so that this has minimal impact
  * on scheduler hot path:
@@ -42,7 +44,7 @@ DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
  *
  * Must be called with preemption disabled.
  */
-static inline void intel_rdt_sched_in(void)
+static inline void __intel_rdt_sched_in(void)
 {
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
 		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
@@ -63,6 +65,12 @@ static inline void intel_rdt_sched_in(void)
 	}
 }
 
+static inline void intel_rdt_sched_in(void)
+{
+	if (static_branch_likely(&rdt_enable_key))
+		__intel_rdt_sched_in();
+}
+
 #else
 
 static inline void intel_rdt_sched_in(void) {}
#53 lore raw

PATCH v2 24/28 x86/intel_rdt/cqm: Add sched_in support

In reply to Vikas Shivappa

OS associates an RMID/CLOSid to a task by writing the per CPU IA32_PQR_ASSOC MSR when a task is scheduled in.

The sched_in code will stay as no-op unless we are running on Intel SKU which supports either resource control or monitoring and we also enable them by mounting the resctrl fs. The per cpu CLOSid/RMID values are cached and the write is performed only when a task with a different CLOSid/RMID is scheduled in.

---
 arch/x86/include/asm/intel_rdt_sched.h | 50 ++++++++++++++++++++--------------
 arch/x86/kernel/cpu/intel_rdt.h        |  4 ---
 2 files changed, 29 insertions(+), 25 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +29 -21
index 8c5be01..3badc0a 100644
@@ -15,7 +15,8 @@
  *
  * The upper 32 bits of IA32_PQR_ASSOC contain closid and the
  * lower 10 bits rmid. The update to IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
+ * contains both parts, so we need to cache them. This also
+ * stores the user configured per cpu CLOSID and RMID.
  *
  * The cache also helps to avoid pointless updates if the value does
  * not change.
@@ -30,38 +31,45 @@ struct intel_pqr_state {
 
 DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
 
 /*
- * __intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
+ * __intel_rdt_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR
  *
  * Following considerations are made so that this has minimal impact
  * on scheduler hot path:
  * - This will stay as no-op unless we are running on an Intel SKU
- *   which supports resource control and we enable by mounting the
- *   resctrl file system.
- * - Caches the per cpu CLOSid values and does the MSR write only
- *   when a task with a different CLOSid is scheduled in.
- *
+ *   which supports resource control or monitoring and we enable by
+ *   mounting the resctrl file system.
+ * - Caches the per cpu CLOSid/RMID values and does the MSR write only
+ *   when a task with a different CLOSid/RMID is scheduled in.
+ * - We allocate RMIDs/CLOSids globally in order to keep this as
+ *   simple as possible.
  * Must be called with preemption disabled.
  */
-static inline void __intel_rdt_sched_in(void)
+static void __intel_rdt_sched_in(void)
 {
+	struct intel_pqr_state newstate = this_cpu_read(rdt_cpu_default);
+	struct intel_pqr_state *curstate = this_cpu_ptr(&pqr_state);
+
+	/*
+	 * If this task has a closid/rmid assigned, use it.
+	 * Else use the closid/rmid assigned to this cpu.
+	 */
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
-		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-		u32 closid;
+		if (current->closid)
+			newstate.closid = current->closid;
+	}
 
-		/*
-		 * If this task has a closid assigned, use it.
-		 * Else use the closid assigned to this cpu.
-		 */
-		closid = current->closid;
-		if (closid == 0)
-			closid = this_cpu_read(rdt_cpu_default.closid);
+	if (static_branch_likely(&rdt_mon_enable_key)) {
+		if (current->rmid)
+			newstate.rmid = current->rmid;
+	}
 
-		if (closid != state->closid) {
-			state->closid = closid;
-			wrmsr(IA32_PQR_ASSOC, state->rmid, closid);
-		}
+	if (newstate.closid != curstate->closid ||
+	    newstate.rmid != curstate->rmid) {
+		*curstate = newstate;
+		wrmsr(IA32_PQR_ASSOC, newstate.rmid, newstate.closid);
 	}
 }
 
arch/x86/kernel/cpu/intel_rdt.h +0 -4
index 92a5d30..7fcaa5f 100644
@@ -22,8 +22,6 @@
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
-
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -61,8 +59,6 @@ struct rmid_read {
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
 
-DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
-
 enum rdt_group_type {
 	RDTCTRL_GROUP = 0,
 	RDTMON_GROUP,
Signature · 1 line
1.9.1
#54 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add sched_in support

x86/intel_rdt/cqm: Add sched_in support
Commit-ID:  748b6b881ccdda8f0663c68605f431279e06f49a
Gitweb:     http://git.kernel.org/tip/748b6b881ccdda8f0663c68605f431279e06f49a
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:43 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:28 +0200

x86/intel_rdt/cqm: Add sched_in support

OS associates an RMID/CLOSid to a task by writing the per CPU IA32_PQR_ASSOC MSR when a task is scheduled in.

The sched_in code will stay as no-op unless we are running on Intel SKU which supports either resource control or monitoring and we also enable them by mounting the resctrl fs. The per cpu CLOSid/RMID values are cached and the write is performed only when a task with a different CLOSid/RMID is scheduled in.

---
 arch/x86/include/asm/intel_rdt_sched.h | 50 ++++++++++++++++++++--------------
 arch/x86/kernel/cpu/intel_rdt.h        |  4 ---
 2 files changed, 29 insertions(+), 25 deletions(-)
arch/x86/include/asm/intel_rdt_sched.h +29 -21
index 8c5be01..3badc0a 100644
@@ -15,7 +15,8 @@
  *
  * The upper 32 bits of IA32_PQR_ASSOC contain closid and the
  * lower 10 bits rmid. The update to IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
+ * contains both parts, so we need to cache them. This also
+ * stores the user configured per cpu CLOSID and RMID.
  *
  * The cache also helps to avoid pointless updates if the value does
  * not change.
@@ -30,38 +31,45 @@ DECLARE_PER_CPU_READ_MOSTLY(struct intel_pqr_state, rdt_cpu_default);
 
 DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
 DECLARE_STATIC_KEY_FALSE(rdt_alloc_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
 
 /*
- * __intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
+ * __intel_rdt_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR
  *
  * Following considerations are made so that this has minimal impact
  * on scheduler hot path:
  * - This will stay as no-op unless we are running on an Intel SKU
- *   which supports resource control and we enable by mounting the
- *   resctrl file system.
- * - Caches the per cpu CLOSid values and does the MSR write only
- *   when a task with a different CLOSid is scheduled in.
- *
+ *   which supports resource control or monitoring and we enable by
+ *   mounting the resctrl file system.
+ * - Caches the per cpu CLOSid/RMID values and does the MSR write only
+ *   when a task with a different CLOSid/RMID is scheduled in.
+ * - We allocate RMIDs/CLOSids globally in order to keep this as
+ *   simple as possible.
  * Must be called with preemption disabled.
  */
-static inline void __intel_rdt_sched_in(void)
+static void __intel_rdt_sched_in(void)
 {
+	struct intel_pqr_state newstate = this_cpu_read(rdt_cpu_default);
+	struct intel_pqr_state *curstate = this_cpu_ptr(&pqr_state);
+
+	/*
+	 * If this task has a closid/rmid assigned, use it.
+	 * Else use the closid/rmid assigned to this cpu.
+	 */
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
-		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-		u32 closid;
+		if (current->closid)
+			newstate.closid = current->closid;
+	}
 
-		/*
-		 * If this task has a closid assigned, use it.
-		 * Else use the closid assigned to this cpu.
-		 */
-		closid = current->closid;
-		if (closid == 0)
-			closid = this_cpu_read(rdt_cpu_default.closid);
+	if (static_branch_likely(&rdt_mon_enable_key)) {
+		if (current->rmid)
+			newstate.rmid = current->rmid;
+	}
 
-		if (closid != state->closid) {
-			state->closid = closid;
-			wrmsr(IA32_PQR_ASSOC, state->rmid, closid);
-		}
+	if (newstate.closid != curstate->closid ||
+	    newstate.rmid != curstate->rmid) {
+		*curstate = newstate;
+		wrmsr(IA32_PQR_ASSOC, newstate.rmid, newstate.closid);
 	}
 }
 
arch/x86/kernel/cpu/intel_rdt.h +0 -4
index 92a5d30..7fcaa5f 100644
@@ -22,8 +22,6 @@
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
-DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
-
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -61,8 +59,6 @@ extern bool rdt_alloc_capable;
 extern bool rdt_mon_capable;
 extern unsigned int rdt_mon_features;
 
-DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
-
 enum rdt_group_type {
 	RDTCTRL_GROUP = 0,
 	RDTMON_GROUP,
#55 lore raw

PATCH v2 25/28 x86/intel_rdt/cqm: Add hotcpu support

In reply to Vikas Shivappa

Resource groups have a per domain directory under "mon_data". Add or remove these directories as and when domains come online and go offline. Also update the per cpu rmids and cache upon onlining and offlining cpus.

---
 arch/x86/kernel/cpu/intel_rdt.c          | 41 +++++++++++++++++++++++-----
 arch/x86/kernel/cpu/intel_rdt.h          |  9 ++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 47 ++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 7 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +34 -7
index 81d1cd3..83f35e3 100644
@@ -479,6 +479,13 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 
 	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
+
+	/*
+	 * If resctrl is mounted, add
+	 * per domain monitor data directories.
+	 */
+	if (static_branch_unlikely(&rdt_mon_enable_key))
+		mkdir_mondata_subdir_allrdtgrp(r, d);
 }
 
 static void domain_remove_cpu(int cpu, struct rdt_resource *r)
@@ -494,6 +501,12 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 
 	cpumask_clear_cpu(cpu, &d->cpu_mask);
 	if (cpumask_empty(&d->cpu_mask)) {
+		/*
+		 * If resctrl is mounted, remove all the
+		 * per domain monitor data directories.
+		 */
+		if (static_branch_unlikely(&rdt_mon_enable_key))
+			rmdir_mondata_subdir_allrdtgrp(r, d->id);
 		kfree(d->ctrl_val);
 		kfree(d->rmid_busy_llc);
 		list_del(&d->list);
@@ -501,13 +514,14 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 	}
 }
 
-static void clear_closid(int cpu)
+static void clear_closid_rmid(int cpu)
 {
 	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 
 	per_cpu(rdt_cpu_default.closid, cpu) = 0;
 	state->closid = 0;
-	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
+	state->rmid = 0;
+	wrmsr(IA32_PQR_ASSOC, 0, 0);
 }
 
 static int intel_rdt_online_cpu(unsigned int cpu)
@@ -515,29 +529,42 @@ static int intel_rdt_online_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_alloc_capable_rdt_resource(r)
+	for_each_capable_rdt_resource(r)
 		domain_add_cpu(cpu, r);
 	/* The cpu is set in default rdtgroup after online. */
 	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
-	clear_closid(cpu);
+	clear_closid_rmid(cpu);
 	mutex_unlock(&rdtgroup_mutex);
 
 	return 0;
 }
 
+static void clear_childcpus(struct rdtgroup *r, unsigned int cpu)
+{
+	struct rdtgroup *cr;
+
+	list_for_each_entry(cr, &r->mon.crdtgrp_list, mon.crdtgrp_list) {
+		if (cpumask_test_and_clear_cpu(cpu, &cr->cpu_mask)) {
+			break;
+		}
+	}
+}
+
 static int intel_rdt_offline_cpu(unsigned int cpu)
 {
 	struct rdtgroup *rdtgrp;
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_alloc_capable_rdt_resource(r)
+	for_each_capable_rdt_resource(r)
 		domain_remove_cpu(cpu, r);
 	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
-		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
+		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) {
+			clear_childcpus(rdtgrp, cpu);
 			break;
+		}
 	}
-	clear_closid(cpu);
+	clear_closid_rmid(cpu);
 	mutex_unlock(&rdtgroup_mutex);
 
 	return 0;
arch/x86/kernel/cpu/intel_rdt.h +9 -0
index 7fcaa5f..2660d15 100644
@@ -301,6 +301,11 @@ enum {
 	RDT_NUM_RESOURCES,
 };
 
+#define for_each_capable_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++)							      \
+		if (r->alloc_capable || r->mon_capable)
+
 #define for_each_alloc_capable_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
@@ -360,5 +365,9 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 void mon_event_count(void *info);
 int rdtgroup_mondata_show(struct seq_file *m, void *arg);
+void rmdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
+				    unsigned int dom_id);
+void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
+				    struct rdt_domain *d);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +47 -0

59 lines not on this page · raw message

Signature · 1 line
1.9.1
#56 lore raw

[tip:x86/cache] x86/intel_rdt/cqm: Add CPU hotplug support

x86/intel_rdt/cqm: Add CPU hotplug support
Commit-ID:  895c663ecef16c8138e20a7d5c052e0fcc400241
Gitweb:     http://git.kernel.org/tip/895c663ecef16c8138e20a7d5c052e0fcc400241
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:44 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:28 +0200

x86/intel_rdt/cqm: Add CPU hotplug support

Resource groups have a per domain directory under "mon_data". Add or remove these directories as and when domains come online and go offline. Also update the per cpu rmids and cache upon onlining and offlining cpus.

---
 arch/x86/kernel/cpu/intel_rdt.c          | 41 +++++++++++++++++++++++-----
 arch/x86/kernel/cpu/intel_rdt.h          |  9 ++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 47 ++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 7 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +34 -7
index 050ea15..f12bb91 100644
@@ -479,6 +479,13 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 
 	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
+
+	/*
+	 * If resctrl is mounted, add
+	 * per domain monitor data directories.
+	 */
+	if (static_branch_unlikely(&rdt_mon_enable_key))
+		mkdir_mondata_subdir_allrdtgrp(r, d);
 }
 
 static void domain_remove_cpu(int cpu, struct rdt_resource *r)
@@ -494,6 +501,12 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 
 	cpumask_clear_cpu(cpu, &d->cpu_mask);
 	if (cpumask_empty(&d->cpu_mask)) {
+		/*
+		 * If resctrl is mounted, remove all the
+		 * per domain monitor data directories.
+		 */
+		if (static_branch_unlikely(&rdt_mon_enable_key))
+			rmdir_mondata_subdir_allrdtgrp(r, d->id);
 		kfree(d->ctrl_val);
 		kfree(d->rmid_busy_llc);
 		list_del(&d->list);
@@ -501,13 +514,14 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 	}
 }
 
-static void clear_closid(int cpu)
+static void clear_closid_rmid(int cpu)
 {
 	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
 
 	per_cpu(rdt_cpu_default.closid, cpu) = 0;
 	state->closid = 0;
-	wrmsr(IA32_PQR_ASSOC, state->rmid, 0);
+	state->rmid = 0;
+	wrmsr(IA32_PQR_ASSOC, 0, 0);
 }
 
 static int intel_rdt_online_cpu(unsigned int cpu)
@@ -515,29 +529,42 @@ static int intel_rdt_online_cpu(unsigned int cpu)
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_alloc_capable_rdt_resource(r)
+	for_each_capable_rdt_resource(r)
 		domain_add_cpu(cpu, r);
 	/* The cpu is set in default rdtgroup after online. */
 	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
-	clear_closid(cpu);
+	clear_closid_rmid(cpu);
 	mutex_unlock(&rdtgroup_mutex);
 
 	return 0;
 }
 
+static void clear_childcpus(struct rdtgroup *r, unsigned int cpu)
+{
+	struct rdtgroup *cr;
+
+	list_for_each_entry(cr, &r->mon.crdtgrp_list, mon.crdtgrp_list) {
+		if (cpumask_test_and_clear_cpu(cpu, &cr->cpu_mask)) {
+			break;
+		}
+	}
+}
+
 static int intel_rdt_offline_cpu(unsigned int cpu)
 {
 	struct rdtgroup *rdtgrp;
 	struct rdt_resource *r;
 
 	mutex_lock(&rdtgroup_mutex);
-	for_each_alloc_capable_rdt_resource(r)
+	for_each_capable_rdt_resource(r)
 		domain_remove_cpu(cpu, r);
 	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
-		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
+		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) {
+			clear_childcpus(rdtgrp, cpu);
 			break;
+		}
 	}
-	clear_closid(cpu);
+	clear_closid_rmid(cpu);
 	mutex_unlock(&rdtgroup_mutex);
 
 	return 0;
arch/x86/kernel/cpu/intel_rdt.h +9 -0
index 7fcaa5f..2660d15 100644
@@ -301,6 +301,11 @@ enum {
 	RDT_NUM_RESOURCES,
 };
 
+#define for_each_capable_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++)							      \
+		if (r->alloc_capable || r->mon_capable)
+
 #define for_each_alloc_capable_rdt_resource(r)				      \
 	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
 	     r++)							      \
@@ -360,5 +365,9 @@ void free_rmid(u32 rmid);
 int rdt_get_mon_l3_config(struct rdt_resource *r);
 void mon_event_count(void *info);
 int rdtgroup_mondata_show(struct seq_file *m, void *arg);
+void rmdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
+				    unsigned int dom_id);
+void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
+				    struct rdt_domain *d);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +47 -0

59 lines not on this page · raw message

#57 lore raw

PATCH v2 26/28 x86/intel_rdt/mbm: Basic counting of MBM events (total and local)

In reply to Vikas Shivappa

From: Tony Luck <[email protected]>

Check CPUID bits for whether each of the MBM events is supported. Allocate space for each RMID for each counter in each domain to save previous MSR counter value and running total of data. Create files in each of the monitor directories.

---
 arch/x86/kernel/cpu/intel_rdt.c             | 23 +++++++++++++++++++-
 arch/x86/kernel/cpu/intel_rdt.h             | 33 +++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c |  1 +
 arch/x86/kernel/cpu/intel_rdt_monitor.c     | 31 ++++++++++++++++++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +22 -1
index 83f35e3..767b4c3 100644
@@ -420,6 +420,8 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
 
 static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 {
+	size_t tsize;
+
 	if (is_llc_occupancy_enabled()) {
 		d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid),
 					   sizeof(unsigned long),
@@ -427,6 +429,23 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 		if (!d->rmid_busy_llc)
 			return -ENOMEM;
 	}
+	if (is_mbm_total_enabled()) {
+		tsize = sizeof(*d->mbm_total);
+		d->mbm_total = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
+		if (!d->mbm_total) {
+			kfree(d->rmid_busy_llc);
+			return -ENOMEM;
+		}
+	}
+	if (is_mbm_local_enabled()) {
+		tsize = sizeof(*d->mbm_local);
+		d->mbm_local = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
+		if (!d->mbm_local) {
+			kfree(d->rmid_busy_llc);
+			kfree(d->mbm_total);
+			return -ENOMEM;
+		}
+	}
 
 	return 0;
 }
@@ -466,6 +485,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 
 	d->id = id;
+	cpumask_set_cpu(cpu, &d->cpu_mask);
 
 	if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
 		kfree(d);
@@ -477,7 +497,6 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 	}
 
-	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
 
 	/*
@@ -509,6 +528,8 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 			rmdir_mondata_subdir_allrdtgrp(r, d->id);
 		kfree(d->ctrl_val);
 		kfree(d->rmid_busy_llc);
+		kfree(d->mbm_total);
+		kfree(d->mbm_local);
 		list_del(&d->list);
 		kfree(d);
 	}
arch/x86/kernel/cpu/intel_rdt.h +33 -0
index 2660d15..2137d5e 100644
@@ -19,6 +19,9 @@
 #define QOS_L3_OCCUP_EVENT_ID		0x01
 #define QOS_L3_MBM_TOTAL_EVENT_ID	0x02
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
+
+#define MBM_CNTR_WIDTH			24
+
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
@@ -50,6 +53,7 @@ struct mon_evt {
 
 struct rmid_read {
 	struct rdtgroup		*rgrp;
+	struct rdt_domain	*d;
 	int			evtid;
 	u64			val;
 };
@@ -160,12 +164,24 @@ struct rftype {
 };
 
 /**
+ * struct mbm_state - status for each MBM counter in each domain
+ * @chunks:	Total data moved (multiply by rdt_group.mon_scale to get bytes)
+ * @prev_msr	Value of IA32_QM_CTR for this RMID last time we read it
+ */
+struct mbm_state {
+	u64	chunks;
+	u64	prev_msr;
+};
+
+/**
  * struct rdt_domain - group of cpus sharing an RDT resource
  * @list:	all instances of this resource
  * @id:		unique id for this instance
  * @cpu_mask:	which cpus share this resource
  * @rmid_busy_llc:
  *		bitmap of which limbo RMIDs are above threshold
+ * @mbm_total:	saved state for MBM total bandwidth
+ * @mbm_local:	saved state for MBM local bandwidth
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -175,6 +191,8 @@ struct rdt_domain {
 	int			id;
 	struct cpumask		cpu_mask;
 	unsigned long		*rmid_busy_llc;
+	struct mbm_state	*mbm_total;
+	struct mbm_state	*mbm_local;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -230,6 +248,21 @@ static inline bool is_llc_occupancy_enabled(void)
 	return (rdt_mon_features & (1 << QOS_L3_OCCUP_EVENT_ID));
 }
 
+static inline bool is_mbm_total_enabled(void)
+{
+	return (rdt_mon_features & (1 << QOS_L3_MBM_TOTAL_EVENT_ID));
+}
+
+static inline bool is_mbm_local_enabled(void)
+{
+	return (rdt_mon_features & (1 << QOS_L3_MBM_LOCAL_EVENT_ID));
+}
+
+static inline bool is_mbm_enabled(void)
+{
+	return (is_mbm_total_enabled() || is_mbm_local_enabled());
+}
+
 /**
  * struct rdt_resource - attributes of an RDT resource
  * @rid:		The index of the resource
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +1 -0
index f44e77d..cf8e2c7 100644
@@ -294,6 +294,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 	 */
 	rr->rgrp = rdtgrp;
 	rr->evtid = evtid;
+	rr->d = d;
 	rr->val = 0;
 
 	smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
arch/x86/kernel/cpu/intel_rdt_monitor.c +30 -1
index 6ae5cf5..ef0358b 100644
@@ -296,7 +296,8 @@ void free_rmid(u32 rmid)
 
 static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 {
-	u64 tval;
+	u64 chunks, shift, tval;
+	struct mbm_state *m;
 
 	tval = __rmid_read(rmid, rr->evtid);
 	if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
@@ -307,6 +308,12 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 	case QOS_L3_OCCUP_EVENT_ID:
 		rr->val += tval;
 		return 0;
+	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		m = &rr->d->mbm_total[rmid];
+		break;
+	case QOS_L3_MBM_LOCAL_EVENT_ID:
+		m = &rr->d->mbm_local[rmid];
+		break;
 	default:
 		/*
 		 * Code would never reach here because
@@ -314,6 +321,14 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 		 */
 		return -EINVAL;
 	}
+	shift = 64 - MBM_CNTR_WIDTH;
+	chunks = (tval << shift) - (m->prev_msr << shift);
+	chunks >>= shift;
+	m->chunks += chunks;
+	m->prev_msr = tval;
+
+	rr->val += m->chunks;
+	return 0;
 }
 
 /*
@@ -377,6 +392,16 @@ static int dom_data_init(struct rdt_resource *r)
 	.evtid		= QOS_L3_OCCUP_EVENT_ID,
 };
 
+static struct mon_evt mbm_total_event = {
+	.name		= "mbm_total_bytes",
+	.evtid		= QOS_L3_MBM_TOTAL_EVENT_ID,
+};
+
+static struct mon_evt mbm_local_event = {
+	.name		= "mbm_local_bytes",
+	.evtid		= QOS_L3_MBM_LOCAL_EVENT_ID,
+};
+
 /*
  * Initialize the event list for the resource.
  *
@@ -390,6 +415,10 @@ static void l3_mon_evt_init(struct rdt_resource *r)
 
 	if (is_llc_occupancy_enabled())
 		list_add_tail(&llc_occupancy_event.list, &r->evt_list);
+	if (is_mbm_total_enabled())
+		list_add_tail(&mbm_total_event.list, &r->evt_list);
+	if (is_mbm_local_enabled())
+		list_add_tail(&mbm_local_event.list, &r->evt_list);
 }
 
 int rdt_get_mon_l3_config(struct rdt_resource *r)
Signature · 1 line
1.9.1
#58 lore raw

[tip:x86/cache] x86/intel_rdt/mbm: Basic counting of MBM events (total and local)

x86/intel_rdt/mbm: Basic counting of MBM events (total and local)
Commit-ID:  9f52425ba303d91c8370719e91d7e578bfdf309f
Gitweb:     http://git.kernel.org/tip/9f52425ba303d91c8370719e91d7e578bfdf309f
Author:     Tony Luck <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:45 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:28 +0200

x86/intel_rdt/mbm: Basic counting of MBM events (total and local)

Check CPUID bits for whether each of the MBM events is supported. Allocate space for each RMID for each counter in each domain to save previous MSR counter value and running total of data. Create files in each of the monitor directories.

---
 arch/x86/kernel/cpu/intel_rdt.c             | 23 +++++++++++++++++++-
 arch/x86/kernel/cpu/intel_rdt.h             | 33 +++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c |  1 +
 arch/x86/kernel/cpu/intel_rdt_monitor.c     | 31 ++++++++++++++++++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +22 -1
index f12bb91..4c17a70 100644
@@ -420,6 +420,8 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
 
 static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 {
+	size_t tsize;
+
 	if (is_llc_occupancy_enabled()) {
 		d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid),
 					   sizeof(unsigned long),
@@ -427,6 +429,23 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 		if (!d->rmid_busy_llc)
 			return -ENOMEM;
 	}
+	if (is_mbm_total_enabled()) {
+		tsize = sizeof(*d->mbm_total);
+		d->mbm_total = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
+		if (!d->mbm_total) {
+			kfree(d->rmid_busy_llc);
+			return -ENOMEM;
+		}
+	}
+	if (is_mbm_local_enabled()) {
+		tsize = sizeof(*d->mbm_local);
+		d->mbm_local = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
+		if (!d->mbm_local) {
+			kfree(d->rmid_busy_llc);
+			kfree(d->mbm_total);
+			return -ENOMEM;
+		}
+	}
 
 	return 0;
 }
@@ -466,6 +485,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 
 	d->id = id;
+	cpumask_set_cpu(cpu, &d->cpu_mask);
 
 	if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
 		kfree(d);
@@ -477,7 +497,6 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
 		return;
 	}
 
-	cpumask_set_cpu(cpu, &d->cpu_mask);
 	list_add_tail(&d->list, add_pos);
 
 	/*
@@ -509,6 +528,8 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 			rmdir_mondata_subdir_allrdtgrp(r, d->id);
 		kfree(d->ctrl_val);
 		kfree(d->rmid_busy_llc);
+		kfree(d->mbm_total);
+		kfree(d->mbm_local);
 		list_del(&d->list);
 		kfree(d);
 	}
arch/x86/kernel/cpu/intel_rdt.h +33 -0
index 2660d15..2137d5e 100644
@@ -19,6 +19,9 @@
 #define QOS_L3_OCCUP_EVENT_ID		0x01
 #define QOS_L3_MBM_TOTAL_EVENT_ID	0x02
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
+
+#define MBM_CNTR_WIDTH			24
+
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
@@ -50,6 +53,7 @@ union mon_data_bits {
 
 struct rmid_read {
 	struct rdtgroup		*rgrp;
+	struct rdt_domain	*d;
 	int			evtid;
 	u64			val;
 };
@@ -160,12 +164,24 @@ struct rftype {
 };
 
 /**
+ * struct mbm_state - status for each MBM counter in each domain
+ * @chunks:	Total data moved (multiply by rdt_group.mon_scale to get bytes)
+ * @prev_msr	Value of IA32_QM_CTR for this RMID last time we read it
+ */
+struct mbm_state {
+	u64	chunks;
+	u64	prev_msr;
+};
+
+/**
  * struct rdt_domain - group of cpus sharing an RDT resource
  * @list:	all instances of this resource
  * @id:		unique id for this instance
  * @cpu_mask:	which cpus share this resource
  * @rmid_busy_llc:
  *		bitmap of which limbo RMIDs are above threshold
+ * @mbm_total:	saved state for MBM total bandwidth
+ * @mbm_local:	saved state for MBM local bandwidth
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -175,6 +191,8 @@ struct rdt_domain {
 	int			id;
 	struct cpumask		cpu_mask;
 	unsigned long		*rmid_busy_llc;
+	struct mbm_state	*mbm_total;
+	struct mbm_state	*mbm_local;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -230,6 +248,21 @@ static inline bool is_llc_occupancy_enabled(void)
 	return (rdt_mon_features & (1 << QOS_L3_OCCUP_EVENT_ID));
 }
 
+static inline bool is_mbm_total_enabled(void)
+{
+	return (rdt_mon_features & (1 << QOS_L3_MBM_TOTAL_EVENT_ID));
+}
+
+static inline bool is_mbm_local_enabled(void)
+{
+	return (rdt_mon_features & (1 << QOS_L3_MBM_LOCAL_EVENT_ID));
+}
+
+static inline bool is_mbm_enabled(void)
+{
+	return (is_mbm_total_enabled() || is_mbm_local_enabled());
+}
+
 /**
  * struct rdt_resource - attributes of an RDT resource
  * @rid:		The index of the resource
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +1 -0
index f44e77d..cf8e2c7 100644
@@ -294,6 +294,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 	 */
 	rr->rgrp = rdtgrp;
 	rr->evtid = evtid;
+	rr->d = d;
 	rr->val = 0;
 
 	smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
arch/x86/kernel/cpu/intel_rdt_monitor.c +30 -1
index 6ae5cf5..ef0358b 100644
@@ -296,7 +296,8 @@ void free_rmid(u32 rmid)
 
 static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 {
-	u64 tval;
+	u64 chunks, shift, tval;
+	struct mbm_state *m;
 
 	tval = __rmid_read(rmid, rr->evtid);
 	if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
@@ -307,6 +308,12 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 	case QOS_L3_OCCUP_EVENT_ID:
 		rr->val += tval;
 		return 0;
+	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		m = &rr->d->mbm_total[rmid];
+		break;
+	case QOS_L3_MBM_LOCAL_EVENT_ID:
+		m = &rr->d->mbm_local[rmid];
+		break;
 	default:
 		/*
 		 * Code would never reach here because
@@ -314,6 +321,14 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 		 */
 		return -EINVAL;
 	}
+	shift = 64 - MBM_CNTR_WIDTH;
+	chunks = (tval << shift) - (m->prev_msr << shift);
+	chunks >>= shift;
+	m->chunks += chunks;
+	m->prev_msr = tval;
+
+	rr->val += m->chunks;
+	return 0;
 }
 
 /*
@@ -377,6 +392,16 @@ static struct mon_evt llc_occupancy_event = {
 	.evtid		= QOS_L3_OCCUP_EVENT_ID,
 };
 
+static struct mon_evt mbm_total_event = {
+	.name		= "mbm_total_bytes",
+	.evtid		= QOS_L3_MBM_TOTAL_EVENT_ID,
+};
+
+static struct mon_evt mbm_local_event = {
+	.name		= "mbm_local_bytes",
+	.evtid		= QOS_L3_MBM_LOCAL_EVENT_ID,
+};
+
 /*
  * Initialize the event list for the resource.
  *
@@ -390,6 +415,10 @@ static void l3_mon_evt_init(struct rdt_resource *r)
 
 	if (is_llc_occupancy_enabled())
 		list_add_tail(&llc_occupancy_event.list, &r->evt_list);
+	if (is_mbm_total_enabled())
+		list_add_tail(&mbm_total_event.list, &r->evt_list);
+	if (is_mbm_local_enabled())
+		list_add_tail(&mbm_local_event.list, &r->evt_list);
 }
 
 int rdt_get_mon_l3_config(struct rdt_resource *r)
#59 lore raw

PATCH v2 27/28 x86/intel_rdt/mbm: Add mbm counter initialization

In reply to Vikas Shivappa

MBM counters are monotonically increasing counts representing the total memory bytes at a particular time. In order to calculate total_bytes for an rdtgroup, we store the value of the counter when we create an rdtgroup or when a new domain comes online.

When the total_bytes(all memory controller bytes) or local_bytes(local memory controller bytes) file in "mon_data" is read it shows the total bytes for that rdtgroup since its creation. User can snapshot this at different time intervals to obtain bytes/second.

---
 arch/x86/kernel/cpu/intel_rdt.h             | 9 +++++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 5 +++--
 arch/x86/kernel/cpu/intel_rdt_monitor.c     | 7 +++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c    | 4 ++++
 4 files changed, 23 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +9 -0
index 2137d5e..f160403 100644
@@ -55,6 +55,7 @@ struct rmid_read {
 	struct rdtgroup		*rgrp;
 	struct rdt_domain	*d;
 	int			evtid;
+	bool			first;
 	u64			val;
 };
 
@@ -263,6 +264,12 @@ static inline bool is_mbm_enabled(void)
 	return (is_mbm_total_enabled() || is_mbm_local_enabled());
 }
 
+static inline bool is_mbm_event(int e)
+{
+	return (e >= QOS_L3_MBM_TOTAL_EVENT_ID &&
+		e <= QOS_L3_MBM_LOCAL_EVENT_ID);
+}
+
 /**
  * struct rdt_resource - attributes of an RDT resource
  * @rid:		The index of the resource
@@ -402,5 +409,7 @@ void rmdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    unsigned int dom_id);
 void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    struct rdt_domain *d);
+void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
+		    struct rdtgroup *rdtgrp, int evtid, int first);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +3 -2
index cf8e2c7..f6ea94f 100644
@@ -287,7 +287,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 }
 
 void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
-		    struct rdtgroup *rdtgrp, int evtid)
+		    struct rdtgroup *rdtgrp, int evtid, int first)
 {
 	/*
 	 * setup the parameters to send to the IPI to read the data.
@@ -296,6 +296,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 	rr->evtid = evtid;
 	rr->d = d;
 	rr->val = 0;
+	rr->first = first;
 
 	smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
 }
@@ -325,7 +326,7 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
 		goto out;
 	}
 
-	mon_event_read(&rr, d, rdtgrp, evtid);
+	mon_event_read(&rr, d, rdtgrp, evtid, false);
 
 	if (rr.val & RMID_VAL_ERROR)
 		seq_puts(m, "Error\n");
arch/x86/kernel/cpu/intel_rdt_monitor.c +7 -0
index ef0358b..383a023 100644
@@ -321,6 +321,13 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 		 */
 		return -EINVAL;
 	}
+
+	if (rr->first) {
+		m->prev_msr = tval;
+		m->chunks = 0;
+		return 0;
+	}
+
 	shift = 64 - MBM_CNTR_WIDTH;
 	chunks = (tval << shift) - (m->prev_msr << shift);
 	chunks >>= shift;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +4 -0
index 90a22d3..50b5d03 100644
@@ -1352,6 +1352,7 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
 	union mon_data_bits priv;
 	struct kernfs_node *kn;
 	struct mon_evt *mevt;
+	struct rmid_read rr;
 	char name[32];
 	int ret;
 
@@ -1382,6 +1383,9 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
 		ret = mon_addfile(kn, mevt->name, priv.priv);
 		if (ret)
 			goto out_destroy;
+
+		if (is_mbm_event(mevt->evtid))
+			mon_event_read(&rr, d, prgrp, mevt->evtid, true);
 	}
 	kernfs_activate(kn);
 	return 0;
Signature · 1 line
1.9.1
#60 lore raw

[tip:x86/cache] x86/intel_rdt/mbm: Add mbm counter initialization

x86/intel_rdt/mbm: Add mbm counter initialization
Commit-ID:  a4de1dfdd726537e2a78b55759fc646d9b0a0be8
Gitweb:     http://git.kernel.org/tip/a4de1dfdd726537e2a78b55759fc646d9b0a0be8
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:46 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:29 +0200

x86/intel_rdt/mbm: Add mbm counter initialization

MBM counters are monotonically increasing counts representing the total memory bytes at a particular time. In order to calculate total_bytes for an rdtgroup, we store the value of the counter when we create an rdtgroup or when a new domain comes online.

When the total_bytes(all memory controller bytes) or local_bytes(local memory controller bytes) file in "mon_data" is read it shows the total bytes for that rdtgroup since its creation. User can snapshot this at different time intervals to obtain bytes/second.

---
 arch/x86/kernel/cpu/intel_rdt.h             | 9 +++++++++
 arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 5 +++--
 arch/x86/kernel/cpu/intel_rdt_monitor.c     | 7 +++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c    | 4 ++++
 4 files changed, 23 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/intel_rdt.h +9 -0
index 2137d5e..f160403 100644
@@ -55,6 +55,7 @@ struct rmid_read {
 	struct rdtgroup		*rgrp;
 	struct rdt_domain	*d;
 	int			evtid;
+	bool			first;
 	u64			val;
 };
 
@@ -263,6 +264,12 @@ static inline bool is_mbm_enabled(void)
 	return (is_mbm_total_enabled() || is_mbm_local_enabled());
 }
 
+static inline bool is_mbm_event(int e)
+{
+	return (e >= QOS_L3_MBM_TOTAL_EVENT_ID &&
+		e <= QOS_L3_MBM_LOCAL_EVENT_ID);
+}
+
 /**
  * struct rdt_resource - attributes of an RDT resource
  * @rid:		The index of the resource
@@ -402,5 +409,7 @@ void rmdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    unsigned int dom_id);
 void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    struct rdt_domain *d);
+void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
+		    struct rdtgroup *rdtgrp, int evtid, int first);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +3 -2
index cf8e2c7..f6ea94f 100644
@@ -287,7 +287,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
 }
 
 void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
-		    struct rdtgroup *rdtgrp, int evtid)
+		    struct rdtgroup *rdtgrp, int evtid, int first)
 {
 	/*
 	 * setup the parameters to send to the IPI to read the data.
@@ -296,6 +296,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 	rr->evtid = evtid;
 	rr->d = d;
 	rr->val = 0;
+	rr->first = first;
 
 	smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
 }
@@ -325,7 +326,7 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
 		goto out;
 	}
 
-	mon_event_read(&rr, d, rdtgrp, evtid);
+	mon_event_read(&rr, d, rdtgrp, evtid, false);
 
 	if (rr.val & RMID_VAL_ERROR)
 		seq_puts(m, "Error\n");
arch/x86/kernel/cpu/intel_rdt_monitor.c +7 -0
index ef0358b..383a023 100644
@@ -321,6 +321,13 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
 		 */
 		return -EINVAL;
 	}
+
+	if (rr->first) {
+		m->prev_msr = tval;
+		m->chunks = 0;
+		return 0;
+	}
+
 	shift = 64 - MBM_CNTR_WIDTH;
 	chunks = (tval << shift) - (m->prev_msr << shift);
 	chunks >>= shift;
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +4 -0
index ea37b97..05088e3 100644
@@ -1351,6 +1351,7 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
 	union mon_data_bits priv;
 	struct kernfs_node *kn;
 	struct mon_evt *mevt;
+	struct rmid_read rr;
 	char name[32];
 	int ret;
 
@@ -1381,6 +1382,9 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
 		ret = mon_addfile(kn, mevt->name, priv.priv);
 		if (ret)
 			goto out_destroy;
+
+		if (is_mbm_event(mevt->evtid))
+			mon_event_read(&rr, d, prgrp, mevt->evtid, true);
 	}
 	kernfs_activate(kn);
 	return 0;
#61 lore raw

PATCH v2 28/28 x86/intel_rdt/mbm: Handle counter overflow

In reply to Vikas Shivappa

Set up a delayed work queue for each domain that will read all the MBM counters of active RMIDs once per second to make sure that they don't wrap around between reads from users.

[Tony: Added the initializations for the work structure and completed the patch]

---
 arch/x86/kernel/cpu/intel_rdt.c          | 21 ++++++++---
 arch/x86/kernel/cpu/intel_rdt.h          | 10 +++++
 arch/x86/kernel/cpu/intel_rdt_monitor.c  | 63 ++++++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c |  9 +++++
 4 files changed, 97 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +15 -6
index 767b4c3..b906e0e 100644
@@ -348,12 +348,10 @@ void rdt_ctrl_update(void *arg)
 	int cpu = smp_processor_id();
 	struct rdt_domain *d;
 
-	list_for_each_entry(d, &r->domains, list) {
-		/* Find the domain that contains this CPU */
-		if (cpumask_test_cpu(cpu, &d->cpu_mask)) {
-			r->msr_update(d, m, r);
-			return;
-		}
+	d = get_domain_from_cpu(cpu, r);
+	if (d) {
+		r->msr_update(d, m, r);
+		return;
 	}
 	pr_warn_once("cpu %d not found in any domain for resource %s\n",
 		     cpu, r->name);
@@ -447,6 +445,11 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 		}
 	}
 
+	if (is_mbm_enabled()) {
+		INIT_DELAYED_WORK(&d->mbm_over, mbm_handle_overflow);
+		mbm_setup_overflow_handler(d);
+	}
+
 	return 0;
 }
 
@@ -531,7 +534,13 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 		kfree(d->mbm_total);
 		kfree(d->mbm_local);
 		list_del(&d->list);
+		if (is_mbm_enabled())
+			cancel_delayed_work(&d->mbm_over);
 		kfree(d);
+	} else if (r == &rdt_resources_all[RDT_RESOURCE_L3] &&
+		   cpu == d->mbm_work_cpu && is_mbm_enabled()) {
+		cancel_delayed_work(&d->mbm_over);
+		mbm_setup_overflow_handler(d);
 	}
 }
 
arch/x86/kernel/cpu/intel_rdt.h +10 -0
index f160403..94e488a 100644
@@ -21,10 +21,13 @@
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
 
 #define MBM_CNTR_WIDTH			24
+#define MBM_OVERFLOW_INTERVAL		1000
 
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -183,6 +186,9 @@ struct mbm_state {
  *		bitmap of which limbo RMIDs are above threshold
  * @mbm_total:	saved state for MBM total bandwidth
  * @mbm_local:	saved state for MBM local bandwidth
+ * @mbm_over:	worker to periodically read MBM h/w counters
+ * @mbm_work_cpu:
+ *		worker cpu for MBM h/w counters
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -194,6 +200,8 @@ struct rdt_domain {
 	unsigned long		*rmid_busy_llc;
 	struct mbm_state	*mbm_total;
 	struct mbm_state	*mbm_local;
+	struct delayed_work	mbm_over;
+	int			mbm_work_cpu;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -411,5 +419,7 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    struct rdt_domain *d);
 void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 		    struct rdtgroup *rdtgrp, int evtid, int first);
+void mbm_setup_overflow_handler(struct rdt_domain *dom);
+void mbm_handle_overflow(struct work_struct *work);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +63 -0

69 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +9 -0
index 50b5d03..8266ef6 100644
@@ -1061,6 +1061,8 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 				int flags, const char *unused_dev_name,
 				void *data)
 {
+	struct rdt_domain *dom;
+	struct rdt_resource *r;
 	struct dentry *dentry;
 	int ret;
 
@@ -1119,6 +1121,13 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 
 	if (rdt_alloc_capable || rdt_mon_capable)
 		static_branch_enable(&rdt_enable_key);
+
+	if (is_mbm_enabled()) {
+		r = &rdt_resources_all[RDT_RESOURCE_L3];
+		list_for_each_entry(dom, &r->domains, list)
+			mbm_setup_overflow_handler(dom);
+	}
+
 	goto out;
 
 out_mondata:
Signature · 1 line
1.9.1
#62 lore raw

[tip:x86/cache] x86/intel_rdt/mbm: Handle counter overflow

x86/intel_rdt/mbm: Handle counter overflow
Commit-ID:  e33026831bdb5f051499fec6a606f79fe1f94cc8
Gitweb:     http://git.kernel.org/tip/e33026831bdb5f051499fec6a606f79fe1f94cc8
Author:     Vikas Shivappa <[email protected]>
AuthorDate: Tue, 25 Jul 2017 14:14:47 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:29 +0200

x86/intel_rdt/mbm: Handle counter overflow

Set up a delayed work queue for each domain that will read all the MBM counters of active RMIDs once per second to make sure that they don't wrap around between reads from users.

[Tony: Added the initializations for the work structure and completed the patch]

---
 arch/x86/kernel/cpu/intel_rdt.c          | 21 ++++++++---
 arch/x86/kernel/cpu/intel_rdt.h          | 10 +++++
 arch/x86/kernel/cpu/intel_rdt_monitor.c  | 63 ++++++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c |  9 +++++
 4 files changed, 97 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/intel_rdt.c +15 -6
index 4c17a70..de26aa7 100644
@@ -348,12 +348,10 @@ void rdt_ctrl_update(void *arg)
 	int cpu = smp_processor_id();
 	struct rdt_domain *d;
 
-	list_for_each_entry(d, &r->domains, list) {
-		/* Find the domain that contains this CPU */
-		if (cpumask_test_cpu(cpu, &d->cpu_mask)) {
-			r->msr_update(d, m, r);
-			return;
-		}
+	d = get_domain_from_cpu(cpu, r);
+	if (d) {
+		r->msr_update(d, m, r);
+		return;
 	}
 	pr_warn_once("cpu %d not found in any domain for resource %s\n",
 		     cpu, r->name);
@@ -447,6 +445,11 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
 		}
 	}
 
+	if (is_mbm_enabled()) {
+		INIT_DELAYED_WORK(&d->mbm_over, mbm_handle_overflow);
+		mbm_setup_overflow_handler(d);
+	}
+
 	return 0;
 }
 
@@ -531,7 +534,13 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
 		kfree(d->mbm_total);
 		kfree(d->mbm_local);
 		list_del(&d->list);
+		if (is_mbm_enabled())
+			cancel_delayed_work(&d->mbm_over);
 		kfree(d);
+	} else if (r == &rdt_resources_all[RDT_RESOURCE_L3] &&
+		   cpu == d->mbm_work_cpu && is_mbm_enabled()) {
+		cancel_delayed_work(&d->mbm_over);
+		mbm_setup_overflow_handler(d);
 	}
 }
 
arch/x86/kernel/cpu/intel_rdt.h +10 -0
index f160403..94e488a 100644
@@ -21,10 +21,13 @@
 #define QOS_L3_MBM_LOCAL_EVENT_ID	0x03
 
 #define MBM_CNTR_WIDTH			24
+#define MBM_OVERFLOW_INTERVAL		1000
 
 #define RMID_VAL_ERROR			BIT_ULL(63)
 #define RMID_VAL_UNAVAIL		BIT_ULL(62)
 
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+
 /**
  * struct mon_evt - Entry in the event list of a resource
  * @evtid:		event id
@@ -183,6 +186,9 @@ struct mbm_state {
  *		bitmap of which limbo RMIDs are above threshold
  * @mbm_total:	saved state for MBM total bandwidth
  * @mbm_local:	saved state for MBM local bandwidth
+ * @mbm_over:	worker to periodically read MBM h/w counters
+ * @mbm_work_cpu:
+ *		worker cpu for MBM h/w counters
  * @ctrl_val:	array of cache or mem ctrl values (indexed by CLOSID)
  * @new_ctrl:	new ctrl value to be loaded
  * @have_new_ctrl: did user provide new_ctrl for this domain
@@ -194,6 +200,8 @@ struct rdt_domain {
 	unsigned long		*rmid_busy_llc;
 	struct mbm_state	*mbm_total;
 	struct mbm_state	*mbm_local;
+	struct delayed_work	mbm_over;
+	int			mbm_work_cpu;
 	u32			*ctrl_val;
 	u32			new_ctrl;
 	bool			have_new_ctrl;
@@ -411,5 +419,7 @@ void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
 				    struct rdt_domain *d);
 void mon_event_read(struct rmid_read *rr, struct rdt_domain *d,
 		    struct rdtgroup *rdtgrp, int evtid, int first);
+void mbm_setup_overflow_handler(struct rdt_domain *dom);
+void mbm_handle_overflow(struct work_struct *work);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
arch/x86/kernel/cpu/intel_rdt_monitor.c +63 -0

69 lines not on this page · raw message

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +9 -0
index 05088e3..c24dd06 100644
@@ -1060,6 +1060,8 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 				int flags, const char *unused_dev_name,
 				void *data)
 {
+	struct rdt_domain *dom;
+	struct rdt_resource *r;
 	struct dentry *dentry;
 	int ret;
 
@@ -1118,6 +1120,13 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
 
 	if (rdt_alloc_capable || rdt_mon_capable)
 		static_branch_enable(&rdt_enable_key);
+
+	if (is_mbm_enabled()) {
+		r = &rdt_resources_all[RDT_RESOURCE_L3];
+		list_for_each_entry(dom, &r->domains, list)
+			mbm_setup_overflow_handler(dom);
+	}
+
 	goto out;
 
 out_mondata:
#63 lore raw

PATCH 1/1 x86/intel_rdt: Show bitmask of shareable resource with other executing units

In reply to Vikas Shivappa

From: Fenghua Yu <[email protected]>

CPUID.(EAX=0x10, ECX=res#):EBX[31:0] reports a bit mask for a resource. Each set bit within the length of the CBM indicates the corresponding unit of the resource allocation may be used by other entities in the platform (e.g. an integrated graphics engine or hardware units outside the processor core and have direct access to the resource). Each cleared bit within the length of the CBM indicates the corresponding allocation unit can be configured to implement a priority-based allocation scheme without interference with other hardware agents in the system. Bits outside the length of the CBM are reserved.

More details on the bit mask are described in x86 Software Developer's Manual.

The bitmask is shown in "info" directory for each resource. It's up to user to decide how to use the bitmask within a CBM in a partition to share or isolate a resource with other executing units.

---

[This is the "patch from Reinette" mentioned in part 00/28 of the series
to add RDT monitoring "Cqm3 patch series"). It's been sitting around here for a while, but isn't really a part of that series, just a general improvement to RDT/CAT. Applies on top of the 28 parts because it uses the new structure names and methods to create a file in RDT directories]

 Documentation/x86/intel_rdt_ui.txt       |  7 +++++++
 arch/x86/kernel/cpu/intel_rdt.c          |  2 ++
 arch/x86/kernel/cpu/intel_rdt.h          |  3 +++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 16 ++++++++++++++++
 4 files changed, 28 insertions(+)
Documentation/x86/intel_rdt_ui.txt +7 -0
index 76f21e2ac176..4d8848e4e224 100644
@@ -48,6 +48,13 @@ related to allocation:
 "min_cbm_bits": 	The minimum number of consecutive bits which
 			must be set when writing a mask.
 
+"shareable_bits":	Bitmask of shareable resource with other executing
+			entities (e.g. I/O). User can use this when
+			setting up exclusive cache partitions. Note that
+			some platforms support devices that have their
+			own settings for cache use which can over-ride
+			these bits.
+
 Memory bandwitdh(MB) subdirectory contains the following files
 with respect to allocation:
 
arch/x86/kernel/cpu/intel_rdt.c +2 -0
index b906e0e3eb57..91917c18a8c2 100644
@@ -193,6 +193,7 @@ static inline bool cache_alloc_hsw_probe(void)
 		r->num_closid = 4;
 		r->default_ctrl = max_cbm;
 		r->cache.cbm_len = 20;
+		r->cache.shareable_bits = 0xc0000;
 		r->cache.min_cbm_bits = 2;
 		r->alloc_capable = true;
 		r->alloc_enabled = true;
@@ -260,6 +261,7 @@ static void rdt_get_cache_alloc_config(int idx, struct rdt_resource *r)
 	r->num_closid = edx.split.cos_max + 1;
 	r->cache.cbm_len = eax.split.cbm_len + 1;
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
+	r->cache.shareable_bits = ebx & r->default_ctrl;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
arch/x86/kernel/cpu/intel_rdt.h +3 -0
index 94e488af082e..4040bf1a075c 100644
@@ -227,12 +227,15 @@ struct msr_param {
  * @cbm_idx_offset:	Offset of CBM index. CBM index is computed by:
  *			closid * cbm_idx_multi + cbm_idx_offset
  *			in a cache bit mask
+ * @shareable_bits:	Bitmask of shareable resource with other
+ *			executing entities
  */
 struct rdt_cache {
 	unsigned int	cbm_len;
 	unsigned int	min_cbm_bits;
 	unsigned int	cbm_idx_mult;
 	unsigned int	cbm_idx_offset;
+	unsigned int	shareable_bits;
 };
 
 /**
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +16 -0
index 8266ef61dd99..83c126be83bf 100644
@@ -596,6 +596,15 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of,
 	return 0;
 }
 
+static int rdt_shareable_bits_show(struct kernfs_open_file *of,
+				   struct seq_file *seq, void *v)
+{
+	struct rdt_resource *r = of->kn->parent->priv;
+
+	seq_printf(seq, "%x\n", r->cache.shareable_bits);
+	return 0;
+}
+
 static int rdt_min_bw_show(struct kernfs_open_file *of,
 			     struct seq_file *seq, void *v)
 {
@@ -712,6 +721,13 @@ static struct rftype res_common_files[] = {
 		.fflags		= RF_CTRL_INFO | RFTYPE_RES_CACHE,
 	},
 	{
+		.name		= "shareable_bits",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdt_shareable_bits_show,
+		.fflags		= RF_CTRL_INFO | RFTYPE_RES_CACHE,
+	},
+	{
 		.name		= "min_bandwidth",
 		.mode		= 0444,
 		.kf_ops		= &rdtgroup_kf_single_ops,
Signature · 1 line
2.11.0
#64 lore raw

[tip:x86/cache] x86/intel_rdt: Show bitmask of shareable resource with other executing units

x86/intel_rdt: Show bitmask of shareable resource with other executing units
Commit-ID:  0dd2d7494cd818d06a2ae1cd840cd62124a2d25e
Gitweb:     http://git.kernel.org/tip/0dd2d7494cd818d06a2ae1cd840cd62124a2d25e
Author:     Fenghua Yu <[email protected]>
AuthorDate: Tue, 25 Jul 2017 15:39:04 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Tue, 1 Aug 2017 22:41:30 +0200

x86/intel_rdt: Show bitmask of shareable resource with other executing units

CPUID.(EAX=0x10, ECX=res#):EBX[31:0] reports a bit mask for a resource. Each set bit within the length of the CBM indicates the corresponding unit of the resource allocation may be used by other entities in the platform (e.g. an integrated graphics engine or hardware units outside the processor core and have direct access to the resource). Each cleared bit within the length of the CBM indicates the corresponding allocation unit can be configured to implement a priority-based allocation scheme without interference with other hardware agents in the system. Bits outside the length of the CBM are reserved.

More details on the bit mask are described in x86 Software Developer's Manual.

The bitmask is shown in "info" directory for each resource. It's up to user to decide how to use the bitmask within a CBM in a partition to share or isolate a resource with other executing units.

---
 Documentation/x86/intel_rdt_ui.txt       |  7 +++++++
 arch/x86/kernel/cpu/intel_rdt.c          |  2 ++
 arch/x86/kernel/cpu/intel_rdt.h          |  3 +++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 16 ++++++++++++++++
 4 files changed, 28 insertions(+)
Documentation/x86/intel_rdt_ui.txt +7 -0
index 76f21e2..4d8848e 100644
@@ -48,6 +48,13 @@ related to allocation:
 "min_cbm_bits": 	The minimum number of consecutive bits which
 			must be set when writing a mask.
 
+"shareable_bits":	Bitmask of shareable resource with other executing
+			entities (e.g. I/O). User can use this when
+			setting up exclusive cache partitions. Note that
+			some platforms support devices that have their
+			own settings for cache use which can over-ride
+			these bits.
+
 Memory bandwitdh(MB) subdirectory contains the following files
 with respect to allocation:
 
arch/x86/kernel/cpu/intel_rdt.c +2 -0
index de26aa7..da4f389 100644
@@ -193,6 +193,7 @@ static inline bool cache_alloc_hsw_probe(void)
 		r->num_closid = 4;
 		r->default_ctrl = max_cbm;
 		r->cache.cbm_len = 20;
+		r->cache.shareable_bits = 0xc0000;
 		r->cache.min_cbm_bits = 2;
 		r->alloc_capable = true;
 		r->alloc_enabled = true;
@@ -260,6 +261,7 @@ static void rdt_get_cache_alloc_cfg(int idx, struct rdt_resource *r)
 	r->num_closid = edx.split.cos_max + 1;
 	r->cache.cbm_len = eax.split.cbm_len + 1;
 	r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
+	r->cache.shareable_bits = ebx & r->default_ctrl;
 	r->data_width = (r->cache.cbm_len + 3) / 4;
 	r->alloc_capable = true;
 	r->alloc_enabled = true;
arch/x86/kernel/cpu/intel_rdt.h +3 -0
index 94e488a..4040bf1 100644
@@ -227,12 +227,15 @@ struct msr_param {
  * @cbm_idx_offset:	Offset of CBM index. CBM index is computed by:
  *			closid * cbm_idx_multi + cbm_idx_offset
  *			in a cache bit mask
+ * @shareable_bits:	Bitmask of shareable resource with other
+ *			executing entities
  */
 struct rdt_cache {
 	unsigned int	cbm_len;
 	unsigned int	min_cbm_bits;
 	unsigned int	cbm_idx_mult;
 	unsigned int	cbm_idx_offset;
+	unsigned int	shareable_bits;
 };
 
 /**
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +16 -0
index c24dd06..2621ae3 100644
@@ -596,6 +596,15 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of,
 	return 0;
 }
 
+static int rdt_shareable_bits_show(struct kernfs_open_file *of,
+				   struct seq_file *seq, void *v)
+{
+	struct rdt_resource *r = of->kn->parent->priv;
+
+	seq_printf(seq, "%x\n", r->cache.shareable_bits);
+	return 0;
+}
+
 static int rdt_min_bw_show(struct kernfs_open_file *of,
 			     struct seq_file *seq, void *v)
 {
@@ -712,6 +721,13 @@ static struct rftype res_common_files[] = {
 		.fflags		= RF_CTRL_INFO | RFTYPE_RES_CACHE,
 	},
 	{
+		.name		= "shareable_bits",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdt_shareable_bits_show,
+		.fflags		= RF_CTRL_INFO | RFTYPE_RES_CACHE,
+	},
+	{
 		.name		= "min_bandwidth",
 		.mode		= 0444,
 		.kf_ops		= &rdtgroup_kf_single_ops,
#65 lore raw

RFC PATCH 1/1 Add "-f" and "-F" flags to watch a "/sys? style file (single number)

In reply to Vikas Shivappa

From: Tony Luck <[email protected]>

-f shows absolute value from the file each time. -F shows the delta
---

This is a proof-of-concept patch to show how "perf" might be extended to use the new RDT file system monitoring files. "-f" is useful for the llc_occupancy "-F" for the MBM files.

 tools/perf/builtin-c2c.c       |  2 ++
 tools/perf/builtin-mem.c       |  2 ++
 tools/perf/builtin-record.c    |  4 ++++
 tools/perf/builtin-stat.c      |  4 ++++
 tools/perf/builtin-top.c       |  4 ++++
 tools/perf/builtin-trace.c     |  4 ++++
 tools/perf/util/evsel.c        | 22 ++++++++++++++++++++++
 tools/perf/util/evsel.h        |  1 +
 tools/perf/util/parse-events.c | 17 +++++++++++++++++
 tools/perf/util/parse-events.h |  1 +
 10 files changed, 61 insertions(+)
tools/perf/builtin-c2c.c +2 -0
index 475999e48f66..094b84d34f7b 100644
@@ -2692,6 +2692,8 @@ static int perf_c2c__record(int argc, const char **argv)
 	OPT_CALLBACK('e', "event", &event_set, "event",
 		     "event selector. Use 'perf mem record -e list' to list available events",
 		     parse_record_events),
+	OPT_CALLBACK('f', "file", &event_set, "file", "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &event_set, "file", "delta file selector", parse_files_option),
 	OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
 	OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
 	OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
tools/perf/builtin-mem.c +2 -0
index e001c0290793..86a332dd30cc 100644
@@ -72,6 +72,8 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
 	OPT_CALLBACK('e', "event", &mem, "event",
 		     "event selector. use 'perf mem record -e list' to list available events",
 		     parse_record_events),
+	OPT_CALLBACK('f', "file", &mem, "file", "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &mem, "file", "delta file selector", parse_files_option),
 	OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"),
 	OPT_INCR('v', "verbose", &verbose,
 		 "be more verbose (show counter open errors, etc)"),
tools/perf/builtin-record.c +4 -0
index 17a14bcce34a..096a7b22f897 100644
@@ -1551,6 +1551,10 @@ static struct option __record_options[] = {
 	OPT_CALLBACK('e', "event", &record.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
+	OPT_CALLBACK('f', "file", &record.evlist, "file",
+		     "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &record.evlist, "file",
+		     "delta file selector", parse_files_option),
 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
 		     "event filter", parse_filter),
 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
tools/perf/builtin-stat.c +4 -0
index 48ac53b199fc..c5da65d0acce 100644
@@ -1736,6 +1736,10 @@ static const struct option stat_options[] = {
 	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
+	OPT_CALLBACK('f', "file", &evsel_list, "file",
+		     "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &evsel_list, "file",
+		     "delta file selector", parse_files_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
tools/perf/builtin-top.c +4 -0
index 6052376634c0..ded5a9e35c6b 100644
@@ -1104,6 +1104,10 @@ int cmd_top(int argc, const char **argv)
 	OPT_CALLBACK('e', "event", &top.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
+	OPT_CALLBACK('f', "file", &top.evlist, "file",
+		     "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &top.evlist, "file",
+		     "delta file selector", parse_files_option),
 	OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
 	OPT_STRING('p', "pid", &target->pid, "pid",
 		    "profile events on existing process id"),
tools/perf/builtin-trace.c +4 -0
index 4b2a5d298197..b404ebc829bc 100644
@@ -2862,6 +2862,10 @@ int cmd_trace(int argc, const char **argv)
 	OPT_CALLBACK('e', "event", &trace, "event",
 		     "event/syscall selector. use 'perf list' to list available events",
 		     trace__parse_events_option),
+	OPT_CALLBACK('f', "file", &evsel_list, "file",
+		     "file selector", parse_files_option),
+	OPT_CALLBACK('F', "file", &evsel_list, "file",
+		     "delta file selector", parse_files_option),
 	OPT_BOOLEAN(0, "comm", &trace.show_comm,
 		    "show the thread COMM next to its id"),
 	OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
tools/perf/util/evsel.c +22 -0
index 413f74df08de..3353571a5c7e 100644
@@ -1256,6 +1256,21 @@ void perf_counts_values__scale(struct perf_counts_values *count,
 		*pscaled = scaled;
 }
 
+static int read_sys_file(int fd, struct perf_counts_values *count)
+{
+	char buf[100];
+	int n;
+	static u64 fake;
+
+	n = pread(fd, buf, sizeof buf, 0);
+	if (n >= 0) {
+		count->val = n ? strtol(buf, NULL, 0) : 0;
+		count->ena = count->run = ++fake;
+		return 0;
+	} else
+		return -errno;
+}
+
 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 		     struct perf_counts_values *count)
 {
@@ -1264,6 +1279,8 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 	if (FD(evsel, cpu, thread) < 0)
 		return -EINVAL;
 
+	if (evsel->sysfile)
+		return read_sys_file(FD(evsel, cpu, thread), count);
 	if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0)
 		return -errno;
 
@@ -1556,6 +1573,11 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 		fprintf(stderr, "%.60s\n", graph_dotted_line);
 	}
 
+	if (evsel->sysfile) {
+		FD(evsel, 0, 0) = open(evsel->name, O_RDONLY, 0);
+		return 0;
+	}
+
 	for (cpu = 0; cpu < cpus->nr; cpu++) {
 
 		for (thread = 0; thread < nthreads; thread++) {
tools/perf/util/evsel.h +1 -0
index d101695c482c..ede30e111947 100644
@@ -121,6 +121,7 @@ struct perf_evsel {
 	bool			per_pkg;
 	bool			precise_max;
 	bool			ignore_missing_thread;
+	bool			sysfile;
 	/* parse modifier helper */
 	int			exclude_GH;
 	int			nr_members;
tools/perf/util/parse-events.c +17 -0
index 01e779b91c8e..0d725eda476d 100644
@@ -1793,6 +1793,23 @@ int parse_events_option(const struct option *opt, const char *str,
 	return ret;
 }
 
+int parse_files_option(const struct option *opt, const char *str,
+		       int unset __maybe_unused)
+{
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+	struct perf_evsel *evsel = calloc(1, sizeof (*evsel));
+
+	evsel->name = strdup(str);
+	evsel->unit = "";
+	evsel->sysfile = true;
+	evsel->snapshot = (opt->short_name == 'f');
+	evsel->scale = 1.0;
+	INIT_LIST_HEAD(&evsel->config_terms);
+	evsel->bpf_fd = -1;
+	perf_evlist__add(evlist, evsel);
+	return 0;
+}
+
 static int
 foreach_evsel_in_last_glob(struct perf_evlist *evlist,
 			   int (*func)(struct perf_evsel *evsel,
tools/perf/util/parse-events.h +1 -0
index a235f4d6d5e5..7e14a4c66fad 100644
@@ -30,6 +30,7 @@ bool have_tracepoints(struct list_head *evlist);
 const char *event_type(int type);
 
 int parse_events_option(const struct option *opt, const char *str, int unset);
+int parse_files_option(const struct option *opt, const char *str, int unset);
 int parse_events(struct perf_evlist *evlist, const char *str,
 		 struct parse_events_error *error);
 int parse_events_terms(struct list_head *terms, const char *str);
Signature · 1 line
2.11.0
#66 lore raw
In reply to Vikas Shivappa
Quoted 5 lines · Vikas Shivappa

Sending the V2 series to address all the feedback that was received in V1. Apart from that this series adds a patch from Reinette to fix a global declaration in existing RDT and also fixes some issues where the prq MSR was not updated when masks or tasks were moved in some cases and some cleanups.

I merged that pile (after fixing the compiler warnings - SIGH) with the proviso that

- the cache line issue vs. the default and current pqr state gets resolved

- the worst case latency problem with the smp function call gets addressed

I decided to merge it now so it gets exposure in next, as I'm going to vanish for my usual summer camp activity for the next 10 days and I don't want to do that huge thing as a last minute merge post rc5.

Upstream merging into 4.14 depends on the resolution of the open issues.

Thanks,

tglx

#67 lore raw

Hello Thomas,

Quoted 13 lines · Thomas Gleixner
Quoted 5 lines · Vikas Shivappa

Sending the V2 series to address all the feedback that was received in V1. Apart from that this series adds a patch from Reinette to fix a global declaration in existing RDT and also fixes some issues where the prq MSR was not updated when masks or tasks were moved in some cases and some cleanups.

I merged that pile (after fixing the compiler warnings - SIGH) with the proviso that

- the cache line issue vs. the default and current pqr state gets resolved

Quoted 7 lines

- the worst case latency problem with the smp function call gets addressed

I decided to merge it now so it gets exposure in next, as I'm going to vanish for my usual summer camp activity for the next 10 days and I don't want to do that huge thing as a last minute merge post rc5.

Upstream merging into 4.14 depends on the resolution of the open issues.

Thanks for all the feedback. Will send a patch on top of tip for open issues.

Vikas

Quoted 7 lines

Thanks,

tglx