Patch from Eric Valette <valette@crf.canon.fr>:

Here is a patch that enables to catch exception
    and get message before crashing RTEMS :)

    It should be generic to any Intel port although enabled
    only for pc386 BSP...

    [Joel] I fixed the bug I introduced in irq_asm.s...
This commit is contained in:
Joel Sherrill
1998-08-21 16:39:52 +00:00
parent 2938140589
commit eb562f2c86
11 changed files with 348 additions and 20 deletions

View File

@@ -15,6 +15,9 @@
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <bspIo.h>
#include <rtems/score/thread.h>
/* _CPU_Initialize
*
@@ -82,3 +85,90 @@ void _CPU_Thread_Idle_body ()
asm volatile ("hlt");
}
}
void _defaultExcHandler (CPU_Exception_frame *ctx)
{
printk("----------------------------------------------------------\n");
printk("Exception %d caught at PC %x by thread %d\n",
ctx->idtIndex,
ctx->eip,
_Thread_Executing->Object.id);
printk("----------------------------------------------------------\n");
printk("Processor execution context at time of the fault was :\n");
printk("----------------------------------------------------------\n");
printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n",
ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n",
ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
printk("----------------------------------------------------------\n");
printk("Error code pushed by processor itself (if not 0) = %x\n",
ctx->faultCode);
printk("----------------------------------------------------------\n\n");
printk(" ************ FAULTY THREAD WILL BE DELETED **************\n");
/*
* OK I could probably use a simplified version but at least this
* should work.
*/
rtems_task_delete(_Thread_Executing->Object.id);
}
cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
extern void rtems_exception_prologue_0();
extern void rtems_exception_prologue_1();
extern void rtems_exception_prologue_2();
extern void rtems_exception_prologue_3();
extern void rtems_exception_prologue_4();
extern void rtems_exception_prologue_5();
extern void rtems_exception_prologue_6();
extern void rtems_exception_prologue_7();
extern void rtems_exception_prologue_8();
extern void rtems_exception_prologue_9();
extern void rtems_exception_prologue_10();
extern void rtems_exception_prologue_11();
extern void rtems_exception_prologue_12();
extern void rtems_exception_prologue_13();
extern void rtems_exception_prologue_14();
extern void rtems_exception_prologue_16();
extern void rtems_exception_prologue_17();
extern void rtems_exception_prologue_18();
static rtems_raw_irq_hdl tbl[] = {
rtems_exception_prologue_0,
rtems_exception_prologue_1,
rtems_exception_prologue_2,
rtems_exception_prologue_3,
rtems_exception_prologue_4,
rtems_exception_prologue_5,
rtems_exception_prologue_6,
rtems_exception_prologue_7,
rtems_exception_prologue_8,
rtems_exception_prologue_9,
rtems_exception_prologue_10,
rtems_exception_prologue_11,
rtems_exception_prologue_12,
rtems_exception_prologue_13,
rtems_exception_prologue_14,
rtems_exception_prologue_16,
rtems_exception_prologue_17,
rtems_exception_prologue_18,
};
void rtems_exception_init_mngt()
{
unsigned int i,j;
interrupt_gate_descriptor *currentIdtEntry;
unsigned limit;
unsigned level;
i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
i386_get_info_from_IDTR (&currentIdtEntry, &limit);
_CPU_ISR_Disable(level);
for (j = 0; j < i; j++) {
create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
}
_CPU_ISR_Enable(level);
}

View File

