All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maksim Davydov <davydov-max@yandex-team.ru>
To: linux-kernel@vger.kernel.org, x86@kernel.org
Cc: davydov-max@yandex-team.ru, den-plotnikov@yandex-team.ru,
	tony.luck@intel.com, tglx@linutronix.de, mingo@redhat.com,
	bp@alien8.de, dave.hansen@linux.intel.com, hpa@zytor.com,
	peterz@infradead.org, juri.lelli@redhat.com,
	vincent.guittot@linaro.org
Subject: [PATCH] x86/split_lock: add split lock counter
Date: Fri, 15 Dec 2023 17:01:13 +0300	[thread overview]
Message-ID: <20231215140113.57173-1-davydov-max@yandex-team.ru> (raw)

Provides per task split locks counter to monitor split locks rate
in the system. It can be helpful in split locks monitoring to get a clear
sense of which process causing split locks and how many of them have
happened by the moment. For instance, it might be used by cloud providers
who can't control guest executable code and want to make decisions based
on the rate value like ratelimiting or notifing the split lock origins.

To implement this functionality the per-task flag have been transformed
into the counter. But procfs interface is used to provide the counter
in machine-readable format.

Signed-off-by: Maksim Davydov <davydov-max@yandex-team.ru>
---
 arch/x86/include/asm/cpu.h  | 18 ++++++++++++++++++
 arch/x86/kernel/cpu/intel.c | 35 +++++++++++++++++++++++++++++++++--
 fs/proc/base.c              |  7 +++++++
 include/linux/sched.h       |  6 +++---
 kernel/fork.c               |  2 +-
 5 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index fecc4fe1d68a..1470124e1d63 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -44,6 +44,12 @@ extern bool handle_user_split_lock(struct pt_regs *regs, long error_code);
 extern bool handle_guest_split_lock(unsigned long ip);
 extern void handle_bus_lock(struct pt_regs *regs);
 u8 get_this_hybrid_cpu_type(void);
+extern int proc_pid_split_locks_show(struct seq_file *s,
+		struct pid_namespace *ns, struct pid *pid,
+		struct task_struct *tsk);
+extern int proc_tgid_split_locks_show(struct seq_file *s,
+		struct pid_namespace *ns, struct pid *pid,
+		struct task_struct *tsk);
 #else
 static inline void __init sld_setup(struct cpuinfo_x86 *c) {}
 static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code)
@@ -62,6 +68,18 @@ static inline u8 get_this_hybrid_cpu_type(void)
 {
 	return 0;
 }
+static inline int proc_pid_split_locks_show(struct seq_file *s,
+		struct pid_namespace *ns, struct pid *pid,
+		struct task_struct *tsk)
+{
+	return 0;
+}
+static inline int proc_tgid_split_locks_show(struct seq_file *s,
+		struct pid_namespace *ns, struct pid *pid,
+		struct task_struct *tsk)
+{
+	return 0;
+}
 #endif
 #ifdef CONFIG_IA32_FEAT_CTL
 void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index a927a8fc9624..20640a4b9eac 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -1160,10 +1160,10 @@ static void split_lock_warn(unsigned long ip)
 	struct delayed_work *work;
 	int cpu;
 
-	if (!current->reported_split_lock)
+	if (!current->detected_split_locks)
 		pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n",
 				    current->comm, current->pid, ip);
-	current->reported_split_lock = 1;
+	current->detected_split_locks++;
 
 	if (sysctl_sld_mitigate) {
 		/*
@@ -1191,6 +1191,37 @@ static void split_lock_warn(unsigned long ip)
 	put_cpu();
 }
 
+static int split_locks_show(struct seq_file *s, struct task_struct *tsk,
+			    int whole)
+{
+	u64 detected_split_locks = tsk->detected_split_locks;
+
+	if (whole) {
+		struct task_struct *t = tsk;
+
+		while_each_thread(tsk, t) {
+			detected_split_locks += t->detected_split_locks;
+		}
+	}
+
+	seq_put_decimal_ull(s, "", detected_split_locks);
+	seq_putc(s, '\n');
+
+	return 0;
+}
+
+int proc_pid_split_locks_show(struct seq_file *s, struct pid_namespace *ns,
+			      struct pid *pid, struct task_struct *tsk)
+{
+	return split_locks_show(s, tsk, 0);
+}
+
+int proc_tgid_split_locks_show(struct seq_file *s, struct pid_namespace *ns,
+			       struct pid *pid, struct task_struct *tsk)
+{
+	return split_locks_show(s, tsk, 1);
+}
+
 bool handle_guest_split_lock(unsigned long ip)
 {
 	if (sld_state == sld_warn) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index dd31e3b6bf77..3c533312dbbc 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -98,6 +98,7 @@
 #include <linux/cn_proc.h>
 #include <linux/ksm.h>
 #include <trace/events/oom.h>
+#include <asm/cpu.h>
 #include "internal.h"
 #include "fd.h"
 
@@ -3360,6 +3361,9 @@ static const struct pid_entry tgid_base_stuff[] = {
 	ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
 	ONE("ksm_stat",  S_IRUSR, proc_pid_ksm_stat),
 #endif
+#ifdef CONFIG_CPU_SUP_INTEL
+	ONE("split_locks", S_IRUGO, proc_tgid_split_locks_show),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -3699,6 +3703,9 @@ static const struct pid_entry tid_base_stuff[] = {
 	ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
 	ONE("ksm_stat",  S_IRUSR, proc_pid_ksm_stat),
 #endif
+#ifdef CONFIG_CPU_SUP_INTEL
+	ONE("split_locks", S_IRUGO, proc_pid_split_locks_show),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 292c31697248..5b9cd4524405 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -957,9 +957,6 @@ struct task_struct {
 #ifdef CONFIG_IOMMU_SVA
 	unsigned			pasid_activated:1;
 #endif
-#ifdef	CONFIG_CPU_SUP_INTEL
-	unsigned			reported_split_lock:1;
-#endif
 #ifdef CONFIG_TASK_DELAY_ACCT
 	/* delay due to memory thrashing */
 	unsigned                        in_thrashing:1;
@@ -1027,6 +1024,9 @@ struct task_struct {
 	u64				stimescaled;
 #endif
 	u64				gtime;
+#ifdef	CONFIG_CPU_SUP_INTEL
+	u64				detected_split_locks;
+#endif
 	struct prev_cputime		prev_cputime;
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 	struct vtime			vtime;
diff --git a/kernel/fork.c b/kernel/fork.c
index 10917c3e1f03..5a0318010dd5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1188,7 +1188,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 #endif
 
 #ifdef CONFIG_CPU_SUP_INTEL
-	tsk->reported_split_lock = 0;
+	tsk->detected_split_locks = 0;
 #endif
 
 #ifdef CONFIG_SCHED_MM_CID
-- 
2.34.1


             reply	other threads:[~2023-12-15 14:01 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-15 14:01 Maksim Davydov [this message]
2023-12-15 18:16 ` [PATCH] x86/split_lock: add split lock counter Dave Hansen
2023-12-16 10:56   ` Maksim Davydov
2024-01-02 15:14     ` Dave Hansen
2023-12-16  2:21 ` kernel test robot
2023-12-16  3:27 ` kernel test robot
2023-12-16  5:59 ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231215140113.57173-1-davydov-max@yandex-team.ru \
    --to=davydov-max@yandex-team.ru \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=den-plotnikov@yandex-team.ru \
    --cc=hpa@zytor.com \
    --cc=juri.lelli@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=vincent.guittot@linaro.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.