summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2015-11-16 07:57:22 -0200
committerRenato Botelho <renato@netgate.com>2015-11-16 07:57:22 -0200
commitad0b136d63d70552782c5c4936ce97e8aa42442e (patch)
tree44825d3d4a6cdbed690f2a6d5611f043119188fd /sys/amd64
parent2e02b14e19fd0fe27055d4a6e11a65e76882bf5f (diff)
parentd1d4e816ce49797ab1f23bb48cf5ee69018df284 (diff)
downloadFreeBSD-src-ad0b136d63d70552782c5c4936ce97e8aa42442e.zip
FreeBSD-src-ad0b136d63d70552782c5c4936ce97e8aa42442e.tar.gz
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/db_trace.c216
-rw-r--r--sys/amd64/amd64/gdb_machdep.c4
-rw-r--r--sys/amd64/amd64/machdep.c25
3 files changed, 76 insertions, 169 deletions
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 39297d9..381237b 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -52,17 +52,8 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
-static db_varfcn_t db_dr0;
-static db_varfcn_t db_dr1;
-static db_varfcn_t db_dr2;
-static db_varfcn_t db_dr3;
-static db_varfcn_t db_dr4;
-static db_varfcn_t db_dr5;
-static db_varfcn_t db_dr6;
-static db_varfcn_t db_dr7;
static db_varfcn_t db_frame;
-static db_varfcn_t db_rsp;
-static db_varfcn_t db_ss;
+static db_varfcn_t db_frame_seg;
CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
@@ -71,17 +62,17 @@ CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
*/
#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
- { "cs", DB_OFFSET(tf_cs), db_frame },
- { "ds", DB_OFFSET(tf_ds), db_frame },
- { "es", DB_OFFSET(tf_es), db_frame },
- { "fs", DB_OFFSET(tf_fs), db_frame },
- { "gs", DB_OFFSET(tf_gs), db_frame },
- { "ss", NULL, db_ss },
+ { "cs", DB_OFFSET(tf_cs), db_frame_seg },
+ { "ds", DB_OFFSET(tf_ds), db_frame_seg },
+ { "es", DB_OFFSET(tf_es), db_frame_seg },
+ { "fs", DB_OFFSET(tf_fs), db_frame_seg },
+ { "gs", DB_OFFSET(tf_gs), db_frame_seg },
+ { "ss", DB_OFFSET(tf_ss), db_frame_seg },
{ "rax", DB_OFFSET(tf_rax), db_frame },
{ "rcx", DB_OFFSET(tf_rcx), db_frame },
{ "rdx", DB_OFFSET(tf_rdx), db_frame },
{ "rbx", DB_OFFSET(tf_rbx), db_frame },
- { "rsp", NULL, db_rsp },
+ { "rsp", DB_OFFSET(tf_rsp), db_frame },
{ "rbp", DB_OFFSET(tf_rbp), db_frame },
{ "rsi", DB_OFFSET(tf_rsi), db_frame },
{ "rdi", DB_OFFSET(tf_rdi), db_frame },
@@ -95,57 +86,18 @@ struct db_variable db_regs[] = {
{ "r15", DB_OFFSET(tf_r15), db_frame },
{ "rip", DB_OFFSET(tf_rip), db_frame },
{ "rflags", DB_OFFSET(tf_rflags), db_frame },
-#define DB_N_SHOW_REGS 24 /* Don't show registers after here. */
- { "dr0", NULL, db_dr0 },
- { "dr1", NULL, db_dr1 },
- { "dr2", NULL, db_dr2 },
- { "dr3", NULL, db_dr3 },
- { "dr4", NULL, db_dr4 },
- { "dr5", NULL, db_dr5 },
- { "dr6", NULL, db_dr6 },
- { "dr7", NULL, db_dr7 },
};
-struct db_variable *db_eregs = db_regs + DB_N_SHOW_REGS;
-
-#define DB_DRX_FUNC(reg) \
-static int \
-db_ ## reg (vp, valuep, op) \
- struct db_variable *vp; \
- db_expr_t * valuep; \
- int op; \
-{ \
- if (op == DB_VAR_GET) \
- *valuep = r ## reg (); \
- else \
- load_ ## reg (*valuep); \
- return (1); \
-}
-
-DB_DRX_FUNC(dr0)
-DB_DRX_FUNC(dr1)
-DB_DRX_FUNC(dr2)
-DB_DRX_FUNC(dr3)
-DB_DRX_FUNC(dr4)
-DB_DRX_FUNC(dr5)
-DB_DRX_FUNC(dr6)
-DB_DRX_FUNC(dr7)
-
-static __inline long
-get_rsp(struct trapframe *tf)
-{
- return ((ISPL(tf->tf_cs)) ? tf->tf_rsp :
- (db_expr_t)tf + offsetof(struct trapframe, tf_rsp));
-}
+struct db_variable *db_eregs = db_regs + nitems(db_regs);
static int
-db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+db_frame_seg(struct db_variable *vp, db_expr_t *valuep, int op)
{
- long *reg;
+ uint16_t *reg;
if (kdb_frame == NULL)
return (0);
- reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+ reg = (uint16_t *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
if (op == DB_VAR_GET)
*valuep = *reg;
else
@@ -154,30 +106,18 @@ db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
}
static int
-db_rsp(struct db_variable *vp, db_expr_t *valuep, int op)
-{
-
- if (kdb_frame == NULL)
- return (0);
-
- if (op == DB_VAR_GET)
- *valuep = get_rsp(kdb_frame);
- else if (ISPL(kdb_frame->tf_cs))
- kdb_frame->tf_rsp = *valuep;
- return (1);
-}
-
-static int
-db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
{
+ long *reg;
if (kdb_frame == NULL)
return (0);
+ reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
if (op == DB_VAR_GET)
- *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
- else if (ISPL(kdb_frame->tf_cs))
- kdb_frame->tf_ss = *valuep;
+ *valuep = *reg;
+ else
+ *reg = *valuep;
return (1);
}
@@ -188,9 +128,7 @@ db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
#define TRAP_INTERRUPT 5
static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
-static int db_numargs(struct amd64_frame *);
-static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t,
- void *);
+static void db_print_stack_entry(const char *, db_addr_t, void *);
static void decode_syscall(int, struct thread *);
static const char * watchtype_str(int type);
@@ -198,62 +136,11 @@ int amd64_set_watch(int watchnum, unsigned long watchaddr, int size,
int access, struct dbreg *d);
int amd64_clr_watch(int watchnum, struct dbreg *d);
-/*
- * Figure out how many arguments were passed into the frame at "fp".
- */
-static int
-db_numargs(fp)
- struct amd64_frame *fp;
-{
-#if 1
- return (0); /* regparm, needs dwarf2 info */
-#else
- long *argp;
- int inst;
- int args;
-
- argp = (long *)db_get_value((long)&fp->f_retaddr, 8, FALSE);
- /*
- * XXX etext is wrong for LKMs. We should attempt to interpret
- * the instruction at the return address in all cases. This
- * may require better fault handling.
- */
- if (argp < (long *)btext || argp >= (long *)etext) {
- args = 5;
- } else {
- inst = db_get_value((long)argp, 4, FALSE);
- if ((inst & 0xff) == 0x59) /* popl %ecx */
- args = 1;
- else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */
- args = ((inst >> 16) & 0xff) / 4;
- else
- args = 5;
- }
- return (args);
-#endif
-}
-
static void
-db_print_stack_entry(name, narg, argnp, argp, callpc, frame)
- const char *name;
- int narg;
- char **argnp;
- long *argp;
- db_addr_t callpc;
- void *frame;
+db_print_stack_entry(const char *name, db_addr_t callpc, void *frame)
{
- db_printf("%s(", name);
-#if 0
- while (narg) {
- if (argnp)
- db_printf("%s=", *argnp++);
- db_printf("%lr", (long)db_get_value((long)argp, 8, FALSE));
- argp++;
- if (--narg != 0)
- db_printf(",");
- }
-#endif
- db_printf(") at ");
+
+ db_printf("%s() at ", name != NULL ? name : "??");
db_printsym(callpc, DB_STGY_PROC);
if (frame != NULL)
db_printf("/frame 0x%lx", (register_t)frame);
@@ -348,7 +235,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
return;
}
- db_print_stack_entry(name, 0, 0, 0, rip, &(*fp)->f_frame);
+ db_print_stack_entry(name, rip, &(*fp)->f_frame);
/*
* Point to base of trapframe which is just above the
@@ -357,7 +244,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
tf = (struct trapframe *)((long)*fp + 16);
if (INKERNEL((long) tf)) {
- rsp = get_rsp(tf);
+ rsp = tf->tf_rsp;
rip = tf->tf_rip;
rbp = tf->tf_rbp;
switch (frame_type) {
@@ -384,17 +271,13 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
}
static int
-db_backtrace(struct thread *td, struct trapframe *tf,
- struct amd64_frame *frame, db_addr_t pc, int count)
+db_backtrace(struct thread *td, struct trapframe *tf, struct amd64_frame *frame,
+ db_addr_t pc, register_t sp, int count)
{
struct amd64_frame *actframe;
-#define MAXNARG 16
- char *argnames[MAXNARG], **argnp = NULL;
const char *name;
- long *argp;
db_expr_t offset;
c_db_sym_t sym;
- int narg;
boolean_t first;
if (count == -1)
@@ -418,48 +301,51 @@ db_backtrace(struct thread *td, struct trapframe *tf,
*/
actframe = frame;
if (first) {
- if (tf != NULL) {
+ first = FALSE;
+ if (sym == C_DB_SYM_NULL && sp != 0) {
+ /*
+ * If a symbol couldn't be found, we've probably
+ * jumped to a bogus location, so try and use
+ * the return address to find our caller.
+ */
+ db_print_stack_entry(name, pc, NULL);
+ pc = db_get_value(sp, 8, FALSE);
+ if (db_search_symbol(pc, DB_STGY_PROC,
+ &offset) == C_DB_SYM_NULL)
+ break;
+ continue;
+ } else if (tf != NULL) {
int instr;
instr = db_get_value(pc, 4, FALSE);
if ((instr & 0xffffffff) == 0xe5894855) {
/* pushq %rbp; movq %rsp, %rbp */
- actframe = (void *)(get_rsp(tf) - 8);
+ actframe = (void *)(tf->tf_rsp - 8);
} else if ((instr & 0xffffff) == 0xe58948) {
/* movq %rsp, %rbp */
- actframe = (void *)get_rsp(tf);
+ actframe = (void *)tf->tf_rsp;
if (tf->tf_rbp == 0) {
/* Fake frame better. */
frame = actframe;
}
} else if ((instr & 0xff) == 0xc3) {
/* ret */
- actframe = (void *)(get_rsp(tf) - 8);
+ actframe = (void *)(tf->tf_rsp - 8);
} else if (offset == 0) {
/* Probably an assembler symbol. */
- actframe = (void *)(get_rsp(tf) - 8);
+ actframe = (void *)(tf->tf_rsp - 8);
}
} else if (strcmp(name, "fork_trampoline") == 0) {
/*
* Don't try to walk back on a stack for a
* process that hasn't actually been run yet.
*/
- db_print_stack_entry(name, 0, 0, 0, pc,
- actframe);
+ db_print_stack_entry(name, pc, actframe);
break;
}
- first = FALSE;
}
- argp = &actframe->f_arg0;
- narg = MAXNARG;
- if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
- argnp = argnames;
- } else {
- narg = db_numargs(frame);
- }
-
- db_print_stack_entry(name, narg, argnp, argp, pc, actframe);
+ db_print_stack_entry(name, pc, actframe);
if (actframe != frame) {
/* `frame' belongs to caller. */
@@ -473,7 +359,7 @@ db_backtrace(struct thread *td, struct trapframe *tf,
if (INKERNEL((long)pc) && !INKERNEL((long)frame)) {
sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
- db_print_stack_entry(name, 0, 0, 0, pc, frame);
+ db_print_stack_entry(name, pc, frame);
break;
}
if (!INKERNEL((long) frame)) {
@@ -495,17 +381,19 @@ db_trace_self(void)
frame = (struct amd64_frame *)rbp;
callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
frame = frame->f_frame;
- db_backtrace(curthread, NULL, frame, callpc, -1);
+ db_backtrace(curthread, NULL, frame, callpc, 0, -1);
}
int
db_trace_thread(struct thread *thr, int count)
{
struct pcb *ctx;
+ struct trapframe *tf;
ctx = kdb_thr_ctx(thr);
- return (db_backtrace(thr, NULL, (struct amd64_frame *)ctx->pcb_rbp,
- ctx->pcb_rip, count));
+ tf = thr == kdb_thread ? kdb_frame : NULL;
+ return (db_backtrace(thr, tf, (struct amd64_frame *)ctx->pcb_rbp,
+ ctx->pcb_rip, ctx->pcb_rsp, count));
}
int
diff --git a/sys/amd64/amd64/gdb_machdep.c b/sys/amd64/amd64/gdb_machdep.c
index 5775c8f..61ffad6 100644
--- a/sys/amd64/amd64/gdb_machdep.c
+++ b/sys/amd64/amd64/gdb_machdep.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
void *
gdb_cpu_getreg(int regnum, size_t *regsz)
{
+ static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL);
+ static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL);
*regsz = gdb_cpu_regsz(regnum);
@@ -76,6 +78,8 @@ gdb_cpu_getreg(int regnum, size_t *regsz)
case 14: return (&kdb_thrctx->pcb_r14);
case 15: return (&kdb_thrctx->pcb_r15);
case 16: return (&kdb_thrctx->pcb_rip);
+ case 18: return (&_kcodesel);
+ case 19: return (&_kdatasel);
}
return (NULL);
}
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 83b5e65..f501e99 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1238,11 +1238,26 @@ DB_SHOW_COMMAND(sysregs, db_show_sysregs)
db_printf("cr2\t0x%016lx\n", rcr2());
db_printf("cr3\t0x%016lx\n", rcr3());
db_printf("cr4\t0x%016lx\n", rcr4());
- db_printf("EFER\t%016lx\n", rdmsr(MSR_EFER));
- db_printf("FEATURES_CTL\t%016lx\n", rdmsr(MSR_IA32_FEATURE_CONTROL));
- db_printf("DEBUG_CTL\t%016lx\n", rdmsr(MSR_DEBUGCTLMSR));
- db_printf("PAT\t%016lx\n", rdmsr(MSR_PAT));
- db_printf("GSBASE\t%016lx\n", rdmsr(MSR_GSBASE));
+ if (rcr4() & CR4_XSAVE)
+ db_printf("xcr0\t0x%016lx\n", rxcr(0));
+ db_printf("EFER\t0x%016lx\n", rdmsr(MSR_EFER));
+ if (cpu_feature2 & (CPUID2_VMX | CPUID2_SMX))
+ db_printf("FEATURES_CTL\t%016lx\n",
+ rdmsr(MSR_IA32_FEATURE_CONTROL));
+ db_printf("DEBUG_CTL\t0x%016lx\n", rdmsr(MSR_DEBUGCTLMSR));
+ db_printf("PAT\t0x%016lx\n", rdmsr(MSR_PAT));
+ db_printf("GSBASE\t0x%016lx\n", rdmsr(MSR_GSBASE));
+}
+
+DB_SHOW_COMMAND(dbregs, db_show_dbregs)
+{
+
+ db_printf("dr0\t0x%016lx\n", rdr0());
+ db_printf("dr1\t0x%016lx\n", rdr1());
+ db_printf("dr2\t0x%016lx\n", rdr2());
+ db_printf("dr3\t0x%016lx\n", rdr3());
+ db_printf("dr6\t0x%016lx\n", rdr6());
+ db_printf("dr7\t0x%016lx\n", rdr7());
}
#endif
OpenPOWER on IntegriCloud