summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-08-15 13:52:29 +0000
committerJohn Levon <john.levon@joyent.com>2018-08-15 13:52:29 +0000
commit005d090d5d39829784302a3c8574b81b88fc69d0 (patch)
tree3583e1eb4c1de6265db97c3683d8da8d78e44b53
parentc6493650bb8171db31ebebfa92d9a19dd0fe3e82 (diff)
downloadillumos-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.c33
-rw-r--r--usr/src/uts/intel/amd64/sys/kdi_regs.h49
-rw-r--r--usr/src/uts/intel/kdi/kdi_asm.s6
-rw-r--r--usr/src/uts/intel/kdi/kdi_idt.c3
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;