Deal with coming in via a TSS.

This commit is contained in:
fvdl 2002-10-05 21:19:16 +00:00
parent d24101a133
commit 736c720259
2 changed files with 73 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_interface.c,v 1.36 2002/10/01 12:56:49 fvdl Exp $ */
/* $NetBSD: db_interface.c,v 1.37 2002/10/05 21:19:16 fvdl Exp $ */
/*
* Mach Operating System
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.36 2002/10/01 12:56:49 fvdl Exp $");
__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.37 2002/10/05 21:19:16 fvdl Exp $");
#include "opt_ddb.h"
@ -79,6 +79,7 @@ const struct db_command db_machine_command_table[] = {
void kdbprinttrap __P((int, int));
#ifdef MULTIPROCESSOR
extern void ddb_ipi(int, struct trapframe);
extern void ddb_ipi_tss(struct i386tss *);
static void ddb_suspend(struct trapframe *);
int ddb_vec;
#endif
@ -99,7 +100,7 @@ db_machine_init()
#ifdef MULTIPROCESSOR
ddb_vec = idt_vec_alloc(0xf0, 0xff);
setgate((struct gate_descriptor *)&idt[ddb_vec], &Xintrddbipi, 0,
SDT_SYS386IGT, SEL_KPL);
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif
}
@ -171,9 +172,12 @@ kdb_trap(type, code, regs)
int type, code;
db_regs_t *regs;
{
int s;
int s, flags;
db_regs_t dbreg;
flags = regs->tf_err & TC_FLAGMASK;
regs->tf_err &= ~TC_FLAGMASK;
switch (type) {
case T_BPTFLT: /* breakpoint */
case T_TRCTRAP: /* single_step */
@ -200,7 +204,7 @@ kdb_trap(type, code, regs)
#endif
/* XXX Should switch to kdb's own stack here. */
ddb_regs = *regs;
if (KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
if (!(flags & TC_TSS) && KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
/*
* Kernel mode - esp and ss not saved
*/
@ -241,7 +245,7 @@ kdb_trap(type, code, regs)
regs->tf_eip = ddb_regs.tf_eip;
regs->tf_cs = ddb_regs.tf_cs;
regs->tf_eflags = ddb_regs.tf_eflags;
if (!KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
if (!(flags & TC_TSS) && !KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
/* ring transit - saved esp and ss valid */
regs->tf_esp = ddb_regs.tf_esp;
regs->tf_ss = ddb_regs.tf_ss;
@ -276,14 +280,44 @@ ddb_ipi(int cpl, struct trapframe frame)
ddb_suspend(&frame);
}
void
ddb_ipi_tss(struct i386tss *tss)
{
struct trapframe tf;
tf.tf_gs = tss->tss_gs;
tf.tf_fs = tss->tss_fs;
tf.tf_es = tss->__tss_es;
tf.tf_ds = tss->__tss_ds;
tf.tf_edi = tss->__tss_edi;
tf.tf_esi = tss->__tss_esi;
tf.tf_ebp = tss->tss_ebp;
tf.tf_ebx = tss->__tss_ebx;
tf.tf_edx = tss->__tss_edx;
tf.tf_ecx = tss->__tss_ecx;
tf.tf_eax = tss->__tss_eax;
tf.tf_trapno = 0;
tf.tf_err = TC_TSS;
tf.tf_eip = tss->__tss_eip;
tf.tf_cs = tss->__tss_cs;
tf.tf_eflags = tss->__tss_eflags;
tf.tf_esp = tss->tss_esp;
tf.tf_ss = tss->__tss_ss;
ddb_suspend(&tf);
}
static void
ddb_suspend(struct trapframe *frame)
{
volatile struct cpu_info *ci = curcpu();
db_regs_t regs;
int flags;
regs = *frame;
if (KERNELMODE(regs.tf_cs, regs.tf_eflags)) {
flags = regs.tf_err & TC_FLAGMASK;
regs.tf_err &= ~TC_FLAGMASK;
if (!(flags & TC_TSS) && KERNELMODE(regs.tf_cs, regs.tf_eflags)) {
/*
* Kernel mode - esp and ss not saved
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_trace.c,v 1.33 2002/10/01 12:56:50 fvdl Exp $ */
/* $NetBSD: db_trace.c,v 1.34 2002/10/05 21:19:16 fvdl Exp $ */
/*
* Mach Operating System
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.33 2002/10/01 12:56:50 fvdl Exp $");
__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.34 2002/10/05 21:19:16 fvdl Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -105,6 +105,8 @@ struct i386_frame {
#define TRAP 1
#define SYSCALL 2
#define INTERRUPT 3
#define INTERRUPT_TSS 4
#define TRAP_TSS 5
db_addr_t db_trap_symbol_value = 0;
db_addr_t db_syscall_symbol_value = 0;
@ -167,6 +169,7 @@ db_numargs(fp)
* It might be possible to dig out from the next frame up the name
* of the function that faulted, but that could get hairy.
*/
void
db_nextframe(fp, ip, argp, is_trap, pr)
struct i386_frame **fp; /* in/out */
@ -175,6 +178,8 @@ db_nextframe(fp, ip, argp, is_trap, pr)
int is_trap; /* in */
void (*pr) __P((const char *, ...)); /* in */
{
struct trapframe *tf;
struct i386tss *tss;
switch (is_trap) {
case NONE:
@ -184,8 +189,21 @@ db_nextframe(fp, ip, argp, is_trap, pr)
db_get_value((int) &(*fp)->f_frame, 4, FALSE);
break;
default: {
struct trapframe *tf;
case TRAP_TSS:
case INTERRUPT_TSS:
tss = (struct i386tss *)*argp;
*ip = tss->__tss_eip;
*fp = (struct i386_frame *)tss->tss_ebp;
if (is_trap == INTERRUPT_TSS)
printf("--- interrupt via task gate ---\n");
else
printf("--- trap via task gate ---\n");
break;
case TRAP:
case SYSCALL:
case INTERRUPT:
default:
/* The only argument to trap() or syscall() is the trapframe. */
tf = (struct trapframe *)argp;
@ -203,7 +221,6 @@ db_nextframe(fp, ip, argp, is_trap, pr)
*fp = (struct i386_frame *)tf->tf_ebp;
*ip = (db_addr_t)tf->tf_eip;
break;
}
}
}
@ -298,7 +315,9 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
* (e.g., npxdna) don't go through trap()
*/
#ifdef __ELF__
if (!strcmp(name, "trap")) {
if (!strcmp(name, "trap_tss")) {
is_trap = TRAP_TSS;
} else if (!strcmp(name, "trap")) {
is_trap = TRAP;
} else if (!strcmp(name, "syscall")) {
is_trap = SYSCALL;
@ -311,13 +330,17 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
!strcmp(name, "Xdoreti") ||
!strncmp(name, "Xsoft", 5)) {
is_trap = INTERRUPT;
} else if (!strncmp(name, "Xtss_", 5)) {
is_trap = INTERRUPT_TSS;
} else
goto normal;
} else
goto normal;
narg = 0;
#else
if (!strcmp(name, "_trap")) {
if (!strcmp(name, "_trap_tss")) {
is_trap = TRAP_TSS;
} else if (!strcmp(name, "_trap")) {
is_trap = TRAP;
} else if (!strcmp(name, "_syscall")) {
is_trap = SYSCALL;
@ -330,6 +353,8 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
!strcmp(name, "_Xdoreti") ||
!strncmp(name, "_Xsoft", 6)) {
is_trap = INTERRUPT;
} else if (!strncmp(name, "_Xtss_", 6)) {
is_trap = INTERRUPT_TSS;
} else
goto normal;
} else