mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
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>
This commit is contained in:
parent
cafeff5a03
commit
42419bcdfd
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user