- Minor spinlock debugging fix

- In rare cases, we might get a NMI (or breakpoint exception) just after
sys_ipc has been invoked, but _before_ esp has been set to tss.esp0 in that
case, we need to switch stacks manually and preserve the processor-saved
frame. We make sure that, before tss there is enough scratch space to cover
EFLAGS, CS, and EIP saved by the processor; this way, we can get around
without having to spend KDB its own interrupt task gate
This commit is contained in:
Jan Stoess 2008-01-25 16:24:21 +01:00
parent cd7e97b512
commit 37031aa006
4 changed files with 64 additions and 16 deletions

View File

@ -1,6 +1,6 @@
/*********************************************************************
*
* Copyright (C) 2002-2003, 2007, Karlsruhe University
* Copyright (C) 2002-2003, 2007-2008, Karlsruhe University
*
* File path: arch/x86/x32/trapgate.h
* Description: defines macros for implementation of trap and
@ -109,6 +109,39 @@ public:
#endif
#if defined(X86_EXC_KDB)
/* js: in rare cases, we might get a NMI (or breakpoint exception) just
* after sys_ipc has been invoked, but _before_ esp has been set to tss.esp0
* in that case, we need to switch stacks manually and preserve the
* processor-saved frame. We make sure that, before tss there is enough scratch
* space to cover EFLAGS, CS, and EIP saved by the processor; this way, we can
* get along without having to establish a interrupt task xgate for KDB
*/
#define kdb_check_stack() \
"push %%ebp \n" \
"lea (tss - 12), %%ebp \n" \
"cmpl %%esp, %%ebp \n" \
"pop %%ebp \n" \
"jne 1f \n" \
"addl $12, %%esp \n" \
"movl (%%esp), %%esp \n" \
"subl $12, %%esp \n" \
"push %%ebp \n" \
"mov (tss ), %%ebp \n" \
"mov %%ebp, 12(%%esp) \n" \
"mov (tss - 4), %%ebp \n" \
"mov %%ebp, 8(%%esp) \n" \
"mov (tss - 8), %%ebp \n" \
"add $3, %%ebp \n" \
"mov %%ebp, 4(%%esp) \n" \
"pop %%ebp \n" \
"1: \n"
#else
#define kdb_check_stack()
#endif
/**
* X86_EXCWITH_ERRORCODE: allows C implementation of
* exception handlers and trap/interrupt gates with error
@ -148,7 +181,6 @@ static void name##handler(x86_exceptionframe_t * frame)
#define X86_EXCNO_ERRORCODE(name, reason) \
extern "C" void name (void); \
static void name##handler(x86_exceptionframe_t * frame); \
@ -158,6 +190,7 @@ void name##_wrapper() \
".global "#name " \n" \
"\t.type "#name",@function \n" \
#name": \n" \
kdb_check_stack() \
"subl $4, %%esp \n" \
"pusha \n" \
"push %%ds \n" \
@ -181,4 +214,7 @@ void name##_wrapper() \
static void name##handler(x86_exceptionframe_t * frame)
#endif /* !__ARCH__X86__X32__TRAPGATE_H__ */

View File

