forked from Imagelibrary/rtems
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:
@@ -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 (¤tIdtEntry, &limit);
|
||||
|
||||
_CPU_ISR_Disable(level);
|
||||
for (j = 0; j < i; j++) {
|
||||
create_interrupt_gate_descriptor (¤tIdtEntry[j], tbl[j]);
|
||||
}
|
||||
_CPU_ISR_Enable(level);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
#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
|
||||
* that must be disabled when a particular entry is activated.
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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 (¤tIdtEntry, &limit);
|
||||
|
||||
_CPU_ISR_Disable(level);
|
||||
for (j = 0; j < i; j++) {
|
||||
create_interrupt_gate_descriptor (¤tIdtEntry[j], tbl[j]);
|
||||
}
|
||||
_CPU_ISR_Enable(level);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user