lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 29 Oct 2016 17:38:06 -0700
From:   David Carrillo-Cisneros <davidcc@...gle.com>
To:     linux-kernel@...r.kernel.org
Cc:     "x86@...nel.org" <x86@...nel.org>, Ingo Molnar <mingo@...hat.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Andi Kleen <ak@...ux.intel.com>,
        Kan Liang <kan.liang@...el.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Vegard Nossum <vegard.nossum@...il.com>,
        Marcelo Tosatti <mtosatti@...hat.com>,
        Nilay Vaish <nilayvaish@...il.com>,
        Borislav Petkov <bp@...e.de>,
        Vikas Shivappa <vikas.shivappa@...ux.intel.com>,
        Ravi V Shankar <ravi.v.shankar@...el.com>,
        Fenghua Yu <fenghua.yu@...el.com>,
        Paul Turner <pjt@...gle.com>,
        Stephane Eranian <eranian@...gle.com>,
        David Carrillo-Cisneros <davidcc@...gle.com>
Subject: [PATCH v3 09/46] perf/x86/intel/cmt: add basic monr hierarchy

Add root for monr hierarchy and auxiliary functions for locking.

Also, add support for attaching CPU and tasks events to monr hierarchy.
As of this patch, both types of events always use the root monr (this
will change when cgroups are introduced later in this series).

More details in code's comments.

Signed-off-by: David Carrillo-Cisneros <davidcc@...gle.com>
---
 arch/x86/events/intel/cmt.c | 77 +++++++++++++++++++++++++++++++++++++++++++--
 arch/x86/events/intel/cmt.h | 26 +++++++++++++++
 2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/arch/x86/events/intel/cmt.c b/arch/x86/events/intel/cmt.c
index 23606a7..39f4bfa 100644
--- a/arch/x86/events/intel/cmt.c
+++ b/arch/x86/events/intel/cmt.c
@@ -26,6 +26,9 @@ static unsigned int cmt_l3_scale;	/* cmt hw units to bytes. */
 
 static unsigned int __min_max_rmid;	/* minimum max_rmid across all pkgs. */
 
+/* Root for system-wide hierarchy of MONitored Resources (monr). */
+static struct monr *monr_hrchy_root;
+
 /* Array of packages (array of pkgds). It's protected by RCU or cmt_mutex. */
 static struct pkg_data **cmt_pkgs_data;
 
@@ -82,6 +85,24 @@ static void monr_hrchy_assert_held_mutexes(void)
 		lockdep_assert_held(&pkgd->mutex);
 }
 
+static void monr_hrchy_acquire_locks(unsigned long *flags)
+{
+	struct pkg_data *pkgd = NULL;
+
+	raw_local_irq_save(*flags);
+	while ((pkgd = cmt_pkgs_data_next_rcu(pkgd)))
+		raw_spin_lock(&pkgd->lock);
+}
+
+static void monr_hrchy_release_locks(unsigned long *flags)
+{
+	struct pkg_data *pkgd = NULL;
+
+	while ((pkgd = cmt_pkgs_data_next_rcu(pkgd)))
+		raw_spin_unlock(&pkgd->lock);
+	raw_local_irq_restore(*flags);
+}
+
 static void monr_dealloc(struct monr *monr)
 {
 	kfree(monr);
@@ -97,6 +118,10 @@ static struct monr *monr_alloc(void)
 	if (!monr)
 		return ERR_PTR(-ENOMEM);
 
+	INIT_LIST_HEAD(&monr->entry);
+	INIT_LIST_HEAD(&monr->children);
+	INIT_LIST_HEAD(&monr->parent_entry);
+
 	return monr;
 }
 
@@ -145,6 +170,26 @@ static int monr_append_event(struct monr *monr, struct perf_event *event)
 	return 0;
 }
 
+static void monr_hrchy_insert_leaf(struct monr *monr, struct monr *parent)
+{
+	unsigned long flags;
+
+	monr_hrchy_acquire_locks(&flags);
+	list_add_tail(&monr->parent_entry, &parent->children);
+	monr->parent = parent;
+	monr_hrchy_release_locks(&flags);
+}
+
+static void monr_hrchy_remove_leaf(struct monr *monr)
+{
+	unsigned long flags;
+
+	monr_hrchy_acquire_locks(&flags);
+	list_del_init(&monr->parent_entry);
+	monr->parent = NULL;
+	monr_hrchy_release_locks(&flags);
+}
+
 static bool is_cgroup_event(struct perf_event *event)
 {
 	return false;
@@ -155,20 +200,32 @@ static int monr_hrchy_attach_cgroup_event(struct perf_event *event)
 	return -EPERM;
 }
 
