summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorTobias Huschle <huschle@linux.ibm.com>2024-08-12 13:39:29 +0200
committerVasily Gorbik <gor@linux.ibm.com>2024-08-29 22:56:34 +0200
commit42419bcdfdcb287918e53500a04aeb532b41ed1f (patch)
tree1bfa8fe14bda89016ee70b1b092a98a031c98e07 /arch/s390
parentcafeff5a030983bbf37b11ab766b68d7da3b8aab (diff)
downloadlinux-42419bcdfdcb287918e53500a04aeb532b41ed1f.tar.gz
linux-42419bcdfdcb287918e53500a04aeb532b41ed1f.tar.bz2
linux-42419bcdfdcb287918e53500a04aeb532b41ed1f.zip
s390/wti: Add wti accounting for missed grace periods
A virtual CPU that has received a warning-track interrupt may fail to acknowledge the interrupt within the warning-track grace period. While this is usually not a problem, it will become necessary to investigate if there is a large number of such missed warning-track interrupts. Therefore, it is necessary to track these events. The information is tracked through the s390 debug facility and can be found under /sys/kernel/debug/s390dbf/wti/. The hex_ascii output is formatted as: <pid> <symbol> The values pid and current psw are collected when a warning track interrupt is received. Symbol is either the kernel symbol matching the collected psw or redacted to <user> when running in user space. Each line represents the currently executing process when a warning track interrupt was received which was then not acknowledged within its grace period. Acked-by: Heiko Carstens <hca@linux.ibm.com> Reviewed-by: Mete Durlu <meted@linux.ibm.com> Signed-off-by: Tobias Huschle <huschle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/wti.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/arch/s390/kernel/wti.c b/arch/s390/kernel/wti.c
index 3abae3908e65..da8bbffbed9d 100644
--- a/arch/s390/kernel/wti.c
+++ b/arch/s390/kernel/wti.c
@@ -5,13 +5,25 @@
* Copyright IBM Corp. 2023
*/
+#include <linux/kallsyms.h>
#include <linux/smpboot.h>
#include <linux/irq.h>
#include <uapi/linux/sched/types.h>
+#include <asm/debug.h>
#include <asm/diag.h>
#include <asm/sclp.h>
+#define WTI_DBF_LEN 64
+
+struct wti_debug {
+ unsigned long missed;
+ unsigned long addr;
+ pid_t pid;
+};
+
struct wti_state {
+ /* debug data for s390dbf */
+ struct wti_debug dbg;
/*
* Represents the real-time thread responsible to
* acknowledge the warning-track interrupt and trigger
@@ -27,6 +39,8 @@ struct wti_state {
static DEFINE_PER_CPU(struct wti_state, wti_state);
+static debug_info_t *wti_dbg;
+
/*
* During a warning-track grace period, interrupts are disabled
* to prevent delays of the warning-track acknowledgment.
@@ -61,6 +75,16 @@ static void wti_irq_enable(void)
local_irq_restore(flags);
}
+static void store_debug_data(struct wti_state *st)
+{
+ struct pt_regs *regs = get_irq_regs();
+
+ st->dbg.pid = current->pid;
+ st->dbg.addr = 0;
+ if (!user_mode(regs))
+ st->dbg.addr = regs->psw.addr;
+}
+
static void wti_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64)
{
@@ -68,6 +92,7 @@ static void wti_interrupt(struct ext_code ext_code,
inc_irq_stat(IRQEXT_WTI);
wti_irq_disable();
+ store_debug_data(st);
st->pending = true;
wake_up_process(st->thread);
}
@@ -79,6 +104,19 @@ static int wti_pending(unsigned int cpu)
return st->pending;
}
+static void wti_dbf_grace_period(struct wti_state *st)
+{
+ struct wti_debug *wdi = &st->dbg;
+ char buf[WTI_DBF_LEN];
+
+ if (wdi->addr)
+ snprintf(buf, sizeof(buf), "%d %pS", wdi->pid, (void *)wdi->addr);
+ else
+ snprintf(buf, sizeof(buf), "%d <user>", wdi->pid);
+ debug_text_event(wti_dbg, 2, buf);
+ wdi->missed++;
+}
+
static void wti_thread_fn(unsigned int cpu)
{
struct wti_state *st = per_cpu_ptr(&wti_state, cpu);
@@ -89,7 +127,8 @@ static void wti_thread_fn(unsigned int cpu)
* resumes when hypervisor decides to dispatch CPU
* to this LPAR again.
*/
- diag49c(DIAG49C_SUBC_ACK);
+ if (diag49c(DIAG49C_SUBC_ACK))
+ wti_dbf_grace_period(st);
wti_irq_enable();
}
@@ -129,7 +168,17 @@ static int __init wti_init(void)
rc = -EOPNOTSUPP;
goto out_subclass;
}
+ wti_dbg = debug_register("wti", 1, 1, WTI_DBF_LEN);
+ if (!wti_dbg) {
+ rc = -ENOMEM;
+ goto out_debug_register;
+ }
+ rc = debug_register_view(wti_dbg, &debug_hex_ascii_view);
+ if (rc)
+ goto out_debug_register;
goto out;
+out_debug_register:
+ debug_unregister(wti_dbg);
out_subclass:
irq_subclass_unregister(IRQ_SUBCLASS_WARNING_TRACK);
unregister_external_irq(EXT_IRQ_WARNING_TRACK, wti_interrupt);