@ -30,6 +30,10 @@
*
********************************************************************/
#if defined(CONFIG_DEBUG)
#define X86_EXC_KDB
#include <debug.h>
#include <ctors.h>
#include <kdb/tracepoints.h>
@ -43,7 +47,6 @@
#include INC_GLUE(debug.h)
#include INC_PLAT(nmi.h)
#if defined(CONFIG_DEBUG)
static void do_return_from_kdb(void);
@ -54,11 +57,13 @@ static bool sync_dbg_enter = false;
extern "C" void sync_debug (word_t address)
{
printf_spin_lock.unlock();
//ENABLE_TRACEPOINT(DEBUG_LOCK, ~0, 0);
if (get_current_tcb() == get_kdebug_tcb())
ENABLE_TRACEPOINT(DEBUG_LOCK, ~0, 0);
if (!sync_dbg_enter)
{
printf_spin_lock.unlock();
sync_dbg_enter = true;
TRACEPOINT(DEBUG_LOCK, "CPU %d, tcb %t, spinlock BUG (lock %x) @ %x\n",
get_current_cpu(), get_current_tcb(),
@ -69,6 +74,7 @@ extern "C" void sync_debug (word_t address)
}
#endif
class cpu_kdb_t
{
private:
@ -96,9 +102,10 @@ public:
{
if (get_current_tcb() == get_kdebug_tcb())
return;
void (*entry)(word_t) = (void (*)(word_t)) get_kip()->kdebug_entry;
void (*exit)(void) = do_return_from_kdb;
kdb_tcb->stack = kdb_tcb->get_stack_top();
kdb_tcb->notify(exit);
kdb_tcb->notify(entry, (word_t) &param);
@ -119,6 +126,11 @@ cpu_kdb_t cpu_kdb UNIT("cpulocal") CTORPRIO(CTORPRIO_CPU, 1);
tcb_t *get_kdebug_tcb() { return cpu_kdb.get_kdb_tcb(); }
void do_enter_kdebug(x86_exceptionframe_t *frame, const word_t exception)
{
cpu_kdb.do_enter_kdebug(frame, X86_EXC_DEBUG);
}
void do_return_from_kdb(void)
{
ASSERT(get_current_tcb() == get_kdebug_tcb());
@ -127,7 +139,7 @@ void do_return_from_kdb(void)
X86_EXCNO_ERRORCODE(exc_breakpoint, X86_EXC_BREAKPOINT)
{
cpu_kdb.do_enter_kdebug(frame, X86_EXC_BREAKPOINT);
cpu_kdb.do_enter_kdebug(frame, X86_EXC_BREAKPOINT);
}
X86_EXCNO_ERRORCODE(exc_debug, X86_EXC_DEBUG)
@ -135,17 +147,10 @@ X86_EXCNO_ERRORCODE(exc_debug, X86_EXC_DEBUG)
cpu_kdb.do_enter_kdebug(frame, X86_EXC_DEBUG);
}
DECLARE_TRACEPOINT(X86_NMI);
X86_EXCNO_ERRORCODE(exc_nmi, X86_EXC_NMI)
{
TRACEPOINT(X86_NMI, "NMI frame %x eip %x efl %x",
frame,
frame->regs[x86_exceptionframe_t::ipreg],
frame->regs[x86_exceptionframe_t::freg]);
cpu_kdb.do_enter_kdebug(frame, X86_EXC_NMI);
}
#ifdef CONFIG_SMP
X86_EXCNO_ERRORCODE(exc_debug_ipi, 0)
{
@ -153,6 +158,8 @@ X86_EXCNO_ERRORCODE(exc_debug_ipi, 0)
}
#endif
#undef X86_EXC_KDB
#endif /* CONFIG_DEBUG */

View File

@ -116,7 +116,7 @@ void setup_smp_boot_gdt (void)
/* processor local data */
x86_segdesc_t gdt[GDT_SIZE] UNIT("x86.cpulocal");
x86_x32_tss_t tss UNIT("x86.cpulocal");
x86_x32_tss_t tss UNIT("x86.cpulocal.tss");

View File

@ -1,6 +1,6 @@
/*********************************************************************
*
* Copyright (C) 1999-2005, 2007, Karlsruhe University
* Copyright (C) 1999-2005, 2007-2008, Karlsruhe University
*
* File path: glue/v4-x86/x32/linker-pc99.lds
* Description: Generic linkser script for x86.
@ -78,6 +78,11 @@ SECTIONS
{
*(.data.cpulocal)
*(.data.x86.cpulocal)
#if defined(CONFIG_DEBUG)
. = . + 8;
#endif
*(.data.x86.cpulocal.tss)
}
_end_cpu_local = .;