diff options
author | John Levon <john.levon@joyent.com> | 2018-08-15 13:52:29 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2018-08-15 13:52:29 +0000 |
commit | 005d090d5d39829784302a3c8574b81b88fc69d0 (patch) | |
tree | 3583e1eb4c1de6265db97c3683d8da8d78e44b53 | |
parent | c6493650bb8171db31ebebfa92d9a19dd0fe3e82 (diff) | |
download | illumos-joyent-005d090d5d39829784302a3c8574b81b88fc69d0.tar.gz |
OS-5852 kmdb tortures via single-step miscellaneous traprelease-20180816
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r-- | usr/src/cmd/mdb/common/kmdb/kaif_start.c | 33 | ||||
-rw-r--r-- | usr/src/uts/intel/amd64/sys/kdi_regs.h | 49 | ||||
-rw-r--r-- | usr/src/uts/intel/kdi/kdi_asm.s | 6 | ||||
-rw-r--r-- | usr/src/uts/intel/kdi/kdi_idt.c | 3 |
4 files changed, 83 insertions, 8 deletions
diff --git a/usr/src/cmd/mdb/common/kmdb/kaif_start.c b/usr/src/cmd/mdb/common/kmdb/kaif_start.c index 6c0fc810bb..c6ecd84b70 100644 --- a/usr/src/cmd/mdb/common/kmdb/kaif_start.c +++ b/usr/src/cmd/mdb/common/kmdb/kaif_start.c @@ -21,10 +21,9 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * The main CPU-control loops, used to control masters and slaves. */ @@ -248,7 +247,7 @@ kaif_slave_loop(kaif_cpusave_t *cpusave) } else if (slavecmd == KAIF_SLAVE_CMD_ACK) { cpusave->krs_cpu_acked = 1; } else if (cpusave->krs_cpu_acked && - slavecmd == KAIF_SLAVE_CMD_SPIN) { + slavecmd == KAIF_SLAVE_CMD_SPIN) { cpusave->krs_cpu_acked = 0; #endif } @@ -292,13 +291,31 @@ kaif_main_loop(kaif_cpusave_t *cpusave) int cmd; if (kaif_master_cpuid == KAIF_MASTER_CPUID_UNSET) { + + /* + * Special case: Unload requested before first debugger entry. + * Don't stop the world, as there's nothing to clean up that + * can't be handled by the running kernel. + */ if (!kmdb_dpi_resume_requested && kmdb_kdi_get_unload_request()) { - /* - * Special case: Unload requested before first debugger - * entry. Don't stop the world, as there's nothing to - * clean up that can't be handled by the running kernel. - */ + cpusave->krs_cpu_state = KAIF_CPU_STATE_NONE; + return (KAIF_CPU_CMD_RESUME); + } + + /* + * We're a slave with no master, so just resume. This can + * happen if, prior to this, two CPUs both raced through + * kdi_cmnint() - for example, a breakpoint on a frequently + * called function. The loser will be redirected to the slave + * loop; note that the event itself is lost at this point. + * + * The winner will then cross-call that slave, but it won't + * actually be received until the slave returns to the kernel + * and enables interrupts. We'll then come back in via + * kdi_slave_entry() and hit this path. + */ + if (cpusave->krs_cpu_state == KAIF_CPU_STATE_SLAVE) { cpusave->krs_cpu_state = KAIF_CPU_STATE_NONE; return (KAIF_CPU_CMD_RESUME); } diff --git a/usr/src/uts/intel/amd64/sys/kdi_regs.h b/usr/src/uts/intel/amd64/sys/kdi_regs.h index 6fe698551f..80cfbd5150 100644 --- a/usr/src/uts/intel/amd64/sys/kdi_regs.h +++ b/usr/src/uts/intel/amd64/sys/kdi_regs.h @@ -29,6 +29,8 @@ #ifndef _AMD64_SYS_KDI_REGS_H #define _AMD64_SYS_KDI_REGS_H +#include <sys/stddef.h> + #ifdef __cplusplus extern "C" { #endif @@ -77,6 +79,53 @@ extern "C" { #define KDIREG_SP KDIREG_RSP #define KDIREG_FP KDIREG_RBP +#if !defined(_ASM) + +/* + * Handy for debugging krs_gregs; keep in sync with the KDIREG_* above. + */ +typedef struct { + greg_t kr_savfp; + greg_t kr_savpc; + greg_t kr_rdi; + greg_t kr_rsi; + greg_t kr_rdx; + greg_t kr_rcx; + greg_t kr_r8; + greg_t kr_r9; + greg_t kr_rax; + greg_t kr_rbx; + greg_t kr_rbp; + greg_t r_r10; + greg_t r_r11; + greg_t r_r12; + greg_t r_r13; + greg_t r_r14; + greg_t r_r15; + greg_t kr_fsbase; + greg_t kr_gsbase; + greg_t kr_kgsbase; + greg_t kr_cr2; + greg_t kr_cr3; + greg_t kr_ds; + greg_t kr_es; + greg_t kr_fs; + greg_t kr_gs; + greg_t kr_trapno; + greg_t kr_err; + greg_t kr_rip; + greg_t kr_cs; + greg_t kr_rflags; + greg_t kr_rsp; + greg_t kr_ss; +} kdiregs_t; + +#if defined(_KERNEL) +CTASSERT(offsetof(kdiregs_t, kr_ss) == ((KDIREG_NGREG - 1) * sizeof (greg_t))); +#endif + +#endif /* !_ASM */ + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/intel/kdi/kdi_asm.s b/usr/src/uts/intel/kdi/kdi_asm.s index edfbea10c7..f106d643f7 100644 --- a/usr/src/uts/intel/kdi/kdi_asm.s +++ b/usr/src/uts/intel/kdi/kdi_asm.s @@ -406,6 +406,7 @@ movq %rax, REG_OFF(KDIREG_CR3)(%rsp) movq REG_OFF(KDIREG_SS)(%rsp), %rax + movq %rax, REG_OFF(KDIREG_SAVPC)(%rsp) xchgq REG_OFF(KDIREG_RIP)(%rsp), %rax movq %rax, REG_OFF(KDIREG_SS)(%rsp) @@ -426,6 +427,11 @@ movq REG_OFF(KDIREG_RIP)(%rsp), %rcx ADD_CRUMB(%rax, KRM_PC, %rcx, %rdx) + movq REG_OFF(KDIREG_RSP)(%rsp), %rcx + ADD_CRUMB(%rax, KRM_SP, %rcx, %rdx) + ADD_CRUMB(%rax, KRM_TRAPNO, $-1, %rdx) + + movq $KDI_CPU_STATE_SLAVE, KRS_CPU_STATE(%rax) pushq %rax jmp kdi_save_common_state diff --git a/usr/src/uts/intel/kdi/kdi_idt.c b/usr/src/uts/intel/kdi/kdi_idt.c index 6ea4681bce..a5520c72c3 100644 --- a/usr/src/uts/intel/kdi/kdi_idt.c +++ b/usr/src/uts/intel/kdi/kdi_idt.c @@ -88,6 +88,9 @@ #define KDI_IDT_DTYPE_KERNEL 0 #define KDI_IDT_DTYPE_BOOT 1 +/* Solely to keep kdiregs_t in the CTF, otherwise unused. */ +kdiregs_t kdi_regs; + kdi_cpusave_t *kdi_cpusave; int kdi_ncpusave; |