@@ -138,6 +138,10 @@ typedef struct {
unsigned32 eflags;
} CPU_Exception_frame;
typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
extern cpuExcHandlerType _currentExcHandler;
extern void rtems_exception_init_mngt();
/*
* The following structure defines the set of information saved
* on the current stack by RTEMS upon receipt of each interrupt
@@ -146,6 +150,29 @@ typedef struct {
typedef CPU_Exception_frame CPU_Interrupt_frame;
typedef enum {
DIVIDE_BY_ZERO = 0,
DEBUG = 1,
NMI = 2,
BREAKPOINT = 3,
OVERFLOW = 4,
BOUND = 5,
ILLEGAL_INSTR = 6,
MATH_COPROC_UNAVAIL = 7,
DOUBLE_FAULT = 8,
I386_COPROC_SEG_ERR = 9,
INVALID_TSS = 10,
SEGMENT_NOT_PRESENT = 11,
STACK_SEGMENT_FAULT = 12,
GENERAL_PROT_ERR = 13,
PAGE_FAULT = 14,
INTEL_RES15 = 15,
FLOAT_ERROR = 16,
ALIGN_CHECK = 17,
MACHINE_CHECK = 18
} Intel_symbolic_exception_name;
/*
* The following table contains the information required to configure
* the i386 specific parameters.

View File

@@ -109,6 +109,105 @@ SYM (_CPU_Context_restore_fp):
frstor (eax) # restore FP context
ret
SYM (_Exception_Handler):
pusha # Push general purpose registers
pushl esp # Push exception frame address
movl _currentExcHandler, eax # Call function storead in _currentExcHandler
call * eax
addl $4, esp
popa # restore general purpose registers
addl $8, esp # skill vector number and faultCode
iret
#define DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY(_vector) \
.p2align 4 ; \
PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
SYM (rtems_exception_prologue_ ## _vector ): \
pushl $ _vector ; \
jmp SYM (_Exception_Handler) ;
#define DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY(_vector) \
.p2align 4 ; \
PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
SYM (rtems_exception_prologue_ ## _vector ): \
pushl $ 0 ; \
pushl $ _vector ; \
jmp SYM (_Exception_Handler) ;
/*
* Divide Error
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (0)
/*
* Debug Exception
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (1)
/*
* NMI
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (2)
/*
* Breakpoint
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (3)
/*
* Overflow
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (4)
/*
* Bound Range Exceeded
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (5)
/*
* Invalid Opcode
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (6)
/*
* No Math Coproc
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (7)
/*
* Double Fault
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (8)
/*
* Coprocessor segment overrun
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (9)
/*
* Invalid TSS
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (10)
/*
* Segment Not Present
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (11)
/*
* Stack segment Fault
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (12)
/*
* General Protection Fault
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (13)
/*
* Page Fault
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (14)
/*
* Floating point error (NB 15 is reserved it is therefor skipped)
*/
DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (16)
/*
* Aligment Check
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (17)
/*
* Machine Check
*/
DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (18)
/*
* GO32 does not require these segment related routines.
*/

View File

@@ -11,9 +11,9 @@ PROJECT_ROOT = @PROJECT_ROOT@
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = network
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# # We only build the Network library if HAS_NETWORKING was defined
# NETWORK_yes_V = network
# NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# wrapup is the one that actually builds and installs the library
# from the individual .rel files built in other directories

View File

@@ -33,7 +33,7 @@
.set HDROFF, 0x24 # offset into bin2boot header of start32 addr
.set STACKOFF, 0x200-0x10 # offset to load into %esp, from start of image
/* #define NEW_GAS*/
/*----------------------------------------------------------------------------+
| CODE section
+----------------------------------------------------------------------------*/
@@ -78,14 +78,20 @@ _start16:
/*---------------------------------------------------------------------+
| Bare PC machines boot in real mode! We have to turn protected mode on.
+---------------------------------------------------------------------*/
#ifdef NEW_GAS
data32
addr32
#endif
lgdt gdtptr - start16 # load Global Descriptor Table
movl %cr0, %eax
orl $CR0_PE, %eax
movl %eax, %cr0 # turn on protected mode
#ifdef NEW_GAS
ljmpl $PROT_CODE_SEG, $1f # flush prefetch queue, and reload %cs
#else
ljmp $PROT_CODE_SEG, $1f # flush prefetch queue, and reload %cs
#endif
1:
.code32

View File

@@ -173,10 +173,13 @@ void bsp_start( void )
console_reserve_resources(&BSP_Configuration);
/*
* Init rtems_interrupt_management
* Init rtems interrupt management
*/
rtems_irq_mngt_init();
/*
* Init rtems exceptions management
*/
rtems_exception_init_mngt();
/*
* The following information is very useful when debugging.
*/

View File

@@ -8,9 +8,9 @@ VPATH = @srcdir@
RTEMS_ROOT = @top_srcdir@
PROJECT_ROOT = @PROJECT_ROOT@
# We only build the Network library if HAS_NETWORKING was defined
NETWORK_yes_V = network
NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# # We only build the Network library if HAS_NETWORKING was defined
# NETWORK_yes_V = network
# NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
BSP_PIECES=startup clock console timer pc386dev $(NETWORK)
GENERIC_PIECES=

View File

