Skip to content

Commit 42419bc

Browse files
tobias-huschleVasily Gorbik
authored andcommitted
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 <[email protected]> Reviewed-by: Mete Durlu <[email protected]> Signed-off-by: Tobias Huschle <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent cafeff5 commit 42419bc

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

arch/s390/kernel/wti.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,25 @@
55
* Copyright IBM Corp. 2023
66
*/
77

8+
#include <linux/kallsyms.h>
89
#include <linux/smpboot.h>
910
#include <linux/irq.h>
1011
#include <uapi/linux/sched/types.h>
12+
#include <asm/debug.h>
1113
#include <asm/diag.h>
1214
#include <asm/sclp.h>
1315

16+
#define WTI_DBF_LEN 64
17+
18+
struct wti_debug {
19+
unsigned long missed;
20+
unsigned long addr;
21+
pid_t pid;
22+
};
23+
1424
struct wti_state {
25+
/* debug data for s390dbf */
26+
struct wti_debug dbg;
1527
/*
1628
* Represents the real-time thread responsible to
1729
* acknowledge the warning-track interrupt and trigger
@@ -27,6 +39,8 @@ struct wti_state {
2739

2840
static DEFINE_PER_CPU(struct wti_state, wti_state);
2941

42+
static debug_info_t *wti_dbg;
43+
3044
/*
3145
* During a warning-track grace period, interrupts are disabled
3246
* to prevent delays of the warning-track acknowledgment.
@@ -61,13 +75,24 @@ static void wti_irq_enable(void)
6175
local_irq_restore(flags);
6276
}
6377

78+
static void store_debug_data(struct wti_state *st)
79+
{
80+
struct pt_regs *regs = get_irq_regs();
81+
82+
st->dbg.pid = current->pid;
83+
st->dbg.addr = 0;
84+
if (!user_mode(regs))
85+
st->dbg.addr = regs->psw.addr;
86+
}
87+
6488
static void wti_interrupt(struct ext_code ext_code,
6589
unsigned int param32, unsigned long param64)
6690
{
6791
struct wti_state *st = this_cpu_ptr(&wti_state);
6892

6993
inc_irq_stat(IRQEXT_WTI);
7094
wti_irq_disable();
95+
store_debug_data(st);
7196
st->pending = true;
7297
wake_up_process(st->thread);
7398
}
@@ -79,6 +104,19 @@ static int wti_pending(unsigned int cpu)
79104
return st->pending;
80105
}
81106

107+
static void wti_dbf_grace_period(struct wti_state *st)
108+
{
109+
struct wti_debug *wdi = &st->dbg;
110+
char buf[WTI_DBF_LEN];
111+
112+
if (wdi->addr)
113+
snprintf(buf, sizeof(buf), "%d %pS", wdi->pid, (void *)wdi->addr);
114+
else
115+
snprintf(buf, sizeof(buf), "%d <user>", wdi->pid);
116+
debug_text_event(wti_dbg, 2, buf);
117+
wdi->missed++;
118+
}
119+
82120
static void wti_thread_fn(unsigned int cpu)
83121
{
84122
struct wti_state *st = per_cpu_ptr(&wti_state, cpu);
@@ -89,7 +127,8 @@ static void wti_thread_fn(unsigned int cpu)
89127
* resumes when hypervisor decides to dispatch CPU
90128
* to this LPAR again.
91129
*/
92-
diag49c(DIAG49C_SUBC_ACK);
130+
if (diag49c(DIAG49C_SUBC_ACK))
131+
wti_dbf_grace_period(st);
93132
wti_irq_enable();
94133
}
95134

@@ -129,7 +168,17 @@ static int __init wti_init(void)
129168
rc = -EOPNOTSUPP;
130169
goto out_subclass;
131170
}
171+
wti_dbg = debug_register("wti", 1, 1, WTI_DBF_LEN);
172+
if (!wti_dbg) {
173+
rc = -ENOMEM;
174+
goto out_debug_register;
175+
}
176+
rc = debug_register_view(wti_dbg, &debug_hex_ascii_view);
177+
if (rc)
178+
goto out_debug_register;
132179
goto out;
180+
out_debug_register:
181+
debug_unregister(wti_dbg);
133182
out_subclass:
134183
irq_subclass_unregister(IRQ_SUBCLASS_WARNING_TRACK);
135184
unregister_external_irq(EXT_IRQ_WARNING_TRACK, wti_interrupt);

0 commit comments

Comments
 (0)