| .. | .. |
|---|
| 59 | 59 | #include <linux/irq.h> |
|---|
| 60 | 60 | #include <linux/delay.h> |
|---|
| 61 | 61 | |
|---|
| 62 | +#if IS_ENABLED(CONFIG_ROCKCHIP_MINIDUMP) |
|---|
| 63 | +#include <soc/rockchip/rk_minidump.h> |
|---|
| 64 | +#endif |
|---|
| 65 | + |
|---|
| 62 | 66 | #include "fiq_debugger/fiq_debugger_priv.h" |
|---|
| 63 | 67 | #include "rockchip_debug.h" |
|---|
| 64 | 68 | |
|---|
| .. | .. |
|---|
| 85 | 89 | extern struct atomic_notifier_head hardlock_notifier_list; |
|---|
| 86 | 90 | extern struct atomic_notifier_head rcu_stall_notifier_list; |
|---|
| 87 | 91 | |
|---|
| 92 | +static inline void rockchip_debug_serror_enable(void) |
|---|
| 93 | +{ |
|---|
| 94 | +#ifdef CONFIG_ARM64 |
|---|
| 95 | + /* enable SError */ |
|---|
| 96 | + asm volatile("msr daifclr, #0x4"); |
|---|
| 97 | +#endif |
|---|
| 98 | +} |
|---|
| 99 | + |
|---|
| 100 | +static inline void rockchip_debug_serror_disable(void) |
|---|
| 101 | +{ |
|---|
| 102 | +#ifdef CONFIG_ARM64 |
|---|
| 103 | + /* disable SError */ |
|---|
| 104 | + asm volatile("msr daifset, #0x4"); |
|---|
| 105 | +#endif |
|---|
| 106 | +} |
|---|
| 107 | + |
|---|
| 88 | 108 | #if IS_ENABLED(CONFIG_FIQ_DEBUGGER) |
|---|
| 89 | 109 | static int rockchip_debug_dump_edpcsr(struct fiq_debugger_output *output) |
|---|
| 90 | 110 | { |
|---|
| .. | .. |
|---|
| 96 | 116 | void __iomem *base; |
|---|
| 97 | 117 | u32 pu = 0, online = 0; |
|---|
| 98 | 118 | |
|---|
| 99 | | -#ifdef CONFIG_ARM64 |
|---|
| 100 | | - /* disable SError */ |
|---|
| 101 | | - asm volatile("msr daifset, #0x4"); |
|---|
| 102 | | -#endif |
|---|
| 119 | + rockchip_debug_serror_disable(); |
|---|
| 103 | 120 | |
|---|
| 104 | 121 | while (rockchip_cpu_debug[i]) { |
|---|
| 105 | 122 | online = cpu_online(i); |
|---|
| .. | .. |
|---|
| 154 | 171 | printed = 0; |
|---|
| 155 | 172 | } |
|---|
| 156 | 173 | |
|---|
| 157 | | -#ifdef CONFIG_ARM64 |
|---|
| 158 | | - /* enable SError */ |
|---|
| 159 | | - asm volatile("msr daifclr, #0x4"); |
|---|
| 160 | | -#endif |
|---|
| 161 | | - |
|---|
| 174 | + rockchip_debug_serror_enable(); |
|---|
| 162 | 175 | return NOTIFY_OK; |
|---|
| 163 | 176 | } |
|---|
| 164 | 177 | |
|---|
| .. | .. |
|---|
| 173 | 186 | void __iomem *base; |
|---|
| 174 | 187 | u32 pu = 0, online = 0; |
|---|
| 175 | 188 | |
|---|
| 176 | | - /* disable SError */ |
|---|
| 177 | | - asm volatile("msr daifset, #0x4"); |
|---|
| 189 | + rockchip_debug_serror_disable(); |
|---|
| 178 | 190 | |
|---|
| 179 | 191 | while (rockchip_cs_pmu[i]) { |
|---|
| 180 | 192 | online = cpu_online(i); |
|---|
| .. | .. |
|---|
| 233 | 245 | prev_pc = NULL; |
|---|
| 234 | 246 | printed = 0; |
|---|
| 235 | 247 | } |
|---|
| 236 | | - /* enable SError */ |
|---|
| 237 | | - asm volatile("msr daifclr, #0x4"); |
|---|
| 248 | + rockchip_debug_serror_enable(); |
|---|
| 238 | 249 | return NOTIFY_OK; |
|---|
| 239 | 250 | } |
|---|
| 240 | 251 | #else |
|---|
| .. | .. |
|---|
| 243 | 254 | return 0; |
|---|
| 244 | 255 | } |
|---|
| 245 | 256 | #endif |
|---|
| 246 | | - |
|---|
| 247 | 257 | |
|---|
| 248 | 258 | int rockchip_debug_dump_pcsr(struct fiq_debugger_output *output) |
|---|
| 249 | 259 | { |
|---|
| .. | .. |
|---|
| 267 | 277 | void __iomem *base; |
|---|
| 268 | 278 | u32 pu = 0; |
|---|
| 269 | 279 | |
|---|
| 270 | | -#ifdef CONFIG_ARM64 |
|---|
| 271 | | - /* disable SError */ |
|---|
| 272 | | - asm volatile("msr daifset, #0x4"); |
|---|
| 273 | | -#endif |
|---|
| 280 | + rockchip_debug_serror_disable(); |
|---|
| 274 | 281 | |
|---|
| 275 | 282 | /* |
|---|
| 276 | 283 | * The panic handler will try to shut down the other CPUs. |
|---|
| .. | .. |
|---|
| 324 | 331 | printed = 0; |
|---|
| 325 | 332 | } |
|---|
| 326 | 333 | |
|---|
| 327 | | -#ifdef CONFIG_ARM64 |
|---|
| 328 | | - /* enable SError */ |
|---|
| 329 | | - asm volatile("msr daifclr, #0x4"); |
|---|
| 330 | | -#endif |
|---|
| 331 | | - |
|---|
| 332 | 334 | return NOTIFY_OK; |
|---|
| 333 | 335 | } |
|---|
| 334 | 336 | |
|---|
| .. | .. |
|---|
| 344 | 346 | void __iomem *base; |
|---|
| 345 | 347 | u32 pu = 0; |
|---|
| 346 | 348 | |
|---|
| 347 | | - /* disable SError */ |
|---|
| 348 | | - asm volatile("msr daifset, #0x4"); |
|---|
| 349 | + rockchip_debug_serror_disable(); |
|---|
| 349 | 350 | |
|---|
| 350 | 351 | /* |
|---|
| 351 | 352 | * The panic handler will try to shut down the other CPUs. |
|---|
| .. | .. |
|---|
| 403 | 404 | prev_pc = NULL; |
|---|
| 404 | 405 | printed = 0; |
|---|
| 405 | 406 | } |
|---|
| 406 | | - /* enable SError */ |
|---|
| 407 | | - asm volatile("msr daifclr, #0x4"); |
|---|
| 407 | + |
|---|
| 408 | 408 | return NOTIFY_OK; |
|---|
| 409 | 409 | } |
|---|
| 410 | 410 | #else |
|---|
| .. | .. |
|---|
| 508 | 508 | rockchip_panic_notify_dump_irqs(); |
|---|
| 509 | 509 | return NOTIFY_OK; |
|---|
| 510 | 510 | } |
|---|
| 511 | + |
|---|
| 512 | +static int rockchip_hardlock_notify(struct notifier_block *nb, |
|---|
| 513 | + unsigned long event, void *p) |
|---|
| 514 | +{ |
|---|
| 515 | + u64 pmpcsr; |
|---|
| 516 | + int el; |
|---|
| 517 | + u32 pu = 0; |
|---|
| 518 | + void *pc = NULL; |
|---|
| 519 | + void __iomem *base; |
|---|
| 520 | + unsigned long edpcsr; |
|---|
| 521 | + unsigned long cpu = event; |
|---|
| 522 | + |
|---|
| 523 | + rockchip_debug_serror_disable(); |
|---|
| 524 | + |
|---|
| 525 | + pu = (u32)readl(rockchip_cpu_debug[cpu] + EDPRSR) & EDPRSR_PU; |
|---|
| 526 | + if (pu != EDPRSR_PU) { |
|---|
| 527 | + pr_err("CPU%ld power down\n", cpu); |
|---|
| 528 | + return NOTIFY_OK; |
|---|
| 529 | + } |
|---|
| 530 | + |
|---|
| 531 | + if (edpcsr_present) { |
|---|
| 532 | + base = rockchip_cpu_debug[cpu]; |
|---|
| 533 | + /* Unlock EDLSR.SLK so that EDPCSRhi gets populated */ |
|---|
| 534 | + writel(EDLAR_UNLOCK, base + EDLAR); |
|---|
| 535 | + if (sizeof(edpcsr) == 8) |
|---|
| 536 | + edpcsr = ((u64)readl(base + EDPCSR_LO)) | |
|---|
| 537 | + ((u64)readl(base + EDPCSR_HI) << 32); |
|---|
| 538 | + else |
|---|
| 539 | + edpcsr = (u32)readl(base + EDPCSR_LO); |
|---|
| 540 | + |
|---|
| 541 | + /* NOTE: no offset on ARMv8; see DBGDEVID1.PCSROffset */ |
|---|
| 542 | + pc = (void *)(edpcsr & ~1); |
|---|
| 543 | + } else { |
|---|
| 544 | + base = rockchip_cs_pmu[cpu]; |
|---|
| 545 | + pmpcsr = ((u64)readl(base + PMPCSR_LO)) | |
|---|
| 546 | + ((u64)readl(base + PMPCSR_HI) << 32); |
|---|
| 547 | + el = (pmpcsr >> 61) & 0x3; |
|---|
| 548 | + if (el == 2) |
|---|
| 549 | + pmpcsr |= 0xff00000000000000; |
|---|
| 550 | + else |
|---|
| 551 | + pmpcsr &= 0x0fffffffffffffff; |
|---|
| 552 | + /* NOTE: no offset on ARMv8; see DBGDEVID1.PCSROffset */ |
|---|
| 553 | + pc = (void *)(pmpcsr & ~1); |
|---|
| 554 | + } |
|---|
| 555 | + |
|---|
| 556 | + rockchip_debug_serror_enable(); |
|---|
| 557 | + |
|---|
| 558 | +#if IS_ENABLED(CONFIG_ROCKCHIP_MINIDUMP) |
|---|
| 559 | + rk_minidump_hardlock_notify(nb, event, pc); |
|---|
| 560 | +#endif |
|---|
| 561 | + |
|---|
| 562 | +#if !IS_ENABLED(CONFIG_BOOTPARAM_HARDLOCKUP_PANIC) |
|---|
| 563 | + rockchip_panic_notify(nb, event, p); |
|---|
| 564 | +#endif |
|---|
| 565 | + return NOTIFY_OK; |
|---|
| 566 | +} |
|---|
| 567 | + |
|---|
| 511 | 568 | static struct notifier_block rockchip_panic_nb = { |
|---|
| 512 | 569 | .notifier_call = rockchip_panic_notify, |
|---|
| 570 | +}; |
|---|
| 571 | + |
|---|
| 572 | +static struct notifier_block rockchip_rcu_stall_nb = { |
|---|
| 573 | + .notifier_call = rockchip_panic_notify, |
|---|
| 574 | +}; |
|---|
| 575 | + |
|---|
| 576 | +static struct notifier_block rockchip_hardlock_nb = { |
|---|
| 577 | + .notifier_call = rockchip_hardlock_notify, |
|---|
| 513 | 578 | }; |
|---|
| 514 | 579 | |
|---|
| 515 | 580 | static const struct of_device_id rockchip_debug_dt_match[] __initconst = { |
|---|
| .. | .. |
|---|
| 527 | 592 | }, |
|---|
| 528 | 593 | { /* sentinel */ }, |
|---|
| 529 | 594 | }; |
|---|
| 530 | | - |
|---|
| 531 | 595 | |
|---|
| 532 | 596 | static int __init rockchip_debug_init(void) |
|---|
| 533 | 597 | { |
|---|
| .. | .. |
|---|
| 575 | 639 | if (IS_ENABLED(CONFIG_NO_GKI)) { |
|---|
| 576 | 640 | if (IS_ENABLED(CONFIG_HARDLOCKUP_DETECTOR)) |
|---|
| 577 | 641 | atomic_notifier_chain_register(&hardlock_notifier_list, |
|---|
| 578 | | - &rockchip_panic_nb); |
|---|
| 642 | + &rockchip_hardlock_nb); |
|---|
| 579 | 643 | |
|---|
| 580 | 644 | atomic_notifier_chain_register(&rcu_stall_notifier_list, |
|---|
| 581 | | - &rockchip_panic_nb); |
|---|
| 645 | + &rockchip_rcu_stall_nb); |
|---|
| 582 | 646 | } |
|---|
| 583 | 647 | |
|---|
| 584 | 648 | return 0; |
|---|
| .. | .. |
|---|
| 594 | 658 | if (IS_ENABLED(CONFIG_NO_GKI)) { |
|---|
| 595 | 659 | if (IS_ENABLED(CONFIG_HARDLOCKUP_DETECTOR)) |
|---|
| 596 | 660 | atomic_notifier_chain_unregister(&hardlock_notifier_list, |
|---|
| 597 | | - &rockchip_panic_nb); |
|---|
| 661 | + &rockchip_hardlock_nb); |
|---|
| 598 | 662 | |
|---|
| 599 | 663 | atomic_notifier_chain_unregister(&rcu_stall_notifier_list, |
|---|
| 600 | | - &rockchip_panic_nb); |
|---|
| 664 | + &rockchip_rcu_stall_nb); |
|---|
| 601 | 665 | } |
|---|
| 602 | 666 | |
|---|
| 603 | 667 | while (rockchip_cpu_debug[i]) |
|---|