diff options
| -rw-r--r-- | arch/x86/platform/uv/uv_nmi.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c index 9126dfb6dbfc..9b8ac60ad8db 100644 --- a/arch/x86/platform/uv/uv_nmi.c +++ b/arch/x86/platform/uv/uv_nmi.c | |||
| @@ -21,7 +21,9 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/kdb.h> | ||
| 24 | #include <linux/kexec.h> | 25 | #include <linux/kexec.h> |
| 26 | #include <linux/kgdb.h> | ||
| 25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 26 | #include <linux/nmi.h> | 28 | #include <linux/nmi.h> |
| 27 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
| @@ -32,6 +34,7 @@ | |||
| 32 | #include <asm/kdebug.h> | 34 | #include <asm/kdebug.h> |
| 33 | #include <asm/local64.h> | 35 | #include <asm/local64.h> |
| 34 | #include <asm/nmi.h> | 36 | #include <asm/nmi.h> |
| 37 | #include <asm/traps.h> | ||
| 35 | #include <asm/uv/uv.h> | 38 | #include <asm/uv/uv.h> |
| 36 | #include <asm/uv/uv_hub.h> | 39 | #include <asm/uv/uv_hub.h> |
| 37 | #include <asm/uv/uv_mmrs.h> | 40 | #include <asm/uv/uv_mmrs.h> |
| @@ -153,8 +156,9 @@ module_param_named(retry_count, uv_nmi_retry_count, int, 0644); | |||
| 153 | * "dump" - dump process stack for each cpu | 156 | * "dump" - dump process stack for each cpu |
| 154 | * "ips" - dump IP info for each cpu | 157 | * "ips" - dump IP info for each cpu |
| 155 | * "kdump" - do crash dump | 158 | * "kdump" - do crash dump |
| 159 | * "kdb" - enter KDB/KGDB (default) | ||
| 156 | */ | 160 | */ |
| 157 | static char uv_nmi_action[8] = "dump"; | 161 | static char uv_nmi_action[8] = "kdb"; |
| 158 | module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); | 162 | module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); |
| 159 | 163 | ||
| 160 | static inline bool uv_nmi_action_is(const char *action) | 164 | static inline bool uv_nmi_action_is(const char *action) |
| @@ -540,6 +544,43 @@ static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs) | |||
| 540 | } | 544 | } |
| 541 | #endif /* !CONFIG_KEXEC */ | 545 | #endif /* !CONFIG_KEXEC */ |
| 542 | 546 | ||
| 547 | #ifdef CONFIG_KGDB_KDB | ||
| 548 | /* Call KDB from NMI handler */ | ||
| 549 | static void uv_call_kdb(int cpu, struct pt_regs *regs, int master) | ||
| 550 | { | ||
| 551 | int ret; | ||
| 552 | |||
| 553 | if (master) { | ||
| 554 | /* call KGDB NMI handler as MASTER */ | ||
| 555 | ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs, | ||
| 556 | &uv_nmi_slave_continue); | ||
| 557 | if (ret) { | ||
| 558 | pr_alert("KDB returned error, is kgdboc set?\n"); | ||
| 559 | atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT); | ||
| 560 | } | ||
| 561 | } else { | ||
| 562 | /* wait for KGDB signal that it's ready for slaves to enter */ | ||
| 563 | int sig; | ||
| 564 | |||
| 565 | do { | ||
| 566 | cpu_relax(); | ||
| 567 | sig = atomic_read(&uv_nmi_slave_continue); | ||
| 568 | } while (!sig); | ||
| 569 | |||
| 570 | /* call KGDB as slave */ | ||
| 571 | if (sig == SLAVE_CONTINUE) | ||
| 572 | kgdb_nmicallback(cpu, regs); | ||
| 573 | } | ||
| 574 | uv_nmi_sync_exit(master); | ||
| 575 | } | ||
| 576 | |||
| 577 | #else /* !CONFIG_KGDB_KDB */ | ||
| 578 | static inline void uv_call_kdb(int cpu, struct pt_regs *regs, int master) | ||
| 579 | { | ||
| 580 | pr_err("UV: NMI error: KGDB/KDB is not enabled in this kernel\n"); | ||
| 581 | } | ||
| 582 | #endif /* !CONFIG_KGDB_KDB */ | ||
| 583 | |||
| 543 | /* | 584 | /* |
| 544 | * UV NMI handler | 585 | * UV NMI handler |
| 545 | */ | 586 | */ |
| @@ -576,6 +617,10 @@ int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) | |||
| 576 | if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) | 617 | if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) |
| 577 | uv_nmi_dump_state(cpu, regs, master); | 618 | uv_nmi_dump_state(cpu, regs, master); |
| 578 | 619 | ||
| 620 | /* Call KDB if enabled */ | ||
| 621 | else if (uv_nmi_action_is("kdb")) | ||
| 622 | uv_call_kdb(cpu, regs, master); | ||
| 623 | |||
| 579 | /* Clear per_cpu "in nmi" flag */ | 624 | /* Clear per_cpu "in nmi" flag */ |
| 580 | atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT); | 625 | atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT); |
| 581 | 626 | ||