+/*
+ * This non cgroup version creates a two-levels hierarchy: Root and first level
+ * and all event monr underneath it.
+ */
+static struct monr *monr_hrchy_get_monr_parent(struct perf_event *event)
+{
+	return monr_hrchy_root;
+}
+
 static int monr_hrchy_attach_cpu_event(struct perf_event *event)
 {
-	return -EPERM;
+	return monr_append_event(monr_hrchy_root, event);
 }
 
 static int monr_hrchy_attach_task_event(struct perf_event *event)
 {
-	struct monr *monr;
+	struct monr *monr_parent, *monr;
 	int err;
 
+	monr_parent = monr_hrchy_get_monr_parent(event);
 	monr = monr_alloc();
 	if (IS_ERR(monr))
 		return -ENOMEM;
 
+	monr_hrchy_insert_leaf(monr, monr_parent);
+
 	err = monr_append_event(monr, event);
 	if (err)
 		monr_dealloc(monr);
@@ -199,6 +256,12 @@ static int monr_hrchy_attach_event(struct perf_event *event)
 	return err;
 }
 
+static void monr_destroy(struct monr *monr)
+{
+	monr_hrchy_remove_leaf(monr);
+	monr_dealloc(monr);
+}
+
 /**
  * __match_event() - Determine if @a and @b should share a rmid.
  */
@@ -281,6 +344,7 @@ static void intel_cmt_event_destroy(struct perf_event *event)
 
 	/* monr is dettached from event. */
 	monr = monr_remove_event(event);
+	monr_destroy(monr);
 
 	monr_hrchy_release_mutexes();
 	mutex_unlock(&cmt_mutex);
@@ -516,6 +580,9 @@ static const struct x86_cpu_id intel_cmt_match[] = {
 
 static void cmt_dealloc(void)
 {
+	kfree(monr_hrchy_root);
+	monr_hrchy_root = NULL;
+
 	kfree(cmt_pkgs_data);
 	cmt_pkgs_data = NULL;
 }
@@ -537,6 +604,12 @@ static int __init cmt_alloc(void)
 	if (!cmt_pkgs_data)
 		return -ENOMEM;
 
+	mutex_lock(&cmt_mutex);
+	monr_hrchy_root = monr_alloc();
+	mutex_unlock(&cmt_mutex);
+	if (IS_ERR(monr_hrchy_root))
+		return PTR_ERR(monr_hrchy_root);
+
 	return 0;
 }
 
diff --git a/arch/x86/events/intel/cmt.h b/arch/x86/events/intel/cmt.h
index 0ce5d4d..46e8335 100644
--- a/arch/x86/events/intel/cmt.h
+++ b/arch/x86/events/intel/cmt.h
@@ -7,6 +7,25 @@
  * In order to monitor a cgroups and/or thread, it must be associated to
  * a monr. A monr is active in a CPU when a thread that is associated to
  * it (either directly or through a cgroup) is scheduled in it.
+ * The monrs are organized in a tree hierarchy named "monr hierarchy". It
+ * captures the dependencies between the monitored entities, e.g.:
+ *
+ *	   cgroup hierarchy		        monr hierarchy
+ *------------------------------------------------------------------------
+ *          root cgroup                           root monr
+ *       (always monitored)                        /      \
+ *       /                \                     monr A    monr B1
+ *  cgroup A             cgroupB                  |
+ * (monitored)        (no monitored)            monr A1
+ *      |              /          \
+ *   task A1       task B1       task B2
+ * (monitored)   (monitored)  (no monitored)
+ *
+ *
+ * This driver mantains the monr hierarchy as separate from the cgroup
+ * hierarchy in order to reduce the need for synchronization between the two
+ * and to make possible to capture dependencies between threads in the same
+ * cgroup or process.
  *
  *
  * Locking
@@ -46,6 +65,9 @@ struct pkg_data {
  * struct monr - MONitored Resource.
  * @mon_events:		The head of event's group that use this monr, if any.
  * @entry:		List entry into cmt_event_monrs.
+ * @parent:		Parent in monr hierarchy.
+ * @children:		List of children in monr hierarchy.
+ * @parent_entry:	Entry in parent's children list.
  *
  * An monr is assigned to every CMT event and/or monitored cgroups when
  * monitoring is activated and that instance's address do not change during
@@ -54,4 +76,8 @@ struct pkg_data {
 struct monr {
 	struct perf_event		*mon_events;
 	struct list_head		entry;
+
+	struct monr			*parent;
+	struct list_head		children;
+	struct list_head		parent_entry;
 };
-- 
2.8.0.rc3.226.g39d4020

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