@@ -14,6 +14,8 @@
#include <bsp.h>
#include <irq.h>
#include <rtems/score/thread.h>
#include <rtems/score/apiext.h>
/*
* pointer to the mask representing the additionnal irq vectors
@@ -360,11 +362,18 @@ int pc386_rtems_irq_mngt_get(rtems_irq_global_settings** config)
void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
{
/*
* If I understand the _Thread_Dispatch routine correctly
* I do not see how this routine can be called given the
* actual code. I plan to use this so far unused feature
* to implement remote debugger ptrace("attach", ...)
* command.
* Process pending signals that have not already been
* processed by _Thread_Displatch. This happens quite
* unfrequently : the ISR must have posted an action
* to the current running thread.
*/
if ( _Thread_Do_post_task_switch_extension ||
_Thread_Executing->do_post_task_switch_extension ) {
_Thread_Executing->do_post_task_switch_extension = FALSE;
_API_extensions_Run_postswitch();
}
/*
* I plan to process other thread related events here.
* This will include DEBUG session requsted from keyboard...
*/
printk(" _ThreadProcessSignalsFromIrq called! mail valette@crf.canon.fr\n");
}

View File

@@ -14,6 +14,8 @@
#include "asm.h"
#include <irq_asm.h>
BEGIN_CODE
SYM (_ISR_Handler):
/*
* Before this was point is reached the vectors unique
@@ -243,3 +245,6 @@ SYM (default_raw_idt_handler):
popa
iret
END_CODE
END

View File

@@ -19,8 +19,7 @@
#include <libcpu/cpu.h>
#include <string.h>
#include <libcpu/cpuModel.h>
extern void printk(const char*, ...);
#include <bspIo.h>
unsigned char Cx86_step = 0;
static const char *Cx86_type[] = {

View File

@@ -15,6 +15,9 @@
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <bspIo.h>
#include <rtems/score/thread.h>
/* _CPU_Initialize
*
@@ -82,3 +85,90 @@ void _CPU_Thread_Idle_body ()
asm volatile ("hlt");
}
}
void _defaultExcHandler (CPU_Exception_frame *ctx)
{
printk("----------------------------------------------------------\n");
printk("Exception %d caught at PC %x by thread %d\n",
ctx->idtIndex,
ctx->eip,
_Thread_Executing->Object.id);
printk("----------------------------------------------------------\n");
printk("Processor execution context at time of the fault was :\n");
printk("----------------------------------------------------------\n");
printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n",
ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n",
ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
printk("----------------------------------------------------------\n");
printk("Error code pushed by processor itself (if not 0) = %x\n",
ctx->faultCode);
printk("----------------------------------------------------------\n\n");
printk(" ************ FAULTY THREAD WILL BE DELETED **************\n");
/*
* OK I could probably use a simplified version but at least this
* should work.
*/
rtems_task_delete(_Thread_Executing->Object.id);
}
cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
extern void rtems_exception_prologue_0();
extern void rtems_exception_prologue_1();
extern void rtems_exception_prologue_2();
extern void rtems_exception_prologue_3();
extern void rtems_exception_prologue_4();
extern void rtems_exception_prologue_5();
extern void rtems_exception_prologue_6();
extern void rtems_exception_prologue_7();
extern void rtems_exception_prologue_8();
extern void rtems_exception_prologue_9();
extern void rtems_exception_prologue_10();
extern void rtems_exception_prologue_11();
extern void rtems_exception_prologue_12();
extern void rtems_exception_prologue_13();
extern void rtems_exception_prologue_14();
extern void rtems_exception_prologue_16();
extern void rtems_exception_prologue_17();
extern void rtems_exception_prologue_18();
static rtems_raw_irq_hdl tbl[] = {
rtems_exception_prologue_0,
rtems_exception_prologue_1,
rtems_exception_prologue_2,
rtems_exception_prologue_3,
rtems_exception_prologue_4,
rtems_exception_prologue_5,
rtems_exception_prologue_6,
rtems_exception_prologue_7,
rtems_exception_prologue_8,
rtems_exception_prologue_9,
rtems_exception_prologue_10,
rtems_exception_prologue_11,
rtems_exception_prologue_12,
rtems_exception_prologue_13,
rtems_exception_prologue_14,
rtems_exception_prologue_16,
rtems_exception_prologue_17,
rtems_exception_prologue_18,
};
void rtems_exception_init_mngt()
{
unsigned int i,j;
interrupt_gate_descriptor *currentIdtEntry;
unsigned limit;
unsigned level;
i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
i386_get_info_from_IDTR (&currentIdtEntry, &limit);
_CPU_ISR_Disable(level);
for (j = 0; j < i; j++) {
create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
}
_CPU_ISR_Enable(level);
}