mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
soc: rockchip: debug: rcu stall and hard lock have own notifier_block
Add rockchip_hardlock_notify to save pc of the cpu that is hard lock, the pc is used for minidump cpu hard lock stack. Signed-off-by: Huibin Hong <huibin.hong@rock-chips.com> Change-Id: Ie542d981f3f12ac1eb3a2f425b76780a04f220cf
This commit is contained in:
@@ -59,6 +59,10 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_ROCKCHIP_MINIDUMP)
|
||||
#include <soc/rockchip/rk_minidump.h>
|
||||
#endif
|
||||
|
||||
#include "fiq_debugger/fiq_debugger_priv.h"
|
||||
#include "rockchip_debug.h"
|
||||
|
||||
@@ -85,6 +89,22 @@ static char log_buf[1024];
|
||||
extern struct atomic_notifier_head hardlock_notifier_list;
|
||||
extern struct atomic_notifier_head rcu_stall_notifier_list;
|
||||
|
||||
static inline void rockchip_debug_serror_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
/* enable SError */
|
||||
asm volatile("msr daifclr, #0x4");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void rockchip_debug_serror_disable(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
/* disable SError */
|
||||
asm volatile("msr daifset, #0x4");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_FIQ_DEBUGGER)
|
||||
static int rockchip_debug_dump_edpcsr(struct fiq_debugger_output *output)
|
||||
{
|
||||
@@ -96,10 +116,7 @@ static int rockchip_debug_dump_edpcsr(struct fiq_debugger_output *output)
|
||||
void __iomem *base;
|
||||
u32 pu = 0, online = 0;
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/* disable SError */
|
||||
asm volatile("msr daifset, #0x4");
|
||||
#endif
|
||||
rockchip_debug_serror_disable();
|
||||
|
||||
while (rockchip_cpu_debug[i]) {
|
||||
online = cpu_online(i);
|
||||
@@ -154,11 +171,7 @@ static int rockchip_debug_dump_edpcsr(struct fiq_debugger_output *output)
|
||||
printed = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/* enable SError */
|
||||
asm volatile("msr daifclr, #0x4");
|
||||
#endif
|
||||
|
||||
rockchip_debug_serror_enable();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
@@ -173,8 +186,7 @@ static int rockchip_debug_dump_pmpcsr(struct fiq_debugger_output *output)
|
||||
void __iomem *base;
|
||||
u32 pu = 0, online = 0;
|
||||
|
||||
/* disable SError */
|
||||
asm volatile("msr daifset, #0x4");
|
||||
rockchip_debug_serror_disable();
|
||||
|
||||
while (rockchip_cs_pmu[i]) {
|
||||
online = cpu_online(i);
|
||||
@@ -233,8 +245,7 @@ static int rockchip_debug_dump_pmpcsr(struct fiq_debugger_output *output)
|
||||
prev_pc = NULL;
|
||||
printed = 0;
|
||||
}
|
||||
/* enable SError */
|
||||
asm volatile("msr daifclr, #0x4");
|
||||
rockchip_debug_serror_enable();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
#else
|
||||
@@ -244,7 +255,6 @@ static int rockchip_debug_dump_pmpcsr(struct fiq_debugger_output *output)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int rockchip_debug_dump_pcsr(struct fiq_debugger_output *output)
|
||||
{
|
||||
if (edpcsr_present)
|
||||
@@ -267,10 +277,7 @@ static int rockchip_panic_notify_edpcsr(struct notifier_block *nb,
|
||||
void __iomem *base;
|
||||
u32 pu = 0;
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/* disable SError */
|
||||
asm volatile("msr daifset, #0x4");
|
||||
#endif
|
||||
rockchip_debug_serror_disable();
|
||||
|
||||
/*
|
||||
* The panic handler will try to shut down the other CPUs.
|
||||
@@ -324,11 +331,7 @@ static int rockchip_panic_notify_edpcsr(struct notifier_block *nb,
|
||||
printed = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/* enable SError */
|
||||
asm volatile("msr daifclr, #0x4");
|
||||
#endif
|
||||
|
||||
rockchip_debug_serror_enable();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
@@ -344,8 +347,7 @@ static int rockchip_panic_notify_pmpcsr(struct notifier_block *nb,
|
||||
void __iomem *base;
|
||||
u32 pu = 0;
|
||||
|
||||
/* disable SError */
|
||||
asm volatile("msr daifset, #0x4");
|
||||
rockchip_debug_serror_disable();
|
||||
|
||||
/*
|
||||
* The panic handler will try to shut down the other CPUs.
|
||||
@@ -403,8 +405,7 @@ static int rockchip_panic_notify_pmpcsr(struct notifier_block *nb,
|
||||
prev_pc = NULL;
|
||||
printed = 0;
|
||||
}
|
||||
/* enable SError */
|
||||
asm volatile("msr daifclr, #0x4");
|
||||
rockchip_debug_serror_enable();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
#else
|
||||
@@ -508,10 +509,75 @@ static int rockchip_panic_notify(struct notifier_block *nb, unsigned long event,
|
||||
rockchip_panic_notify_dump_irqs();
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int rockchip_hardlock_notify(struct notifier_block *nb,
|
||||
unsigned long event, void *p)
|
||||
{
|
||||
u64 pmpcsr;
|
||||
int el;
|
||||
u32 pu = 0;
|
||||
void *pc = NULL;
|
||||
void __iomem *base;
|
||||
unsigned long edpcsr;
|
||||
unsigned long cpu = event;
|
||||
|
||||
rockchip_debug_serror_disable();
|
||||
|
||||
pu = (u32)readl(rockchip_cpu_debug[cpu] + EDPRSR) & EDPRSR_PU;
|
||||
if (pu != EDPRSR_PU) {
|
||||
pr_err("CPU%ld power down\n", cpu);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
if (edpcsr_present) {
|
||||
base = rockchip_cpu_debug[cpu];
|
||||
/* Unlock EDLSR.SLK so that EDPCSRhi gets populated */
|
||||
writel(EDLAR_UNLOCK, base + EDLAR);
|
||||
if (sizeof(edpcsr) == 8)
|
||||
edpcsr = ((u64)readl(base + EDPCSR_LO)) |
|
||||
((u64)readl(base + EDPCSR_HI) << 32);
|
||||
else
|
||||
edpcsr = (u32)readl(base + EDPCSR_LO);
|
||||
|
||||
/* NOTE: no offset on ARMv8; see DBGDEVID1.PCSROffset */
|
||||
pc = (void *)(edpcsr & ~1);
|
||||
} else {
|
||||
base = rockchip_cs_pmu[cpu];
|
||||
pmpcsr = ((u64)readl(base + PMPCSR_LO)) |
|
||||
((u64)readl(base + PMPCSR_HI) << 32);
|
||||
el = (pmpcsr >> 61) & 0x3;
|
||||
if (el == 2)
|
||||
pmpcsr |= 0xff00000000000000;
|
||||
else
|
||||
pmpcsr &= 0x0fffffffffffffff;
|
||||
/* NOTE: no offset on ARMv8; see DBGDEVID1.PCSROffset */
|
||||
pc = (void *)(pmpcsr & ~1);
|
||||
}
|
||||
|
||||
rockchip_debug_serror_enable();
|
||||
|
||||
#if IS_ENABLED(CONFIG_ROCKCHIP_MINIDUMP)
|
||||
rk_minidump_hardlock_notify(nb, event, pc);
|
||||
#endif
|
||||
|
||||
#if !IS_ENABLED(CONFIG_BOOTPARAM_HARDLOCKUP_PANIC)
|
||||
rockchip_panic_notify(nb, event, p);
|
||||
#endif
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block rockchip_panic_nb = {
|
||||
.notifier_call = rockchip_panic_notify,
|
||||
};
|
||||
|
||||
static struct notifier_block rockchip_rcu_stall_nb = {
|
||||
.notifier_call = rockchip_panic_notify,
|
||||
};
|
||||
|
||||
static struct notifier_block rockchip_hardlock_nb = {
|
||||
.notifier_call = rockchip_hardlock_notify,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_debug_dt_match[] __initconst = {
|
||||
/* external debug */
|
||||
{
|
||||
@@ -528,7 +594,6 @@ static const struct of_device_id rockchip_cspmu_dt_match[] __initconst = {
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
||||
static int __init rockchip_debug_init(void)
|
||||
{
|
||||
int i;
|
||||
@@ -575,10 +640,10 @@ static int __init rockchip_debug_init(void)
|
||||
if (IS_ENABLED(CONFIG_NO_GKI)) {
|
||||
if (IS_ENABLED(CONFIG_HARDLOCKUP_DETECTOR))
|
||||
atomic_notifier_chain_register(&hardlock_notifier_list,
|
||||
&rockchip_panic_nb);
|
||||
&rockchip_hardlock_nb);
|
||||
|
||||
atomic_notifier_chain_register(&rcu_stall_notifier_list,
|
||||
&rockchip_panic_nb);
|
||||
&rockchip_rcu_stall_nb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -594,10 +659,10 @@ static void __exit rockchip_debug_exit(void)
|
||||
if (IS_ENABLED(CONFIG_NO_GKI)) {
|
||||
if (IS_ENABLED(CONFIG_HARDLOCKUP_DETECTOR))
|
||||
atomic_notifier_chain_unregister(&hardlock_notifier_list,
|
||||
&rockchip_panic_nb);
|
||||
&rockchip_hardlock_nb);
|
||||
|
||||
atomic_notifier_chain_unregister(&rcu_stall_notifier_list,
|
||||
&rockchip_panic_nb);
|
||||
&rockchip_rcu_stall_nb);
|
||||
}
|
||||
|
||||
while (rockchip_cpu_debug[i])
|
||||
|
||||
Reference in New Issue
Block a user