forked from Imagelibrary/rtems
remove depratated powerpc exception API
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
2009-10-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* shared/irq/irq_asm.S, shared/irq/README.deprecated,
|
||||
shared/irq/irq.c, shared/vectors/vectors.h,
|
||||
shared/vectors/vectors_init.c, shared/vectors/README.deprecated,
|
||||
shared/vectors/vectors.S: Removed files.
|
||||
* Makefile.am: Update for removed files.
|
||||
|
||||
2009-10-22 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* shared/clock/clock.c, shared/irq/irq_init.c,
|
||||
|
||||
@@ -51,7 +51,7 @@ EXTRA_DIST += shared/residual/residual.c
|
||||
EXTRA_DIST += shared/openpic/openpic.c
|
||||
|
||||
## shared/irq
|
||||
EXTRA_DIST += shared/irq/i8259.c shared/irq/irq.c shared/irq/irq_init.c \
|
||||
EXTRA_DIST += shared/irq/i8259.c shared/irq/irq_init.c \
|
||||
shared/irq/irq_asm.S shared/irq/openpic_i8259_irq.c
|
||||
|
||||
## shared/start
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2009-10-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* vectors/vectors.h, vectors/vectors_init.c, vectors/vectors.S,
|
||||
irq/irq_init.c, irq/irq_asm.S: Removed files.
|
||||
|
||||
2009-10-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* include/irq-config.h: New file.
|
||||
|
||||
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* IRQ veneers for RTEMS.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* Modified to support the MCP750.
|
||||
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
|
||||
*
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2003/7:
|
||||
* - store isr nesting level in _ISR_Nest_level rather than
|
||||
* SPRG0 - RTEMS relies on that variable.
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2005/4:
|
||||
* - DONT enable FP across user ISR since fpregs are never saved!!
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
.p2align 5
|
||||
|
||||
PUBLIC_VAR(decrementer_exception_vector_prolog_code)
|
||||
|
||||
SYM (decrementer_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
#ifdef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
|
||||
/*
|
||||
* save link register
|
||||
*/
|
||||
mflr r4
|
||||
stw r4, EXC_LR_OFFSET(r1)
|
||||
/*
|
||||
* make link register contain shared_raw_irq_code_entry
|
||||
* address
|
||||
*/
|
||||
lis r4,shared_raw_irq_code_entry@h
|
||||
ori r4,r4,shared_raw_irq_code_entry@l
|
||||
mtlr r4
|
||||
|
||||
li r4, ASM_DEC_VECTOR
|
||||
blr
|
||||
#else
|
||||
li r4, ASM_DEC_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
#endif
|
||||
|
||||
PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
|
||||
|
||||
decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
|
||||
|
||||
PUBLIC_VAR(external_exception_vector_prolog_code)
|
||||
|
||||
SYM (external_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
#ifdef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
|
||||
/*
|
||||
* save link register
|
||||
*/
|
||||
mflr r4
|
||||
stw r4, EXC_LR_OFFSET(r1)
|
||||
/*
|
||||
* make link register contain shared_raw_irq_code_entry
|
||||
* address
|
||||
*/
|
||||
lis r4,shared_raw_irq_code_entry@h
|
||||
ori r4,r4,shared_raw_irq_code_entry@l
|
||||
mtlr r4
|
||||
|
||||
li r4, ASM_EXT_VECTOR
|
||||
blr
|
||||
#else
|
||||
li r4, ASM_EXT_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
#endif
|
||||
|
||||
PUBLIC_VAR (external_exception_vector_prolog_code_size)
|
||||
|
||||
external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
|
||||
|
||||
PUBLIC_VAR(shared_raw_irq_code_entry)
|
||||
PUBLIC_VAR(C_dispatch_irq_handler)
|
||||
|
||||
.p2align 5
|
||||
SYM (shared_raw_irq_code_entry):
|
||||
/*
|
||||
* Entry conditions :
|
||||
* Registers already saved : R1, R4
|
||||
* R1 : points to a location with enough room for the
|
||||
* interrupt frame
|
||||
* R4 : vector number
|
||||
*/
|
||||
/*
|
||||
* Save SRR0/SRR1 As soon As possible as it is the minimal needed
|
||||
* to reenable exception processing
|
||||
*/
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
stw r3, GPR3_OFFSET(r1)
|
||||
|
||||
mfsrr0 r0
|
||||
mfsrr1 r2
|
||||
mfmsr r3
|
||||
|
||||
stw r0, SRR0_FRAME_OFFSET(r1)
|
||||
stw r2, SRR1_FRAME_OFFSET(r1)
|
||||
/*
|
||||
* Enable data and instruction address translation, exception recovery
|
||||
*
|
||||
* also, on CPUs with FP, enable FP so that FP context can be
|
||||
* saved and restored (using FP instructions)
|
||||
*/
|
||||
ori r3, r3, MSR_RI | MSR_IR | MSR_DR
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Push C scratch registers on the current stack. It may
|
||||
* actually be the thread stack or the interrupt stack.
|
||||
* Anyway we have to make it in order to be able to call C/C++
|
||||
* functions. Depending on the nesting interrupt level, we will
|
||||
* switch to the right stack later.
|
||||
*/
|
||||
stw r5, GPR5_OFFSET(r1)
|
||||
stw r6, GPR6_OFFSET(r1)
|
||||
stw r7, GPR7_OFFSET(r1)
|
||||
stw r8, GPR8_OFFSET(r1)
|
||||
stw r9, GPR9_OFFSET(r1)
|
||||
stw r10, GPR10_OFFSET(r1)
|
||||
stw r11, GPR11_OFFSET(r1)
|
||||
stw r12, GPR12_OFFSET(r1)
|
||||
stw r13, GPR13_OFFSET(r1)
|
||||
|
||||
mfcr r5
|
||||
mfctr r6
|
||||
mfxer r7
|
||||
#ifndef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
|
||||
mflr r8
|
||||
#endif
|
||||
|
||||
stw r5, EXC_CR_OFFSET(r1)
|
||||
stw r6, EXC_CTR_OFFSET(r1)
|
||||
stw r7, EXC_XER_OFFSET(r1)
|
||||
#ifndef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
|
||||
stw r8, EXC_LR_OFFSET(r1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add some non volatile registers to store information
|
||||
* that will be used when returning from C handler
|
||||
*/
|
||||
stw r14, GPR14_OFFSET(r1)
|
||||
stw r15, GPR15_OFFSET(r1)
|
||||
/*
|
||||
* save current stack pointer location in R14
|
||||
*/
|
||||
addi r14, r1, 0
|
||||
/*
|
||||
* store part of _Thread_Dispatch_disable_level address in R15
|
||||
*/
|
||||
addis r15,0, _Thread_Dispatch_disable_level@ha
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
/*
|
||||
* Get current nesting level in R2
|
||||
*/
|
||||
mfspr r2, SPRG0
|
||||
#else
|
||||
/*
|
||||
* Retrieve current nesting level from _ISR_Nest_level
|
||||
*/
|
||||
lis r7, _ISR_Nest_level@ha
|
||||
lwz r2, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
/*
|
||||
* Check if stack switch is necessary
|
||||
*/
|
||||
cmpwi r2,0
|
||||
bne nested
|
||||
mfspr r1, SPRG1
|
||||
|
||||
nested:
|
||||
/*
|
||||
* Start Incrementing nesting level in R2
|
||||
*/
|
||||
addi r2,r2,1
|
||||
/*
|
||||
* Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r6,_Thread_Dispatch_disable_level@l(r15)
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
/*
|
||||
* Store new nesting level in SPRG0
|
||||
*/
|
||||
mtspr SPRG0, r2
|
||||
#else
|
||||
/* store new nesting level in _ISR_Nest_level */
|
||||
stw r2, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
|
||||
addi r6, r6, 1
|
||||
mfmsr r5
|
||||
/*
|
||||
* store new _Thread_Dispatch_disable_level value
|
||||
*/
|
||||
stw r6, _Thread_Dispatch_disable_level@l(r15)
|
||||
/*
|
||||
* We are now running on the interrupt stack. External and decrementer
|
||||
* exceptions are still disabled. I see no purpose trying to optimize
|
||||
* further assembler code.
|
||||
*/
|
||||
/*
|
||||
* Call C exception handler for decrementer Interrupt frame is passed just
|
||||
* in case...
|
||||
*/
|
||||
addi r3, r14, 0x8
|
||||
bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
|
||||
/*
|
||||
* start decrementing nesting level. Note : do not test result against 0
|
||||
* value as an easy exit condition because if interrupt nesting level > 1
|
||||
* then _Thread_Dispatch_disable_level > 1
|
||||
*/
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
mfspr r2, SPRG0
|
||||
#else
|
||||
lis r7, _ISR_Nest_level@ha
|
||||
lwz r2, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
/*
|
||||
* start decrementing _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r3,_Thread_Dispatch_disable_level@l(r15)
|
||||
addi r2, r2, -1 /* Continue decrementing nesting level */
|
||||
addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
mtspr SPRG0, r2 /* End decrementing nesting level */
|
||||
#else
|
||||
stw r2, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
|
||||
#endif
|
||||
stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
|
||||
cmpwi r3, 0
|
||||
/*
|
||||
* switch back to original stack (done here just optimize registers
|
||||
* contention. Could have been done before...)
|
||||
*/
|
||||
addi r1, r14, 0
|
||||
bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
|
||||
/*
|
||||
* Here we are running again on the thread system stack.
|
||||
* We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
|
||||
* Interrupt are still disabled. Time to check if scheduler request to
|
||||
* do something with the current thread...
|
||||
*/
|
||||
addis r4, 0, _Context_Switch_necessary@ha
|
||||
lbz r5, _Context_Switch_necessary@l(r4)
|
||||
cmpwi r5, 0
|
||||
bne switch
|
||||
|
||||
addis r6, 0, _ISR_Signals_to_thread_executing@ha
|
||||
lbz r7, _ISR_Signals_to_thread_executing@l(r6)
|
||||
cmpwi r7, 0
|
||||
li r8, 0
|
||||
beq easy_exit
|
||||
stb r8, _ISR_Signals_to_thread_executing@l(r6)
|
||||
/*
|
||||
* going to call _ThreadProcessSignalsFromIrq
|
||||
* Push a complete exception like frame...
|
||||
*/
|
||||
stmw r16, GPR16_OFFSET(r1)
|
||||
addi r3, r1, 0x8
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r2, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r2, GPR1_OFFSET(r1)
|
||||
/*
|
||||
* Call High Level signal handling code
|
||||
*/
|
||||
bl _ThreadProcessSignalsFromIrq
|
||||
/*
|
||||
* start restoring exception like frame
|
||||
*/
|
||||
lwz r31, EXC_CTR_OFFSET(r1)
|
||||
lwz r30, EXC_XER_OFFSET(r1)
|
||||
lwz r29, EXC_CR_OFFSET(r1)
|
||||
lwz r28, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r31
|
||||
mtxer r30
|
||||
mtcr r29
|
||||
mtlr r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Make path non recoverable...
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
switch:
|
||||
#if ( PPC_HAS_FPU != 0 )
|
||||
#if ! defined( CPU_USE_DEFERRED_FP_SWITCH )
|
||||
#error missing include file???
|
||||
#endif
|
||||
mfmsr r4
|
||||
#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
|
||||
/* if the executing thread has FP enabled propagate
|
||||
* this now so _Thread_Dispatch can save/restore the FPREGS
|
||||
* NOTE: it is *crucial* to disable the FPU across the
|
||||
* user ISR [independent of using the 'deferred'
|
||||
* strategy or not]. We don't save FP regs across
|
||||
* the user ISR and hence we prefer an exception to
|
||||
* be raised rather than experiencing corruption.
|
||||
*/
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
rlwimi r4, r3, 0, 18, 18 /* MSR_FP */
|
||||
#else
|
||||
ori r4, r4, MSR_FP
|
||||
#endif
|
||||
mtmsr r4
|
||||
#endif
|
||||
bl SYM (_Thread_Dispatch)
|
||||
|
||||
easy_exit:
|
||||
/*
|
||||
* start restoring interrupt frame
|
||||
*/
|
||||
lwz r3, EXC_CTR_OFFSET(r1)
|
||||
lwz r4, EXC_XER_OFFSET(r1)
|
||||
lwz r5, EXC_CR_OFFSET(r1)
|
||||
lwz r6, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r3
|
||||
mtxer r4
|
||||
mtcr r5
|
||||
mtlr r6
|
||||
|
||||
lwz r15, GPR15_OFFSET(r1)
|
||||
lwz r14, GPR14_OFFSET(r1)
|
||||
lwz r13, GPR13_OFFSET(r1)
|
||||
lwz r12, GPR12_OFFSET(r1)
|
||||
lwz r11, GPR11_OFFSET(r1)
|
||||
lwz r10, GPR10_OFFSET(r1)
|
||||
lwz r9, GPR9_OFFSET(r1)
|
||||
lwz r8, GPR8_OFFSET(r1)
|
||||
lwz r7, GPR7_OFFSET(r1)
|
||||
lwz r6, GPR6_OFFSET(r1)
|
||||
lwz r5, GPR5_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable nested exception processing, data and instruction
|
||||
* translation.
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r4, SRR1_FRAME_OFFSET(r1)
|
||||
lwz r2, SRR0_FRAME_OFFSET(r1)
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
mtsrr1 r4
|
||||
mtsrr0 r2
|
||||
lwz r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,163 +0,0 @@
|
||||
/* irq_init.c
|
||||
*
|
||||
* This file contains the implementation of rtems initialization
|
||||
* related to interrupt handling.
|
||||
*
|
||||
* CopyRight (C) 2001 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <bsp/8xx_immap.h>
|
||||
#include <bsp/mbx.h>
|
||||
#include <bsp/commproc.h>
|
||||
|
||||
extern unsigned int external_exception_vector_prolog_code_size;
|
||||
extern void external_exception_vector_prolog_code(void);
|
||||
extern unsigned int decrementer_exception_vector_prolog_code_size;
|
||||
extern void decrementer_exception_vector_prolog_code(void);
|
||||
|
||||
volatile unsigned int ppc_cached_irq_mask;
|
||||
|
||||
/*
|
||||
* default on/off function
|
||||
*/
|
||||
static void nop_func1(void *unused){}
|
||||
static void nop_func2(void){}
|
||||
|
||||
/*
|
||||
* default isOn function
|
||||
*/
|
||||
static int not_connected(void) {return 0;}
|
||||
/*
|
||||
* default possible isOn function
|
||||
*/
|
||||
static int connected(void) {return 1;}
|
||||
|
||||
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
|
||||
static rtems_irq_global_settings initial_config;
|
||||
static rtems_irq_connect_data defaultIrq = {
|
||||
/* vectorIdex, hdl , handle , on , off , isOn */
|
||||
0, nop_func1 , 0 , nop_func2 , nop_func2 , not_connected
|
||||
};
|
||||
static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
|
||||
/*
|
||||
* actual rpiorities for interrupt :
|
||||
* 0 means that only current interrupt is masked
|
||||
* 255 means all other interrupts are masked
|
||||
*/
|
||||
/*
|
||||
* SIU interrupts.
|
||||
*/
|
||||
7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0,
|
||||
/*
|
||||
* CPM Interrupts
|
||||
*/
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
/*
|
||||
* Processor exceptions handled as interrupts
|
||||
*/
|
||||
0
|
||||
};
|
||||
|
||||
void BSP_SIU_irq_init(void)
|
||||
{
|
||||
/*
|
||||
* In theory we should initialize two registers at least :
|
||||
* SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But
|
||||
* we should take care that a monitor may have restoreed to another value.
|
||||
* If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT
|
||||
* please feel free to add it here.
|
||||
*/
|
||||
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0;
|
||||
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000;
|
||||
ppc_cached_irq_mask = 0;
|
||||
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize CPM interrupt management
|
||||
*/
|
||||
void
|
||||
BSP_CPM_irq_init(void)
|
||||
{
|
||||
/*
|
||||
* Initialize the CPM interrupt controller.
|
||||
*/
|
||||
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
|
||||
#ifdef mpc860
|
||||
(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
|
||||
#else
|
||||
(CICR_SCB_SCC2 | CICR_SCA_SCC1) |
|
||||
#endif
|
||||
((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
|
||||
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
|
||||
|
||||
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
|
||||
}
|
||||
|
||||
void BSP_rtems_irq_mng_init(unsigned cpuId)
|
||||
{
|
||||
rtems_raw_except_connect_data vectorDesc;
|
||||
int i;
|
||||
|
||||
BSP_SIU_irq_init();
|
||||
BSP_CPM_irq_init();
|
||||
/*
|
||||
* Initialize Rtems management interrupt table
|
||||
*/
|
||||
/*
|
||||
* re-init the rtemsIrq table
|
||||
*/
|
||||
for (i = 0; i < BSP_IRQ_NUMBER; i++) {
|
||||
rtemsIrq[i] = defaultIrq;
|
||||
rtemsIrq[i].name = i;
|
||||
}
|
||||
/*
|
||||
* Init initial Interrupt management config
|
||||
*/
|
||||
initial_config.irqNb = BSP_IRQ_NUMBER;
|
||||
initial_config.defaultEntry = defaultIrq;
|
||||
initial_config.irqHdlTbl = rtemsIrq;
|
||||
initial_config.irqBase = BSP_LOWEST_OFFSET;
|
||||
initial_config.irqPrioTbl = irqPrioTable;
|
||||
|
||||
if (!BSP_rtems_irq_mngt_set(&initial_config)) {
|
||||
/*
|
||||
* put something here that will show the failure...
|
||||
*/
|
||||
BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* We must connect the raw irq handler for the two
|
||||
* expected interrupt sources : decrementer and external interrupts.
|
||||
*/
|
||||
vectorDesc.exceptIndex = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size;
|
||||
vectorDesc.on = nop_func2;
|
||||
vectorDesc.off = nop_func2;
|
||||
vectorDesc.isOn = connected;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
|
||||
}
|
||||
vectorDesc.exceptIndex = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS external raw exception\n");
|
||||
}
|
||||
#ifdef TRACE_IRQ_INIT
|
||||
printk("RTEMS IRQ management is now operationnal\n");
|
||||
#endif
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* (c) 1999, Eric Valette valette@crf.canon.fr
|
||||
*
|
||||
*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* exception veneers for RTEMS.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
.p2align 5
|
||||
|
||||
PUBLIC_VAR(default_exception_vector_code_prolog)
|
||||
SYM (default_exception_vector_code_prolog):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r3, GPR3_OFFSET(r1)
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
mflr r2
|
||||
stw r2, EXC_LR_OFFSET(r1)
|
||||
bl 0f
|
||||
0: /*
|
||||
* r3 = exception vector entry point
|
||||
* (256 * vector number) + few instructions
|
||||
*/
|
||||
mflr r3
|
||||
/*
|
||||
* r3 = r3 >> 8 = vector
|
||||
*/
|
||||
srwi r3,r3,8
|
||||
#ifdef THIS_CODE_LINKED_USING_FLASH_ADDR_RANGE
|
||||
lis r2,push_normalized_frame@h
|
||||
ori r2,r2,push_normalized_frame@l
|
||||
mtlr r2
|
||||
blr
|
||||
#else
|
||||
ba push_normalized_frame
|
||||
#endif
|
||||
|
||||
PUBLIC_VAR (default_exception_vector_code_prolog_size)
|
||||
|
||||
default_exception_vector_code_prolog_size= . - default_exception_vector_code_prolog
|
||||
|
||||
.p2align 5
|
||||
PUBLIC_VAR (push_normalized_frame)
|
||||
SYM (push_normalized_frame):
|
||||
stw r3, EXCEPTION_NUMBER_OFFSET(r1)
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
mfsrr0 r2
|
||||
stw r2, SRR0_FRAME_OFFSET(r1)
|
||||
mfsrr1 r3
|
||||
stw r3, SRR1_FRAME_OFFSET(r1)
|
||||
/*
|
||||
* Save general purpose registers
|
||||
* Already saved in prolog : R1, R2, R3, LR.
|
||||
* Saved a few line above : R0
|
||||
*
|
||||
* Manual says that "stmw" instruction may be slower than
|
||||
* series of individual "stw" but who cares about performance
|
||||
* for the DEFAULT exception handler?
|
||||
*/
|
||||
stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */
|
||||
|
||||
mfcr r31
|
||||
stw r31, EXC_CR_OFFSET(r1)
|
||||
mfctr r30
|
||||
stw r30, EXC_CTR_OFFSET(r1)
|
||||
mfxer r28
|
||||
stw r28, EXC_XER_OFFSET(r1)
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r2, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r2, GPR1_OFFSET(r1)
|
||||
/*
|
||||
* Enable data and instruction address translation, exception nesting
|
||||
*/
|
||||
mfmsr r3
|
||||
ori r3,r3, MSR_RI | MSR_IR | MSR_DR
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Call C exception handler
|
||||
*/
|
||||
/*
|
||||
* store the execption frame address in r3 (first param)
|
||||
*/
|
||||
addi r3, r1, 0x8
|
||||
/*
|
||||
* globalExceptHdl(r3)
|
||||
*/
|
||||
addis r4, 0, globalExceptHdl@ha
|
||||
lwz r5, globalExceptHdl@l(r4)
|
||||
mtlr r5
|
||||
blrl
|
||||
/*
|
||||
* Restore registers status
|
||||
*/
|
||||
lwz r31, EXC_CR_OFFSET(r1)
|
||||
mtcr r31
|
||||
lwz r30, EXC_CTR_OFFSET(r1)
|
||||
mtctr r30
|
||||
lwz r29, EXC_LR_OFFSET(r1)
|
||||
mtlr r29
|
||||
lwz r28, EXC_XER_OFFSET(r1)
|
||||
mtxer r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Make path non recoverable...
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* vectors.h Exception frame related contant and API.
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#ifndef LIBBSP_POWERPC_MBX8XX_VECTORS_H
|
||||
#define LIBBSP_POWERPC_MBX8XX_VECTORS_H
|
||||
|
||||
/*
|
||||
* The callee (high level exception code written in C)
|
||||
* will store the Link Registers (return address) at entry r1 + 4 !!!.
|
||||
* So let room for it!!!.
|
||||
*/
|
||||
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
|
||||
#define SRR0_FRAME_OFFSET 8
|
||||
#define SRR1_FRAME_OFFSET 12
|
||||
#define EXCEPTION_NUMBER_OFFSET 16
|
||||
#define GPR0_OFFSET 20
|
||||
#define GPR1_OFFSET 24
|
||||
#define GPR2_OFFSET 28
|
||||
#define GPR3_OFFSET 32
|
||||
#define GPR4_OFFSET 36
|
||||
#define GPR5_OFFSET 40
|
||||
#define GPR6_OFFSET 44
|
||||
#define GPR7_OFFSET 48
|
||||
#define GPR8_OFFSET 52
|
||||
#define GPR9_OFFSET 56
|
||||
#define GPR10_OFFSET 60
|
||||
#define GPR11_OFFSET 64
|
||||
#define GPR12_OFFSET 68
|
||||
#define GPR13_OFFSET 72
|
||||
#define GPR14_OFFSET 76
|
||||
#define GPR15_OFFSET 80
|
||||
#define GPR16_OFFSET 84
|
||||
#define GPR17_OFFSET 88
|
||||
#define GPR18_OFFSET 92
|
||||
#define GPR19_OFFSET 96
|
||||
#define GPR20_OFFSET 100
|
||||
#define GPR21_OFFSET 104
|
||||
#define GPR22_OFFSET 108
|
||||
#define GPR23_OFFSET 112
|
||||
#define GPR24_OFFSET 116
|
||||
#define GPR25_OFFSET 120
|
||||
#define GPR26_OFFSET 124
|
||||
#define GPR27_OFFSET 128
|
||||
#define GPR28_OFFSET 132
|
||||
#define GPR29_OFFSET 136
|
||||
#define GPR30_OFFSET 140
|
||||
#define GPR31_OFFSET 144
|
||||
#define EXC_CR_OFFSET 148
|
||||
#define EXC_CTR_OFFSET 152
|
||||
#define EXC_XER_OFFSET 156
|
||||
#define EXC_LR_OFFSET 160
|
||||
#define EXC_DAR_OFFSET 164
|
||||
/*
|
||||
* maintain the EABI requested 8 bytes aligment
|
||||
* As SVR4 ABI requires 16, make it 16 (as some
|
||||
* exception may need more registers to be processed...)
|
||||
*/
|
||||
#define EXCEPTION_FRAME_END 176
|
||||
|
||||
#ifndef ASM
|
||||
/*
|
||||
* default raw exception handlers
|
||||
*/
|
||||
|
||||
extern void default_exception_vector_code_prolog();
|
||||
extern int default_exception_vector_code_prolog_size;
|
||||
|
||||
/* codemove is like memmove, but it also gets the cache line size
|
||||
* as 4th parameter to synchronize them. If this last parameter is
|
||||
* zero, it performs more or less like memmove. No copy is performed if
|
||||
* source and destination addresses are equal. However the caches
|
||||
* are synchronized. Note that the size is always rounded up to the
|
||||
* next mutiple of 4.
|
||||
*/
|
||||
extern void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
extern void initialize_exceptions();
|
||||
|
||||
typedef struct {
|
||||
unsigned EXC_SRR0;
|
||||
unsigned EXC_SRR1;
|
||||
unsigned _EXC_number;
|
||||
unsigned GPR0;
|
||||
unsigned GPR1;
|
||||
unsigned GPR2;
|
||||
unsigned GPR3;
|
||||
unsigned GPR4;
|
||||
unsigned GPR5;
|
||||
unsigned GPR6;
|
||||
unsigned GPR7;
|
||||
unsigned GPR8;
|
||||
unsigned GPR9;
|
||||
unsigned GPR10;
|
||||
unsigned GPR11;
|
||||
unsigned GPR12;
|
||||
unsigned GPR13;
|
||||
unsigned GPR14;
|
||||
unsigned GPR15;
|
||||
unsigned GPR16;
|
||||
unsigned GPR17;
|
||||
unsigned GPR18;
|
||||
unsigned GPR19;
|
||||
unsigned GPR20;
|
||||
unsigned GPR21;
|
||||
unsigned GPR22;
|
||||
unsigned GPR23;
|
||||
unsigned GPR24;
|
||||
unsigned GPR25;
|
||||
unsigned GPR26;
|
||||
unsigned GPR27;
|
||||
unsigned GPR28;
|
||||
unsigned GPR29;
|
||||
unsigned GPR30;
|
||||
unsigned GPR31;
|
||||
unsigned EXC_CR;
|
||||
unsigned EXC_CTR;
|
||||
unsigned EXC_XER;
|
||||
unsigned EXC_LR;
|
||||
unsigned EXC_MSR;
|
||||
unsigned EXC_DAR;
|
||||
}BSP_Exception_frame;
|
||||
|
||||
typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr);
|
||||
extern exception_handler_t globalExceptHdl;
|
||||
/*
|
||||
* Compatibility with pc386
|
||||
*/
|
||||
typedef BSP_Exception_frame CPU_Exception_frame;
|
||||
typedef exception_handler_t cpuExcHandlerType;
|
||||
|
||||
#endif /* ASM */
|
||||
|
||||
#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* vectors_init.c Exception hanlding initialisation (and generic handler).
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
static rtems_raw_except_global_settings exception_config;
|
||||
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
|
||||
|
||||
exception_handler_t globalExceptHdl;
|
||||
|
||||
void C_exception_handler(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
int recoverable = 0;
|
||||
|
||||
printk("exception handler called for exception %d\n", excPtr->_EXC_number);
|
||||
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
|
||||
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
|
||||
printk("\t R0 = %x\n", excPtr->GPR0);
|
||||
printk("\t R1 = %x\n", excPtr->GPR1);
|
||||
printk("\t R2 = %x\n", excPtr->GPR2);
|
||||
printk("\t R3 = %x\n", excPtr->GPR3);
|
||||
printk("\t R4 = %x\n", excPtr->GPR4);
|
||||
printk("\t R5 = %x\n", excPtr->GPR5);
|
||||
printk("\t R6 = %x\n", excPtr->GPR6);
|
||||
printk("\t R7 = %x\n", excPtr->GPR7);
|
||||
printk("\t R8 = %x\n", excPtr->GPR8);
|
||||
printk("\t R9 = %x\n", excPtr->GPR9);
|
||||
printk("\t R10 = %x\n", excPtr->GPR10);
|
||||
printk("\t R11 = %x\n", excPtr->GPR11);
|
||||
printk("\t R12 = %x\n", excPtr->GPR12);
|
||||
printk("\t R13 = %x\n", excPtr->GPR13);
|
||||
printk("\t R14 = %x\n", excPtr->GPR14);
|
||||
printk("\t R15 = %x\n", excPtr->GPR15);
|
||||
printk("\t R16 = %x\n", excPtr->GPR16);
|
||||
printk("\t R17 = %x\n", excPtr->GPR17);
|
||||
printk("\t R18 = %x\n", excPtr->GPR18);
|
||||
printk("\t R19 = %x\n", excPtr->GPR19);
|
||||
printk("\t R20 = %x\n", excPtr->GPR20);
|
||||
printk("\t R21 = %x\n", excPtr->GPR21);
|
||||
printk("\t R22 = %x\n", excPtr->GPR22);
|
||||
printk("\t R23 = %x\n", excPtr->GPR23);
|
||||
printk("\t R24 = %x\n", excPtr->GPR24);
|
||||
printk("\t R25 = %x\n", excPtr->GPR25);
|
||||
printk("\t R26 = %x\n", excPtr->GPR26);
|
||||
printk("\t R27 = %x\n", excPtr->GPR27);
|
||||
printk("\t R28 = %x\n", excPtr->GPR28);
|
||||
printk("\t R29 = %x\n", excPtr->GPR29);
|
||||
printk("\t R30 = %x\n", excPtr->GPR30);
|
||||
printk("\t R31 = %x\n", excPtr->GPR31);
|
||||
printk("\t CR = %x\n", excPtr->EXC_CR);
|
||||
printk("\t CTR = %x\n", excPtr->EXC_CTR);
|
||||
printk("\t XER = %x\n", excPtr->EXC_XER);
|
||||
printk("\t LR = %x\n", excPtr->EXC_LR);
|
||||
printk("\t MSR = %x\n", excPtr->EXC_MSR);
|
||||
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
|
||||
recoverable = 1;
|
||||
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
|
||||
#ifdef TEST_RAW_EXCEPTION_CODE
|
||||
recoverable = 1;
|
||||
#else
|
||||
recoverable = 0;
|
||||
#endif
|
||||
if (!recoverable) {
|
||||
printk("unrecoverable exception!!! Push reset button\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
void nop_except_enable(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
}
|
||||
int except_always_enabled(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void initialize_exceptions(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize pointer used by low level execption handling
|
||||
*/
|
||||
globalExceptHdl = C_exception_handler;
|
||||
/*
|
||||
* Put default_exception_vector_code_prolog at relevant exception
|
||||
* code entry addresses
|
||||
*/
|
||||
exception_config.exceptSize = LAST_VALID_EXC + 1;
|
||||
exception_config.rawExceptHdlTbl = &exception_table[0];
|
||||
exception_config.defaultRawEntry.exceptIndex = 0;
|
||||
exception_config.defaultRawEntry.hdl.vector = 0;
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog;
|
||||
/*
|
||||
* Note that next line the '&' before default_exception_vector_code_prolog_size
|
||||
* is not a bug as it is defined a .set directly in asm...
|
||||
*/
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) &default_exception_vector_code_prolog_size;
|
||||
for (i=0; i <= exception_config.exceptSize; i++) {
|
||||
printk("installing exception number %d\n", i);
|
||||
if (!ppc_vector_is_valid (i)) {
|
||||
continue;
|
||||
}
|
||||
#if 0 /* FIXME: refine this condition, leave Syscall for EPPCBug console */
|
||||
if (i == ASM_SYS_VECTOR) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
exception_table[i].exceptIndex = i;
|
||||
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
|
||||
exception_table[i].hdl.vector = i;
|
||||
exception_table[i].on = nop_except_enable;
|
||||
exception_table[i].off = nop_except_enable;
|
||||
exception_table[i].isOn = except_always_enabled;
|
||||
}
|
||||
if (!ppc_init_exceptions(&exception_config)) {
|
||||
/*
|
||||
* At this stage we may not call BSP_Panic because it uses exceptions!!!
|
||||
*/
|
||||
printk("Exception handling initialization failed\n");
|
||||
printk("System locked\n"); while(1);
|
||||
}
|
||||
else {
|
||||
printk("Exception handling initialization done\n");
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
2009-10-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* vectors/vectors.h, vectors/vectors_init.c, vectors/vectors.S,
|
||||
irq/irq_init.c, irq/irq_asm.S: Removed files.
|
||||
|
||||
2009-10-22 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* include/irq-config.h: New file.
|
||||
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* IRQ veneers for RTEMS.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* Modified to support the MCP750.
|
||||
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
|
||||
*
|
||||
* Modifications to store nesting level in global _ISR_Nest_level
|
||||
* variable instead of SPRG0. Andy Dachs <a.dachs@sstl.co.uk>
|
||||
*
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2005/4:
|
||||
* - DONT enable FP across user ISR since fpregs are never saved!!
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <bsp/vectors.h>
|
||||
#include <rtems/score/cpuopts.h> /* for PPC_HAS_FPU */
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <rtems/asm.h>
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
.p2align 5
|
||||
|
||||
PUBLIC_VAR(decrementer_exception_vector_prolog_code)
|
||||
|
||||
SYM (decrementer_exception_vector_prolog_code):
|
||||
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_DEC_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
|
||||
|
||||
decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
|
||||
|
||||
PUBLIC_VAR(external_exception_vector_prolog_code)
|
||||
|
||||
SYM (external_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_EXT_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (external_exception_vector_prolog_code_size)
|
||||
|
||||
external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
|
||||
|
||||
PUBLIC_VAR(shared_raw_irq_code_entry)
|
||||
PUBLIC_VAR(C_dispatch_irq_handler)
|
||||
|
||||
.p2align 5
|
||||
SYM (shared_raw_irq_code_entry):
|
||||
/*
|
||||
* Entry conditions :
|
||||
* Registers already saved : R1, R4
|
||||
* R1 : points to a location with enough room for the
|
||||
* interrupt frame
|
||||
* R4 : vector number
|
||||
*/
|
||||
/*
|
||||
* Save SRR0/SRR1 As soon As possible as it is the minimal needed
|
||||
* to reenable exception processing
|
||||
*/
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
stw r3, GPR3_OFFSET(r1)
|
||||
|
||||
mfsrr0 r0
|
||||
mfsrr1 r2
|
||||
mfmsr r3
|
||||
|
||||
stw r0, SRR0_FRAME_OFFSET(r1)
|
||||
stw r2, SRR1_FRAME_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Enable data and instruction address translation, exception recovery
|
||||
*
|
||||
* also, on CPUs with FP, enable FP so that FP context can be
|
||||
* saved and restored (using FP instructions)
|
||||
*/
|
||||
ori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Push C scratch registers on the current stack. It may
|
||||
* actually be the thread stack or the interrupt stack.
|
||||
* Anyway we have to make it in order to be able to call C/C++
|
||||
* functions. Depending on the nesting interrupt level, we will
|
||||
* switch to the right stack later.
|
||||
*/
|
||||
stw r5, GPR5_OFFSET(r1)
|
||||
stw r6, GPR6_OFFSET(r1)
|
||||
stw r7, GPR7_OFFSET(r1)
|
||||
stw r8, GPR8_OFFSET(r1)
|
||||
stw r9, GPR9_OFFSET(r1)
|
||||
stw r10, GPR10_OFFSET(r1)
|
||||
stw r11, GPR11_OFFSET(r1)
|
||||
stw r12, GPR12_OFFSET(r1)
|
||||
stw r13, GPR13_OFFSET(r1)
|
||||
|
||||
mfcr r5
|
||||
mfctr r6
|
||||
mfxer r7
|
||||
mflr r8
|
||||
|
||||
stw r5, EXC_CR_OFFSET(r1)
|
||||
stw r6, EXC_CTR_OFFSET(r1)
|
||||
stw r7, EXC_XER_OFFSET(r1)
|
||||
stw r8, EXC_LR_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Add some non volatile registers to store information
|
||||
* that will be used when returning from C handler
|
||||
*/
|
||||
stw r14, GPR14_OFFSET(r1)
|
||||
stw r15, GPR15_OFFSET(r1)
|
||||
/*
|
||||
* save current stack pointer location in R14
|
||||
*/
|
||||
addi r14, r1, 0
|
||||
/*
|
||||
* store part of _Thread_Dispatch_disable_level address in R15
|
||||
*/
|
||||
addis r15,0, _Thread_Dispatch_disable_level@ha
|
||||
/*
|
||||
* Get current nesting level in R2
|
||||
*/
|
||||
/* mfspr r2, SPRG0 */
|
||||
addis r6, 0, _ISR_Nest_level@ha
|
||||
lwz r2, _ISR_Nest_level@l( r6 )
|
||||
|
||||
/*
|
||||
* Check if stack switch is necessary
|
||||
*/
|
||||
cmpwi r2,0
|
||||
bne nested
|
||||
mfspr r1, SPRG1
|
||||
|
||||
nested:
|
||||
/*
|
||||
* Start Incrementing nesting level in R2
|
||||
*/
|
||||
addi r2,r2,1
|
||||
|
||||
addis r6, 0, _ISR_Nest_level@ha
|
||||
stw r2, _ISR_Nest_level@l( r6 )
|
||||
|
||||
/*
|
||||
* Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r6,_Thread_Dispatch_disable_level@l(r15)
|
||||
/*
|
||||
* store new nesting level in SPRG0
|
||||
*/
|
||||
/* mtspr SPRG0, r2 */
|
||||
|
||||
addi r6, r6, 1
|
||||
mfmsr r5
|
||||
/*
|
||||
* store new _Thread_Dispatch_disable_level value
|
||||
*/
|
||||
stw r6, _Thread_Dispatch_disable_level@l(r15)
|
||||
/*
|
||||
* We are now running on the interrupt stack. External and decrementer
|
||||
* exceptions are still disabled. I see no purpose trying to optimize
|
||||
* further assembler code.
|
||||
*/
|
||||
/*
|
||||
* Call C exception handler for decrementer Interrupt frame is passed just
|
||||
* in case...
|
||||
*/
|
||||
|
||||
addi r3, r14, 0x8
|
||||
bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
|
||||
|
||||
/*
|
||||
* start decrementing nesting level. Note : do not test result against 0
|
||||
* value as an easy exit condition because if interrupt nesting level > 1
|
||||
* then _Thread_Dispatch_disable_level > 1
|
||||
*/
|
||||
/* mfspr r2, SPRG0 */
|
||||
|
||||
addis r6, 0, _ISR_Nest_level@ha
|
||||
lwz r2, _ISR_Nest_level@l( r6 )
|
||||
|
||||
/*
|
||||
* start decrementing _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r3,_Thread_Dispatch_disable_level@l(r15)
|
||||
addi r2, r2, -1 /* Continue decrementing nesting level */
|
||||
addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
|
||||
|
||||
stw r2, _ISR_Nest_level@l( r6 )
|
||||
/* mtspr SPRG0, r2 */ /* End decrementing nesting level */
|
||||
|
||||
stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
|
||||
cmpwi r3, 0
|
||||
/*
|
||||
* switch back to original stack (done here just optimize registers
|
||||
* contention. Could have been done before...)
|
||||
*/
|
||||
addi r1, r14, 0
|
||||
bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
|
||||
/*
|
||||
* Here we are running again on the thread system stack.
|
||||
* We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
|
||||
* Interrupt are still disabled. Time to check if scheduler request to
|
||||
* do something with the current thread...
|
||||
*/
|
||||
addis r4, 0, _Context_Switch_necessary@ha
|
||||
lbz r5, _Context_Switch_necessary@l(r4)
|
||||
cmpwi r5, 0
|
||||
bne switch
|
||||
|
||||
addis r6, 0, _ISR_Signals_to_thread_executing@ha
|
||||
lbz r7, _ISR_Signals_to_thread_executing@l(r6)
|
||||
cmpwi r7, 0
|
||||
li r8, 0
|
||||
beq easy_exit
|
||||
stb r8, _ISR_Signals_to_thread_executing@l(r6)
|
||||
/*
|
||||
* going to call _ThreadProcessSignalsFromIrq
|
||||
* Push a complete exception like frame...
|
||||
*/
|
||||
stmw r16, GPR16_OFFSET(r1)
|
||||
addi r3, r1, 0x8
|
||||
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r2, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r2, GPR1_OFFSET(r1)
|
||||
/*
|
||||
* Call High Level signal handling code
|
||||
*/
|
||||
bl _ThreadProcessSignalsFromIrq
|
||||
|
||||
/*
|
||||
* start restoring exception like frame
|
||||
*/
|
||||
lwz r31, EXC_CTR_OFFSET(r1)
|
||||
lwz r30, EXC_XER_OFFSET(r1)
|
||||
lwz r29, EXC_CR_OFFSET(r1)
|
||||
lwz r28, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r31
|
||||
mtxer r30
|
||||
mtcr r29
|
||||
mtlr r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Make path non recoverable...
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
switch:
|
||||
#if ( PPC_HAS_FPU != 0 )
|
||||
#if ! defined( CPU_USE_DEFERRED_FP_SWITCH )
|
||||
#error missing include file???
|
||||
#endif
|
||||
mfmsr r4
|
||||
#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
|
||||
/* if the executing thread has FP enabled propagate
|
||||
* this now so _Thread_Dispatch can save/restore the FPREGS
|
||||
* NOTE: it is *crucial* to disable the FPU across the
|
||||
* user ISR [independent of using the 'deferred'
|
||||
* strategy or not]. We don't save FP regs across
|
||||
* the user ISR and hence we prefer an exception to
|
||||
* be raised rather than experiencing corruption.
|
||||
*/
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
rlwimi r4, r3, 0, 18, 18 /* MSR_FP */
|
||||
#else
|
||||
ori r4, r4, MSR_FP
|
||||
#endif
|
||||
mtmsr r4
|
||||
#endif
|
||||
bl SYM (_Thread_Dispatch)
|
||||
|
||||
easy_exit:
|
||||
/*
|
||||
* start restoring interrupt frame
|
||||
*/
|
||||
lwz r3, EXC_CTR_OFFSET(r1)
|
||||
lwz r4, EXC_XER_OFFSET(r1)
|
||||
lwz r5, EXC_CR_OFFSET(r1)
|
||||
lwz r6, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r3
|
||||
mtxer r4
|
||||
mtcr r5
|
||||
mtlr r6
|
||||
|
||||
lwz r15, GPR15_OFFSET(r1)
|
||||
lwz r14, GPR14_OFFSET(r1)
|
||||
lwz r13, GPR13_OFFSET(r1)
|
||||
lwz r12, GPR12_OFFSET(r1)
|
||||
lwz r11, GPR11_OFFSET(r1)
|
||||
lwz r10, GPR10_OFFSET(r1)
|
||||
lwz r9, GPR9_OFFSET(r1)
|
||||
lwz r8, GPR8_OFFSET(r1)
|
||||
lwz r7, GPR7_OFFSET(r1)
|
||||
lwz r6, GPR6_OFFSET(r1)
|
||||
lwz r5, GPR5_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable nested exception processing, data and instruction
|
||||
* translation.
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r4, SRR1_FRAME_OFFSET(r1)
|
||||
lwz r2, SRR0_FRAME_OFFSET(r1)
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
mtsrr1 r4
|
||||
mtsrr0 r2
|
||||
lwz r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,152 +0,0 @@
|
||||
/* irq_init.c
|
||||
*
|
||||
* This file contains the implementation of rtems initialization
|
||||
* related to interrupt handling.
|
||||
*
|
||||
* CopyRight (C) 2001 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
/*
|
||||
#include <bsp/8xx_immap.h>
|
||||
#include <bsp/mbx.h>
|
||||
#include <bsp/commproc.h>
|
||||
*/
|
||||
|
||||
extern unsigned int external_exception_vector_prolog_code_size;
|
||||
extern void external_exception_vector_prolog_code(void);
|
||||
extern unsigned int decrementer_exception_vector_prolog_code_size;
|
||||
extern void decrementer_exception_vector_prolog_code(void);
|
||||
|
||||
extern void BSP_panic(char *s);
|
||||
extern void _BSP_Fatal_error(unsigned int v);
|
||||
/*
|
||||
volatile unsigned int ppc_cached_irq_mask;
|
||||
*/
|
||||
|
||||
/*
|
||||
* default on/off function
|
||||
*/
|
||||
static void nop_func(void){}
|
||||
/*
|
||||
* default isOn function
|
||||
*/
|
||||
static int not_connected(void) {return 0;}
|
||||
/*
|
||||
* default possible isOn function
|
||||
*/
|
||||
static int connected(void) {return 1;}
|
||||
|
||||
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
|
||||
static rtems_irq_global_settings initial_config;
|
||||
static rtems_irq_connect_data defaultIrq = {
|
||||
/* vectorIdex, hdl , handle , on , off , isOn */
|
||||
0, nop_func , NULL , nop_func , nop_func , not_connected
|
||||
};
|
||||
|
||||
/*
|
||||
List the interrupts is their order of priority (highest first).
|
||||
This does not have to be the same order as the siprr settings but
|
||||
without knowing more about the application they are kept the same.
|
||||
*/
|
||||
|
||||
static rtems_irq_prio irqPrioTable[BSP_CPM_IRQ_NUMBER]={
|
||||
/*
|
||||
* actual priorities for interrupt :
|
||||
*/
|
||||
/*
|
||||
* CPM Interrupts
|
||||
*/
|
||||
0, 45, 63, 44, 66, 68, 35, 39, 50, 62, 34, 0, 30, 40, 52, 58,
|
||||
2, 3, 0, 5, 15, 16, 17, 18, 49, 51, 0, 0, 0, 0, 0, 0,
|
||||
6, 7, 8, 0, 11, 12, 0, 0, 20, 21, 22, 23, 0, 0, 0, 0,
|
||||
29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57, 60, 64, 65, 69, 70,
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize CPM interrupt management
|
||||
*/
|
||||
void
|
||||
BSP_CPM_irq_init(void)
|
||||
{
|
||||
m8260.simr_l = 0;
|
||||
m8260.simr_h = 0;
|
||||
m8260.sipnr_l = 0xffffffff;
|
||||
m8260.sipnr_h = 0xffffffff;
|
||||
m8260.sicr = 0;
|
||||
|
||||
/*
|
||||
* Initialize the interrupt priorities.
|
||||
*/
|
||||
m8260.siprr = 0x05309770; /* reset value */
|
||||
m8260.scprr_h = 0x05309770; /* reset value */
|
||||
m8260.scprr_l = 0x05309770; /* reset value */
|
||||
|
||||
}
|
||||
|
||||
void BSP_rtems_irq_mng_init(unsigned cpuId)
|
||||
{
|
||||
rtems_raw_except_connect_data vectorDesc;
|
||||
int i;
|
||||
|
||||
BSP_CPM_irq_init();
|
||||
/*
|
||||
* Initialize Rtems management interrupt table
|
||||
*/
|
||||
/*
|
||||
* re-init the rtemsIrq table
|
||||
*/
|
||||
for (i = 0; i < BSP_IRQ_NUMBER; i++) {
|
||||
rtemsIrq[i] = defaultIrq;
|
||||
rtemsIrq[i].name = i;
|
||||
}
|
||||
/*
|
||||
* Init initial Interrupt management config
|
||||
*/
|
||||
initial_config.irqNb = BSP_IRQ_NUMBER;
|
||||
initial_config.defaultEntry = defaultIrq;
|
||||
initial_config.irqHdlTbl = rtemsIrq;
|
||||
initial_config.irqBase = BSP_LOWEST_OFFSET;
|
||||
initial_config.irqPrioTbl = irqPrioTable;
|
||||
|
||||
if (!BSP_rtems_irq_mngt_set(&initial_config)) {
|
||||
/*
|
||||
* put something here that will show the failure...
|
||||
*/
|
||||
BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* We must connect the raw irq handler for the two
|
||||
* expected interrupt sources : decrementer and external interrupts.
|
||||
*/
|
||||
vectorDesc.exceptIndex = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size;
|
||||
vectorDesc.on = nop_func;
|
||||
vectorDesc.off = nop_func;
|
||||
vectorDesc.isOn = connected;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
|
||||
}
|
||||
vectorDesc.exceptIndex = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS external raw exception\n");
|
||||
}
|
||||
#ifdef TRACE_IRQ_INIT
|
||||
printk("RTEMS IRQ management is now operationnal\n");
|
||||
#endif
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* (c) 1999, Eric Valette valette@crf.canon.fr
|
||||
*
|
||||
*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* exception veneers for RTEMS.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
.p2align 5
|
||||
|
||||
PUBLIC_VAR(default_exception_vector_code_prolog)
|
||||
SYM (default_exception_vector_code_prolog):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r3, GPR3_OFFSET(r1)
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
mflr r2
|
||||
stw r2, EXC_LR_OFFSET(r1)
|
||||
bl 0f
|
||||
0: /*
|
||||
* r3 = exception vector entry point
|
||||
* (256 * vector number) + few instructions
|
||||
*/
|
||||
mflr r3
|
||||
/*
|
||||
* r3 = r3 >> 8 = vector
|
||||
*/
|
||||
srwi r3,r3,8
|
||||
ba push_normalized_frame
|
||||
|
||||
PUBLIC_VAR (default_exception_vector_code_prolog_size)
|
||||
|
||||
default_exception_vector_code_prolog_size= . - default_exception_vector_code_prolog
|
||||
|
||||
.p2align 5
|
||||
PUBLIC_VAR (push_normalized_frame)
|
||||
SYM (push_normalized_frame):
|
||||
stw r3, EXCEPTION_NUMBER_OFFSET(r1)
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
mfsrr0 r2
|
||||
stw r2, SRR0_FRAME_OFFSET(r1)
|
||||
mfsrr1 r3
|
||||
stw r3, SRR1_FRAME_OFFSET(r1)
|
||||
/*
|
||||
* Save general purpose registers
|
||||
* Already saved in prolog : R1, R2, R3, LR.
|
||||
* Saved a few line above : R0
|
||||
*
|
||||
* Manual says that "stmw" instruction may be slower than
|
||||
* series of individual "stw" but who cares about performance
|
||||
* for the DEFAULT exception handler?
|
||||
*/
|
||||
stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */
|
||||
|
||||
mfcr r31
|
||||
stw r31, EXC_CR_OFFSET(r1)
|
||||
mfctr r30
|
||||
stw r30, EXC_CTR_OFFSET(r1)
|
||||
mfxer r28
|
||||
stw r28, EXC_XER_OFFSET(r1)
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r2, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r2, GPR1_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Enable data and instruction address translation, exception nesting
|
||||
*/
|
||||
mfmsr r3
|
||||
ori r3,r3, MSR_RI /*| MSR_IR | MSR_DR*/
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Call C exception handler
|
||||
*/
|
||||
/*
|
||||
* store the execption frame address in r3 (first param)
|
||||
*/
|
||||
addi r3, r1, 0x8
|
||||
/*
|
||||
* globalExceptHdl(r3)
|
||||
*/
|
||||
addis r4, 0, globalExceptHdl@ha
|
||||
lwz r5, globalExceptHdl@l(r4)
|
||||
mtlr r5
|
||||
blrl
|
||||
/*
|
||||
* Restore registers status
|
||||
*/
|
||||
lwz r31, EXC_CR_OFFSET(r1)
|
||||
mtcr r31
|
||||
lwz r30, EXC_CTR_OFFSET(r1)
|
||||
mtctr r30
|
||||
lwz r29, EXC_LR_OFFSET(r1)
|
||||
mtlr r29
|
||||
lwz r28, EXC_XER_OFFSET(r1)
|
||||
mtxer r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Make path non recoverable...
|
||||
*/
|
||||
mfmsr r3
|
||||
xori r3, r3, MSR_RI /*| MSR_IR | MSR_DR*/
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* vectors.h Exception frame related contant and API.
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#ifndef LIBBSP_POWERPC_MBX8XX_VECTORS_H
|
||||
#define LIBBSP_POWERPC_MBX8XX_VECTORS_H
|
||||
|
||||
/*
|
||||
* The callee (high level exception code written in C)
|
||||
* will store the Link Registers (return address) at entry r1 + 4 !!!.
|
||||
* So let room for it!!!.
|
||||
*/
|
||||
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
|
||||
#define SRR0_FRAME_OFFSET 8
|
||||
#define SRR1_FRAME_OFFSET 12
|
||||
#define EXCEPTION_NUMBER_OFFSET 16
|
||||
#define GPR0_OFFSET 20
|
||||
#define GPR1_OFFSET 24
|
||||
#define GPR2_OFFSET 28
|
||||
#define GPR3_OFFSET 32
|
||||
#define GPR4_OFFSET 36
|
||||
#define GPR5_OFFSET 40
|
||||
#define GPR6_OFFSET 44
|
||||
#define GPR7_OFFSET 48
|
||||
#define GPR8_OFFSET 52
|
||||
#define GPR9_OFFSET 56
|
||||
#define GPR10_OFFSET 60
|
||||
#define GPR11_OFFSET 64
|
||||
#define GPR12_OFFSET 68
|
||||
#define GPR13_OFFSET 72
|
||||
#define GPR14_OFFSET 76
|
||||
#define GPR15_OFFSET 80
|
||||
#define GPR16_OFFSET 84
|
||||
#define GPR17_OFFSET 88
|
||||
#define GPR18_OFFSET 92
|
||||
#define GPR19_OFFSET 96
|
||||
#define GPR20_OFFSET 100
|
||||
#define GPR21_OFFSET 104
|
||||
#define GPR22_OFFSET 108
|
||||
#define GPR23_OFFSET 112
|
||||
#define GPR24_OFFSET 116
|
||||
#define GPR25_OFFSET 120
|
||||
#define GPR26_OFFSET 124
|
||||
#define GPR27_OFFSET 128
|
||||
#define GPR28_OFFSET 132
|
||||
#define GPR29_OFFSET 136
|
||||
#define GPR30_OFFSET 140
|
||||
#define GPR31_OFFSET 144
|
||||
#define EXC_CR_OFFSET 148
|
||||
#define EXC_CTR_OFFSET 152
|
||||
#define EXC_XER_OFFSET 156
|
||||
#define EXC_LR_OFFSET 160
|
||||
#define EXC_DAR_OFFSET 164
|
||||
/*
|
||||
* maintain the EABI requested 8 bytes aligment
|
||||
* As SVR4 ABI requires 16, make it 16 (as some
|
||||
* exception may need more registers to be processed...)
|
||||
*/
|
||||
#define EXCEPTION_FRAME_END 176
|
||||
|
||||
#ifndef ASM
|
||||
/*
|
||||
* default raw exception handlers
|
||||
*/
|
||||
|
||||
extern void default_exception_vector_code_prolog();
|
||||
extern int default_exception_vector_code_prolog_size;
|
||||
|
||||
/* codemove is like memmove, but it also gets the cache line size
|
||||
* as 4th parameter to synchronize them. If this last parameter is
|
||||
* zero, it performs more or less like memmove. No copy is performed if
|
||||
* source and destination addresses are equal. However the caches
|
||||
* are synchronized. Note that the size is always rounded up to the
|
||||
* next mutiple of 4.
|
||||
*/
|
||||
extern void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
extern void initialize_exceptions();
|
||||
|
||||
typedef struct {
|
||||
unsigned EXC_SRR0;
|
||||
unsigned EXC_SRR1;
|
||||
unsigned _EXC_number;
|
||||
unsigned GPR0;
|
||||
unsigned GPR1;
|
||||
unsigned GPR2;
|
||||
unsigned GPR3;
|
||||
unsigned GPR4;
|
||||
unsigned GPR5;
|
||||
unsigned GPR6;
|
||||
unsigned GPR7;
|
||||
unsigned GPR8;
|
||||
unsigned GPR9;
|
||||
unsigned GPR10;
|
||||
unsigned GPR11;
|
||||
unsigned GPR12;
|
||||
unsigned GPR13;
|
||||
unsigned GPR14;
|
||||
unsigned GPR15;
|
||||
unsigned GPR16;
|
||||
unsigned GPR17;
|
||||
unsigned GPR18;
|
||||
unsigned GPR19;
|
||||
unsigned GPR20;
|
||||
unsigned GPR21;
|
||||
unsigned GPR22;
|
||||
unsigned GPR23;
|
||||
unsigned GPR24;
|
||||
unsigned GPR25;
|
||||
unsigned GPR26;
|
||||
unsigned GPR27;
|
||||
unsigned GPR28;
|
||||
unsigned GPR29;
|
||||
unsigned GPR30;
|
||||
unsigned GPR31;
|
||||
unsigned EXC_CR;
|
||||
unsigned EXC_CTR;
|
||||
unsigned EXC_XER;
|
||||
unsigned EXC_LR;
|
||||
unsigned EXC_MSR;
|
||||
unsigned EXC_DAR;
|
||||
}BSP_Exception_frame;
|
||||
|
||||
typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr);
|
||||
extern exception_handler_t globalExceptHdl;
|
||||
/*
|
||||
* Compatibility with pc386
|
||||
*/
|
||||
typedef BSP_Exception_frame CPU_Exception_frame;
|
||||
typedef exception_handler_t cpuExcHandlerType;
|
||||
|
||||
#endif /* ASM */
|
||||
|
||||
#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* vectors_init.c Exception hanlding initialisation (and generic handler).
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
static rtems_raw_except_global_settings exception_config;
|
||||
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
|
||||
|
||||
exception_handler_t globalExceptHdl;
|
||||
|
||||
void C_exception_handler(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
int recoverable = 0;
|
||||
|
||||
printk("exception handler called for exception %d\n", excPtr->_EXC_number);
|
||||
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
|
||||
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
|
||||
printk("\t R0 = %x\n", excPtr->GPR0);
|
||||
printk("\t R1 = %x\n", excPtr->GPR1);
|
||||
printk("\t R2 = %x\n", excPtr->GPR2);
|
||||
printk("\t R3 = %x\n", excPtr->GPR3);
|
||||
printk("\t R4 = %x\n", excPtr->GPR4);
|
||||
printk("\t R5 = %x\n", excPtr->GPR5);
|
||||
printk("\t R6 = %x\n", excPtr->GPR6);
|
||||
printk("\t R7 = %x\n", excPtr->GPR7);
|
||||
printk("\t R8 = %x\n", excPtr->GPR8);
|
||||
printk("\t R9 = %x\n", excPtr->GPR9);
|
||||
printk("\t R10 = %x\n", excPtr->GPR10);
|
||||
printk("\t R11 = %x\n", excPtr->GPR11);
|
||||
printk("\t R12 = %x\n", excPtr->GPR12);
|
||||
printk("\t R13 = %x\n", excPtr->GPR13);
|
||||
printk("\t R14 = %x\n", excPtr->GPR14);
|
||||
printk("\t R15 = %x\n", excPtr->GPR15);
|
||||
printk("\t R16 = %x\n", excPtr->GPR16);
|
||||
printk("\t R17 = %x\n", excPtr->GPR17);
|
||||
printk("\t R18 = %x\n", excPtr->GPR18);
|
||||
printk("\t R19 = %x\n", excPtr->GPR19);
|
||||
printk("\t R20 = %x\n", excPtr->GPR20);
|
||||
printk("\t R21 = %x\n", excPtr->GPR21);
|
||||
printk("\t R22 = %x\n", excPtr->GPR22);
|
||||
printk("\t R23 = %x\n", excPtr->GPR23);
|
||||
printk("\t R24 = %x\n", excPtr->GPR24);
|
||||
printk("\t R25 = %x\n", excPtr->GPR25);
|
||||
printk("\t R26 = %x\n", excPtr->GPR26);
|
||||
printk("\t R27 = %x\n", excPtr->GPR27);
|
||||
printk("\t R28 = %x\n", excPtr->GPR28);
|
||||
printk("\t R29 = %x\n", excPtr->GPR29);
|
||||
printk("\t R30 = %x\n", excPtr->GPR30);
|
||||
printk("\t R31 = %x\n", excPtr->GPR31);
|
||||
printk("\t CR = %x\n", excPtr->EXC_CR);
|
||||
printk("\t CTR = %x\n", excPtr->EXC_CTR);
|
||||
printk("\t XER = %x\n", excPtr->EXC_XER);
|
||||
printk("\t LR = %x\n", excPtr->EXC_LR);
|
||||
printk("\t MSR = %x\n", excPtr->EXC_MSR);
|
||||
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
|
||||
recoverable = 1;
|
||||
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
|
||||
#ifdef TEST_RAW_EXCEPTION_CODE
|
||||
recoverable = 1;
|
||||
#else
|
||||
recoverable = 0;
|
||||
#endif
|
||||
if (!recoverable) {
|
||||
printk("unrecoverable exception!!! Push reset button\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
void nop_except_enable(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
}
|
||||
int except_always_enabled(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void initialize_exceptions(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize pointer used by low level execption handling
|
||||
*/
|
||||
globalExceptHdl = C_exception_handler;
|
||||
/*
|
||||
* Put default_exception_vector_code_prolog at relevant exception
|
||||
* code entry addresses
|
||||
*/
|
||||
exception_config.exceptSize = LAST_VALID_EXC + 1;
|
||||
exception_config.rawExceptHdlTbl = &exception_table[0];
|
||||
exception_config.defaultRawEntry.exceptIndex = 0;
|
||||
exception_config.defaultRawEntry.hdl.vector = 0;
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog;
|
||||
/*
|
||||
* Note that next line the '&' before default_exception_vector_code_prolog_size
|
||||
* is not a bug as it is defined a .set directly in asm...
|
||||
*/
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) &default_exception_vector_code_prolog_size;
|
||||
|
||||
/*
|
||||
_BSP_GPLED0_off();
|
||||
_BSP_GPLED1_on();
|
||||
*/
|
||||
|
||||
for (i=0; i <= exception_config.exceptSize; i++) {
|
||||
/*
|
||||
printk("installing exception number %d\n", i);
|
||||
*/
|
||||
if (!ppc_vector_is_valid (i)) {
|
||||
continue;
|
||||
}
|
||||
exception_table[i].exceptIndex = i;
|
||||
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
|
||||
exception_table[i].hdl.vector = i;
|
||||
exception_table[i].on = nop_except_enable;
|
||||
exception_table[i].off = nop_except_enable;
|
||||
exception_table[i].isOn = except_always_enabled;
|
||||
}
|
||||
|
||||
/* _BSP_GPLED0_on(); */
|
||||
|
||||
if (!ppc_init_exceptions(&exception_config)) {
|
||||
/*
|
||||
* At this stage we may not call BSP_Panic because it uses exceptions!!!
|
||||
*/
|
||||
printk("Exception handling initialization failed\n");
|
||||
printk("System locked\n"); while(1);
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
printk("Exception handling initialization done\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* _BSP_GPLED1_off(); */
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
The files:
|
||||
|
||||
irq.c, irq_asm.S
|
||||
|
||||
in this directory are DEPRECATED.
|
||||
|
||||
DO NOT COPY/MODIFY FOR NEW BSPs
|
||||
|
||||
as this has created major maintenance headache.
|
||||
Consider using the library in
|
||||
|
||||
libcpu/powercp/new-exceptions/bspsupport/
|
||||
|
||||
which implements the same functionality in a
|
||||
(hopefully) generic way.
|
||||
|
||||
T.S., 12/2007
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* This file contains the PIC-independent implementation of the
|
||||
* functions described in irq.h
|
||||
*
|
||||
* Copyright (C) 1998, 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq_supp.h>
|
||||
#include <rtems/irq.h>
|
||||
#include <rtems/score/apiext.h> /* for post ISR signal processing */
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <bsp/vectors.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/bspIo.h> /* for printk */
|
||||
|
||||
extern unsigned int external_exception_vector_prolog_code_size[];
|
||||
extern void external_exception_vector_prolog_code();
|
||||
extern unsigned int decrementer_exception_vector_prolog_code_size[];
|
||||
extern void decrementer_exception_vector_prolog_code();
|
||||
|
||||
/*
|
||||
* default handler connected on each irq after bsp initialization
|
||||
*/
|
||||
static rtems_irq_connect_data default_rtems_entry;
|
||||
|
||||
/*
|
||||
* location used to store initial tables used for interrupt
|
||||
* management.
|
||||
*/
|
||||
static rtems_irq_global_settings* internal_config;
|
||||
static rtems_irq_connect_data* rtems_hdl_tbl;
|
||||
|
||||
/*
|
||||
* ------------------------ RTEMS Irq helper functions ----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function check that the value given for the irq line
|
||||
* is valid.
|
||||
*/
|
||||
|
||||
static int isValidInterrupt(int irq)
|
||||
{
|
||||
if ( (irq < internal_config->irqBase) ||
|
||||
(irq >= internal_config->irqBase + internal_config->irqNb))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------- RTEMS Shared Irq Handler Mngt Routines ------------
|
||||
*/
|
||||
int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
rtems_irq_connect_data* vchain;
|
||||
|
||||
if (!isValidInterrupt(irq->name)) {
|
||||
printk("Invalid interrupt vector %d\n",irq->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
if ( (int)rtems_hdl_tbl[irq->name].next_handler == -1 ) {
|
||||
rtems_interrupt_enable(level);
|
||||
printk(
|
||||
"IRQ vector %d already connected to an unshared handler\n",
|
||||
irq->name
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vchain = (rtems_irq_connect_data*)malloc(sizeof(rtems_irq_connect_data));
|
||||
|
||||
/* save off topmost handler */
|
||||
vchain[0]= rtems_hdl_tbl[irq->name];
|
||||
|
||||
/*
|
||||
* store the data provided by user
|
||||
*/
|
||||
rtems_hdl_tbl[irq->name] = *irq;
|
||||
|
||||
/* link chain to new topmost handler */
|
||||
rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
|
||||
|
||||
/*
|
||||
* enable_irq_at_pic is supposed to ignore
|
||||
* requests to disable interrupts outside
|
||||
* of the range handled by the PIC
|
||||
*/
|
||||
BSP_enable_irq_at_pic(irq->name);
|
||||
|
||||
/*
|
||||
* Enable interrupt on device
|
||||
*/
|
||||
if (irq->on)
|
||||
irq->on(irq);
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------- RTEMS Single Irq Handler Mngt Routines ------------
|
||||
*/
|
||||
|
||||
int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!isValidInterrupt(irq->name)) {
|
||||
printk("Invalid interrupt vector %d\n",irq->name);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if default handler is actually connected. If not issue an error.
|
||||
* You must first get the current handler via i386_get_current_idt_entry
|
||||
* and then disconnect it using i386_delete_idt_entry.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
rtems_interrupt_disable(level);
|
||||
if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
|
||||
rtems_interrupt_enable(level);
|
||||
printk("IRQ vector %d already connected\n",irq->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* store the data provided by user
|
||||
*/
|
||||
rtems_hdl_tbl[irq->name] = *irq;
|
||||
rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
|
||||
|
||||
/*
|
||||
* enable_irq_at_pic is supposed to ignore
|
||||
* requests to disable interrupts outside
|
||||
* of the range handled by the PIC
|
||||
*/
|
||||
BSP_enable_irq_at_pic(irq->name);
|
||||
|
||||
/*
|
||||
* Enable interrupt on device
|
||||
*/
|
||||
if (irq->on)
|
||||
irq->on(irq);
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!isValidInterrupt(irq->name)) {
|
||||
return 0;
|
||||
}
|
||||
rtems_interrupt_disable(level);
|
||||
*irq = rtems_hdl_tbl[irq->name];
|
||||
rtems_interrupt_enable(level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
|
||||
{
|
||||
rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!isValidInterrupt(irq->name)) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if default handler is actually connected. If not issue an error.
|
||||
* You must first get the current handler via i386_get_current_idt_entry
|
||||
* and then disconnect it using i386_delete_idt_entry.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
rtems_interrupt_disable(level);
|
||||
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (int)rtems_hdl_tbl[irq->name].next_handler != -1 ) {
|
||||
int found = 0;
|
||||
|
||||
for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
|
||||
(vchain->hdl != default_rtems_entry.hdl);
|
||||
(pchain= vchain,
|
||||
vchain = (rtems_irq_connect_data*)vchain->next_handler) ) {
|
||||
if ( vchain->hdl == irq->hdl ) {
|
||||
found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !found ) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* disable_irq_at_pic is supposed to ignore
|
||||
* requests to disable interrupts outside
|
||||
* of the range handled by the PIC
|
||||
*/
|
||||
BSP_disable_irq_at_pic(irq->name);
|
||||
|
||||
/*
|
||||
* Disable interrupt on device
|
||||
*/
|
||||
if (irq->off)
|
||||
irq->off(irq);
|
||||
|
||||
/*
|
||||
* restore the default irq value
|
||||
*/
|
||||
if( !vchain ) {
|
||||
/* single handler vector... */
|
||||
rtems_hdl_tbl[irq->name] = default_rtems_entry;
|
||||
} else {
|
||||
if ( pchain ) {
|
||||
/* non-first handler being removed */
|
||||
pchain->next_handler = vchain->next_handler;
|
||||
} else {
|
||||
/* first handler isn't malloc'ed, so just overwrite it. Since
|
||||
* the contents of vchain are being struct copied, vchain itself
|
||||
* goes away
|
||||
*/
|
||||
vchain = vchain->next_handler;
|
||||
rtems_hdl_tbl[irq->name]= *vchain;
|
||||
}
|
||||
free(vchain);
|
||||
}
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* RTEMS Global Interrupt Handler Management Routines
|
||||
*/
|
||||
|
||||
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
|
||||
{
|
||||
int i;
|
||||
rtems_interrupt_level level;
|
||||
rtems_irq_connect_data* vchain;
|
||||
rtems_raw_except_connect_data vectorDesc;
|
||||
|
||||
/*
|
||||
* Store various code accelerators
|
||||
*/
|
||||
internal_config = config;
|
||||
default_rtems_entry = config->defaultEntry;
|
||||
rtems_hdl_tbl = config->irqHdlTbl;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
if ( !BSP_setup_the_pic(config) ) {
|
||||
printk("PIC setup failed; leaving IRQs OFF\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i = config->irqBase; i < config->irqBase + config->irqNb; i++ ) {
|
||||
for( vchain = &rtems_hdl_tbl[i];
|
||||
((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
|
||||
vchain = (rtems_irq_connect_data*)vchain->next_handler ) {
|
||||
if (vchain->on)
|
||||
vchain->on(vchain);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
/*
|
||||
* We must connect the raw irq handler for the two
|
||||
* expected interrupt sources : decrementer and external interrupts.
|
||||
*/
|
||||
vectorDesc.exceptIndex = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_DEC_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size =
|
||||
(unsigned) decrementer_exception_vector_prolog_code_size;
|
||||
vectorDesc.on = 0;
|
||||
vectorDesc.off = 0;
|
||||
vectorDesc.isOn = 0;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
|
||||
}
|
||||
|
||||
vectorDesc.exceptIndex = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.vector = ASM_EXT_VECTOR;
|
||||
vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
|
||||
vectorDesc.hdl.raw_hdl_size =
|
||||
(unsigned) external_exception_vector_prolog_code_size;
|
||||
if (!ppc_set_exception (&vectorDesc)) {
|
||||
BSP_panic("Unable to initialize RTEMS external raw exception\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
|
||||
{
|
||||
*config = internal_config;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
|
||||
{
|
||||
/*
|
||||
* 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 requested from keyboard...
|
||||
*/
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
/*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* IRQ veneers for RTEMS.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* Modified to support the MCP750.
|
||||
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
|
||||
*
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2003/7:
|
||||
* - store isr nesting level in _ISR_Nest_level rather than
|
||||
* SPRG0 - RTEMS relies on that variable.
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2005/4:
|
||||
* - DONT enable FP across ISR since fpregs are not saved!!
|
||||
* FPU is used by Thread_Dispatch however...
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
|
||||
#define MSR_EXC_BITS (MSR_DR | MSR_IR | MSR_RI)
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
.p2align 5
|
||||
#if defined(ASM_DEC_VECTOR)
|
||||
PUBLIC_VAR(decrementer_exception_vector_prolog_code)
|
||||
|
||||
SYM (decrementer_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_DEC_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
|
||||
|
||||
decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
|
||||
#endif
|
||||
|
||||
#if defined(ASM_60X_SYSMGMT_VECTOR)
|
||||
PUBLIC_VAR(sysmgmt_exception_vector_prolog_code)
|
||||
|
||||
SYM (sysmgmt_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_60X_SYSMGMT_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (sysmgmt_exception_vector_prolog_code_size)
|
||||
|
||||
sysmgmt_exception_vector_prolog_code_size = . - sysmgmt_exception_vector_prolog_code
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ASM_BOOKE_DEC_VECTOR)
|
||||
PUBLIC_VAR(pit_exception_vector_prolog_code)
|
||||
|
||||
SYM (pit_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_BOOKE_DEC_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (pit_exception_vector_prolog_code_size)
|
||||
|
||||
pit_exception_vector_prolog_code_size = . - pit_exception_vector_prolog_code
|
||||
#endif
|
||||
|
||||
#if defined(ASM_BOOKE_FIT_VECTOR)
|
||||
PUBLIC_VAR(fit_exception_vector_prolog_code)
|
||||
|
||||
SYM (fit_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_BOOKE_FIT_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (fit_exception_vector_prolog_code_size)
|
||||
|
||||
fit_exception_vector_prolog_code_size = . - fit_exception_vector_prolog_code
|
||||
#endif
|
||||
|
||||
PUBLIC_VAR(external_exception_vector_prolog_code)
|
||||
|
||||
#if defined(ASM_EXT_VECTOR)
|
||||
SYM (external_exception_vector_prolog_code):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
li r4, ASM_EXT_VECTOR
|
||||
ba shared_raw_irq_code_entry
|
||||
|
||||
PUBLIC_VAR (external_exception_vector_prolog_code_size)
|
||||
|
||||
external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
|
||||
#endif
|
||||
|
||||
PUBLIC_VAR(shared_raw_irq_code_entry)
|
||||
PUBLIC_VAR(C_dispatch_irq_handler)
|
||||
|
||||
.p2align 5
|
||||
SYM (shared_raw_irq_code_entry):
|
||||
/*
|
||||
* Entry conditions :
|
||||
* Registers already saved : R1, R4
|
||||
* R1 : points to a location with enough room for the
|
||||
* interrupt frame
|
||||
* R4 : vector number
|
||||
*/
|
||||
/*
|
||||
* Save SRR0/SRR1 As soon As possible as it is the minimal needed
|
||||
* to reenable exception processing
|
||||
*/
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
/* PPC EABI: R2 is reserved (pointer to short data .sdata2) - we won't touch it
|
||||
* but we still save/restore it, just in case...
|
||||
*/
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
stw r3, GPR3_OFFSET(r1)
|
||||
|
||||
mfsrr0 r0
|
||||
mfsrr1 r3
|
||||
|
||||
stw r0, SRR0_FRAME_OFFSET(r1)
|
||||
stw r3, SRR1_FRAME_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Enable data and instruction address translation, exception recovery
|
||||
* by merging original bits from saved SRR1.
|
||||
*/
|
||||
li r0, MSR_EXC_BITS
|
||||
and r0, r0, r3
|
||||
mfmsr r3
|
||||
or r3, r3, r0
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Push C scratch registers on the current stack. It may
|
||||
* actually be the thread stack or the interrupt stack.
|
||||
* Anyway we have to make it in order to be able to call C/C++
|
||||
* functions. Depending on the nesting interrupt level, we will
|
||||
* switch to the right stack later.
|
||||
*/
|
||||
stw r5, GPR5_OFFSET(r1)
|
||||
stw r6, GPR6_OFFSET(r1)
|
||||
stw r7, GPR7_OFFSET(r1)
|
||||
stw r8, GPR8_OFFSET(r1)
|
||||
stw r9, GPR9_OFFSET(r1)
|
||||
stw r10, GPR10_OFFSET(r1)
|
||||
stw r11, GPR11_OFFSET(r1)
|
||||
stw r12, GPR12_OFFSET(r1)
|
||||
stw r13, GPR13_OFFSET(r1)
|
||||
|
||||
mfcr r5
|
||||
mfctr r6
|
||||
mfxer r7
|
||||
mflr r8
|
||||
|
||||
stw r5, EXC_CR_OFFSET(r1)
|
||||
stw r6, EXC_CTR_OFFSET(r1)
|
||||
stw r7, EXC_XER_OFFSET(r1)
|
||||
stw r8, EXC_LR_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Add some non volatile registers to store information
|
||||
* that will be used when returning from C handler
|
||||
*/
|
||||
stw r14, GPR14_OFFSET(r1)
|
||||
stw r15, GPR15_OFFSET(r1)
|
||||
/*
|
||||
* save current stack pointer location in R14
|
||||
*/
|
||||
addi r14, r1, 0
|
||||
/*
|
||||
* store part of _Thread_Dispatch_disable_level address in R15
|
||||
*/
|
||||
addis r15,0, _Thread_Dispatch_disable_level@ha
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
/*
|
||||
* Get current nesting level in R3
|
||||
*/
|
||||
mfspr r3, SPRG0
|
||||
#else
|
||||
/*
|
||||
* Retrieve current nesting level from _ISR_Nest_level
|
||||
*/
|
||||
lis r7, _ISR_Nest_level@ha
|
||||
lwz r3, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
/*
|
||||
* Check if stack switch is necessary
|
||||
*/
|
||||
cmpwi r3,0
|
||||
bne nested
|
||||
mfspr r1, SPRG1
|
||||
|
||||
nested:
|
||||
/*
|
||||
* Start Incrementing nesting level in R3
|
||||
*/
|
||||
addi r3,r3,1
|
||||
/*
|
||||
* Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r6,_Thread_Dispatch_disable_level@l(r15)
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
/*
|
||||
* Store new nesting level in SPRG0
|
||||
*/
|
||||
mtspr SPRG0, r3
|
||||
#else
|
||||
/* store new nesting level in _ISR_Nest_level */
|
||||
stw r3, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
|
||||
addi r6, r6, 1
|
||||
mfmsr r5
|
||||
/*
|
||||
* store new _Thread_Dispatch_disable_level value
|
||||
*/
|
||||
stw r6, _Thread_Dispatch_disable_level@l(r15)
|
||||
/*
|
||||
* We are now running on the interrupt stack. External and decrementer
|
||||
* exceptions are still disabled. I see no purpose trying to optimize
|
||||
* further assembler code.
|
||||
*/
|
||||
/*
|
||||
* Call C exception handler for decrementer Interrupt frame is passed just
|
||||
* in case...
|
||||
*/
|
||||
addi r3, r14, 0x8
|
||||
/* clear CR[6] to make sure no varargs fn callee assumes there are FP args passed */
|
||||
crxor 6,6,6
|
||||
bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
|
||||
/*
|
||||
* start decrementing nesting level. Note : do not test result against 0
|
||||
* value as an easy exit condition because if interrupt nesting level > 1
|
||||
* then _Thread_Dispatch_disable_level > 1
|
||||
*/
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
mfspr r4, SPRG0
|
||||
#else
|
||||
lis r7, _ISR_Nest_level@ha
|
||||
lwz r4, _ISR_Nest_level@l(r7)
|
||||
#endif
|
||||
/*
|
||||
* start decrementing _Thread_Dispatch_disable_level
|
||||
*/
|
||||
lwz r3,_Thread_Dispatch_disable_level@l(r15)
|
||||
addi r4, r4, -1 /* Continue decrementing nesting level */
|
||||
addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
|
||||
#if BROKEN_ISR_NEST_LEVEL
|
||||
mtspr SPRG0, r4 /* End decrementing nesting level */
|
||||
#else
|
||||
stw r4, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
|
||||
#endif
|
||||
stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
|
||||
cmpwi r3, 0
|
||||
/*
|
||||
* switch back to original stack (done here just optimize registers
|
||||
* contention. Could have been done before...)
|
||||
*/
|
||||
addi r1, r14, 0
|
||||
bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
|
||||
/*
|
||||
* Here we are running again on the thread system stack.
|
||||
* We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
|
||||
* Interrupt are still disabled. Time to check if scheduler request to
|
||||
* do something with the current thread...
|
||||
*/
|
||||
addis r4, 0, _Context_Switch_necessary@ha
|
||||
lbz r5, _Context_Switch_necessary@l(r4)
|
||||
cmpwi r5, 0
|
||||
bne switch
|
||||
|
||||
addis r6, 0, _ISR_Signals_to_thread_executing@ha
|
||||
lbz r7, _ISR_Signals_to_thread_executing@l(r6)
|
||||
cmpwi r7, 0
|
||||
li r8, 0
|
||||
beq easy_exit
|
||||
stb r8, _ISR_Signals_to_thread_executing@l(r6)
|
||||
/*
|
||||
* going to call _ThreadProcessSignalsFromIrq
|
||||
* Push a complete exception like frame...
|
||||
*/
|
||||
stmw r16, GPR16_OFFSET(r1)
|
||||
addi r3, r1, 0x8
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r4, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r4, GPR1_OFFSET(r1)
|
||||
/*
|
||||
* Call High Level signal handling code
|
||||
*/
|
||||
bl _ThreadProcessSignalsFromIrq
|
||||
/*
|
||||
* start restoring exception like frame
|
||||
*/
|
||||
lwz r31, EXC_CTR_OFFSET(r1)
|
||||
lwz r30, EXC_XER_OFFSET(r1)
|
||||
lwz r29, EXC_CR_OFFSET(r1)
|
||||
lwz r28, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r31
|
||||
mtxer r30
|
||||
mtcr r29
|
||||
mtlr r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Make path non recoverable...
|
||||
*/
|
||||
li r0, MSR_EXC_BITS
|
||||
mfmsr r3
|
||||
andc r3, r3, r0
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
switch:
|
||||
bl SYM (_Thread_Dispatch)
|
||||
|
||||
easy_exit:
|
||||
/*
|
||||
* start restoring interrupt frame
|
||||
*/
|
||||
lwz r3, EXC_CTR_OFFSET(r1)
|
||||
lwz r4, EXC_XER_OFFSET(r1)
|
||||
lwz r5, EXC_CR_OFFSET(r1)
|
||||
lwz r6, EXC_LR_OFFSET(r1)
|
||||
|
||||
mtctr r3
|
||||
mtxer r4
|
||||
mtcr r5
|
||||
mtlr r6
|
||||
|
||||
lwz r15, GPR15_OFFSET(r1)
|
||||
lwz r14, GPR14_OFFSET(r1)
|
||||
lwz r13, GPR13_OFFSET(r1)
|
||||
lwz r12, GPR12_OFFSET(r1)
|
||||
lwz r11, GPR11_OFFSET(r1)
|
||||
lwz r10, GPR10_OFFSET(r1)
|
||||
lwz r9, GPR9_OFFSET(r1)
|
||||
lwz r8, GPR8_OFFSET(r1)
|
||||
lwz r7, GPR7_OFFSET(r1)
|
||||
lwz r6, GPR6_OFFSET(r1)
|
||||
lwz r5, GPR5_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable nested exception processing, data and instruction
|
||||
* translation.
|
||||
*/
|
||||
li r0, MSR_EXC_BITS
|
||||
mfmsr r3
|
||||
andc r3, r3, r0
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r4, SRR1_FRAME_OFFSET(r1)
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
|
||||
mtsrr1 r4
|
||||
mtsrr0 r3
|
||||
lwz r4, GPR4_OFFSET(r1)
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
addi r1,r1, EXCEPTION_FRAME_END
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,14 +0,0 @@
|
||||
The files in this directory (vectors.S, vectors.h, vectors_init.c)
|
||||
are DEPRECATED.
|
||||
|
||||
DO NOT COPY/MODIFY FOR NEW BSPs
|
||||
|
||||
as this has created major maintenance headache.
|
||||
Consider using the library in
|
||||
|
||||
libcpu/powercp/new-exceptions/bspsupport/
|
||||
|
||||
which implements the same functionality in a
|
||||
(hopefully) generic way.
|
||||
|
||||
T.S., 12/2007
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* (c) 1999, Eric Valette valette@crf.canon.fr
|
||||
*
|
||||
*
|
||||
* This file contains the assembly code for the PowerPC
|
||||
* exception veneers for RTEMS.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
|
||||
#define MSR_EXC_BITS (MSR_DR | MSR_IR | MSR_RI)
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
.text
|
||||
/* 603e shadows GPR0..GPR3 for certain exceptions. We must switch
|
||||
* that off before we can use the stack pointer. Note that this is
|
||||
* ONLY safe if the shadowing is actually active -- otherwise, r1
|
||||
* is destroyed. We deliberately use r1 so problems become obvious
|
||||
* if this is abused!
|
||||
*/
|
||||
PUBLIC_VAR(tgpr_clr_exception_vector_code_prolog)
|
||||
SYM (tgpr_clr_exception_vector_code_prolog):
|
||||
mfmsr r1
|
||||
rlwinm r1,r1,0,15,13
|
||||
mtmsr r1
|
||||
isync
|
||||
/* fall thru */
|
||||
PUBLIC_VAR(default_exception_vector_code_prolog)
|
||||
SYM (default_exception_vector_code_prolog):
|
||||
/*
|
||||
* let room for exception frame
|
||||
*/
|
||||
stw r3, GPR3_OFFSET-EXCEPTION_FRAME_END(r1)
|
||||
mflr r3
|
||||
stw r3, EXC_LR_OFFSET-EXCEPTION_FRAME_END(r1)
|
||||
bla push_normalized_frame
|
||||
|
||||
/* IMPORTANT: prologue size MUST be < 32 bytes; 'altivec unavailable' exception
|
||||
* is already at 0xf20 :-(
|
||||
*/
|
||||
|
||||
PUBLIC_VAR (default_exception_vector_code_prolog_size)
|
||||
PUBLIC_VAR (tgpr_clr_exception_vector_code_prolog_size)
|
||||
|
||||
default_exception_vector_code_prolog_size = . - default_exception_vector_code_prolog
|
||||
tgpr_clr_exception_vector_code_prolog_size= . - tgpr_clr_exception_vector_code_prolog
|
||||
|
||||
.p2align 5
|
||||
PUBLIC_VAR (push_normalized_frame)
|
||||
SYM (push_normalized_frame):
|
||||
stwu r1, - (EXCEPTION_FRAME_END)(r1)
|
||||
mfcr r3
|
||||
stw r3, EXC_CR_OFFSET(r1)
|
||||
/*
|
||||
* r3 = exception vector entry point
|
||||
* (256 * vector number) + few instructions
|
||||
*/
|
||||
/*
|
||||
* FIXME: vectors should distingish
|
||||
* all bits in mask 0x00003ff0
|
||||
* and keep in mind that the LR/R3 contains the
|
||||
* address BEHIND the entry code
|
||||
*/
|
||||
mflr r3
|
||||
/* mask upper bits in case vectors are in the high area (psim) */
|
||||
rlwinm r3, r3, 32-5, 20, 31
|
||||
|
||||
/* FIXME: should do this really only on ALTIVEC-capable CPU
|
||||
* Hopefully, this vector offset doesn't apply to any other one...
|
||||
*/
|
||||
#if defined(ASM_60X_VEC_VECTOR)
|
||||
/*
|
||||
* Remap altivec unavaliable (0xf20) to its vector number...
|
||||
*/
|
||||
cmplwi r3,(ASM_60X_VEC_VECTOR_OFFSET>>5)
|
||||
bne 1f
|
||||
li r3,ASM_60X_VEC_VECTOR<<3
|
||||
1:
|
||||
#endif
|
||||
/*
|
||||
* r3 = r3 >> 8 = vector #
|
||||
*/
|
||||
srwi r3,r3,3
|
||||
stw r3, EXCEPTION_NUMBER_OFFSET(r1)
|
||||
stw r0, GPR0_OFFSET(r1)
|
||||
stw r4, GPR4_OFFSET(r1)
|
||||
/* R2 should never change (EABI: pointer to .sdata2) - we
|
||||
* save it nevertheless..
|
||||
*/
|
||||
stw r2, GPR2_OFFSET(r1)
|
||||
|
||||
/* Fetch 405 critical exception state from SRR2/SRR3 */
|
||||
lis r4, bsp_raw_vector_is_405_critical@ha
|
||||
lwz r0, bsp_raw_vector_is_405_critical@l(r4)
|
||||
rlwnm. r0,r0,r3,0,0
|
||||
beq 1f
|
||||
/*
|
||||
* NOTE: srr2/3 are stored in slots SRR0/1
|
||||
* for critical exceptions
|
||||
*/
|
||||
mfsrr2 r3
|
||||
stw r3, SRR0_FRAME_OFFSET(r1)
|
||||
mfsrr3 r3
|
||||
stw r3, SRR1_FRAME_OFFSET(r1)
|
||||
b 2f
|
||||
1:
|
||||
mfsrr0 r3
|
||||
stw r3, SRR0_FRAME_OFFSET(r1)
|
||||
mfsrr1 r3
|
||||
stw r3, SRR1_FRAME_OFFSET(r1)
|
||||
2:
|
||||
/*
|
||||
* Save general purpose registers
|
||||
* Already saved in prolog : R1, R3, LR.
|
||||
* Saved a few line above : R0, R2
|
||||
*
|
||||
* Manual says that "stmw" instruction may be slower than
|
||||
* series of individual "stw" but who cares about performance
|
||||
* for the DEFAULT exception handler?
|
||||
*/
|
||||
stmw r5, GPR5_OFFSET(r1) /* save R5->R31 */
|
||||
|
||||
mfctr r30
|
||||
stw r30, EXC_CTR_OFFSET(r1)
|
||||
mfxer r28
|
||||
stw r28, EXC_XER_OFFSET(r1)
|
||||
mfmsr r28
|
||||
stw r28, EXC_MSR_OFFSET(r1)
|
||||
mfdar r28
|
||||
stw r28, EXC_DAR_OFFSET(r1)
|
||||
/*
|
||||
* compute SP at exception entry
|
||||
*/
|
||||
addi r3, r1, EXCEPTION_FRAME_END
|
||||
/*
|
||||
* store it at the right place
|
||||
*/
|
||||
stw r3, GPR1_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Enable data and instruction address translation, exception nesting
|
||||
* by merging original bits from saved SRR1.
|
||||
*/
|
||||
lwz r0, SRR1_FRAME_OFFSET(r1)
|
||||
li r3, MSR_EXC_BITS
|
||||
and r0, r0, r3
|
||||
mfmsr r3
|
||||
or r3, r3, r0
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
/*
|
||||
* Call C exception handler
|
||||
*/
|
||||
/*
|
||||
* store the execption frame address in r3 (first param)
|
||||
*/
|
||||
addi r3, r1, 0x8
|
||||
/* clear CR[6] to make sure no varargs fn callee assumes there are FP args passed */
|
||||
crxor 6,6,6
|
||||
/*
|
||||
* globalExceptHdl(r3)
|
||||
*/
|
||||
addis r4, 0, globalExceptHdl@ha
|
||||
lwz r5, globalExceptHdl@l(r4)
|
||||
mtlr r5
|
||||
blrl
|
||||
/*
|
||||
* Restore registers status
|
||||
*/
|
||||
lwz r31, EXC_CR_OFFSET(r1)
|
||||
mtcr r31
|
||||
lwz r30, EXC_CTR_OFFSET(r1)
|
||||
mtctr r30
|
||||
lwz r29, EXC_LR_OFFSET(r1)
|
||||
mtlr r29
|
||||
lwz r28, EXC_XER_OFFSET(r1)
|
||||
mtxer r28
|
||||
|
||||
lmw r4, GPR4_OFFSET(r1)
|
||||
lwz r2, GPR2_OFFSET(r1)
|
||||
|
||||
/*
|
||||
* Disable data and instruction translation. Mark path non recoverable
|
||||
*/
|
||||
li r0, MSR_EXC_BITS
|
||||
mfmsr r3
|
||||
andc r3, r3, r0
|
||||
mtmsr r3
|
||||
SYNC
|
||||
/*
|
||||
* determine, whether to restore from
|
||||
* srr0/1 or srr2/3
|
||||
*/
|
||||
lis r3, bsp_raw_vector_is_405_critical@ha
|
||||
lwz r0,EXCEPTION_NUMBER_OFFSET(r1)
|
||||
lwz r3, bsp_raw_vector_is_405_critical@l(r3)
|
||||
rlwnm. r3,r3,r0,0,0
|
||||
beq 1f
|
||||
/*
|
||||
* NOTE: srr2/3 are stored in slots SRR0/1
|
||||
* for critical exceptions
|
||||
*/
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr3 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr2 r3
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
/* DONT add back the frame size but reload the value
|
||||
* stored in the frame -- maybe the exception handler
|
||||
* changed it with good reason (e.g., gdb pushed a dummy frame)
|
||||
*/
|
||||
lwz r1, GPR1_OFFSET(r1)
|
||||
SYNC
|
||||
rfci
|
||||
1:
|
||||
/*
|
||||
* Restore rfi related settings
|
||||
*/
|
||||
|
||||
lwz r3, SRR1_FRAME_OFFSET(r1)
|
||||
mtsrr1 r3
|
||||
lwz r3, SRR0_FRAME_OFFSET(r1)
|
||||
mtsrr0 r3
|
||||
|
||||
lwz r3, GPR3_OFFSET(r1)
|
||||
lwz r0, GPR0_OFFSET(r1)
|
||||
/* DONT add back the frame size but reload the value
|
||||
* stored in the frame -- maybe the exception handler
|
||||
* changed it with good reason (e.g., gdb pushed a dummy frame)
|
||||
*/
|
||||
lwz r1, GPR1_OFFSET(r1)
|
||||
SYNC
|
||||
rfi
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* vectors.h Exception frame related contant and API.
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#ifndef LIBBSP_POWERPC_SHARED_VECTORS_H
|
||||
#define LIBBSP_POWERPC_SHARED_VECTORS_H
|
||||
#include <libcpu/raw_exception.h>
|
||||
|
||||
/*
|
||||
* The callee (high level exception code written in C)
|
||||
* will store the Link Registers (return address) at entry r1 + 4 !!!.
|
||||
* So let room for it!!!.
|
||||
*/
|
||||
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
|
||||
#define SRR0_FRAME_OFFSET 8
|
||||
#define SRR1_FRAME_OFFSET 12
|
||||
#define EXCEPTION_NUMBER_OFFSET 16
|
||||
#define GPR0_OFFSET 20
|
||||
#define GPR1_OFFSET 24
|
||||
#define GPR2_OFFSET 28
|
||||
#define GPR3_OFFSET 32
|
||||
#define GPR4_OFFSET 36
|
||||
#define GPR5_OFFSET 40
|
||||
#define GPR6_OFFSET 44
|
||||
#define GPR7_OFFSET 48
|
||||
#define GPR8_OFFSET 52
|
||||
#define GPR9_OFFSET 56
|
||||
#define GPR10_OFFSET 60
|
||||
#define GPR11_OFFSET 64
|
||||
#define GPR12_OFFSET 68
|
||||
#define GPR13_OFFSET 72
|
||||
#define GPR14_OFFSET 76
|
||||
#define GPR15_OFFSET 80
|
||||
#define GPR16_OFFSET 84
|
||||
#define GPR17_OFFSET 88
|
||||
#define GPR18_OFFSET 92
|
||||
#define GPR19_OFFSET 96
|
||||
#define GPR20_OFFSET 100
|
||||
#define GPR21_OFFSET 104
|
||||
#define GPR22_OFFSET 108
|
||||
#define GPR23_OFFSET 112
|
||||
#define GPR24_OFFSET 116
|
||||
#define GPR25_OFFSET 120
|
||||
#define GPR26_OFFSET 124
|
||||
#define GPR27_OFFSET 128
|
||||
#define GPR28_OFFSET 132
|
||||
#define GPR29_OFFSET 136
|
||||
#define GPR30_OFFSET 140
|
||||
#define GPR31_OFFSET 144
|
||||
#define EXC_CR_OFFSET 148
|
||||
#define EXC_CTR_OFFSET 152
|
||||
#define EXC_XER_OFFSET 156
|
||||
#define EXC_LR_OFFSET 160
|
||||
#define EXC_MSR_OFFSET 164
|
||||
#define EXC_DAR_OFFSET 168
|
||||
/*
|
||||
* maintain the EABI requested 8 bytes aligment
|
||||
* As SVR4 ABI requires 16, make it 16 (as some
|
||||
* exception may need more registers to be processed...)
|
||||
*/
|
||||
#define EXCEPTION_FRAME_END 176
|
||||
|
||||
#ifndef ASM
|
||||
/*
|
||||
* default raw exception handlers
|
||||
* The "*_size" symbol is generated by the linker; prevent it from
|
||||
* being accessed in one of the short data areas by declaring
|
||||
* it as an array
|
||||
*/
|
||||
|
||||
extern void default_exception_vector_code_prolog();
|
||||
extern unsigned int default_exception_vector_code_prolog_size[];
|
||||
extern void tgpr_clr_exception_vector_code_prolog();
|
||||
extern unsigned int tgpr_clr_exception_vector_code_prolog_size[];
|
||||
/*
|
||||
* FIXME: these should move to a "irq_asm.h"
|
||||
*/
|
||||
extern void external_exception_vector_prolog_code();
|
||||
extern unsigned int external_exception_vector_prolog_code_size[];
|
||||
#if defined(ASM_DEC_VECTOR)
|
||||
extern void decrementer_exception_vector_prolog_code();
|
||||
extern unsigned int decrementer_exception_vector_prolog_code_size[];
|
||||
#endif
|
||||
#if defined(ASM_60X_SYSMGMT_VECTOR)
|
||||
extern void sysmgmt_exception_vector_prolog_code();
|
||||
extern unsigned int sysmgmt_exception_vector_prolog_code_size[];
|
||||
#endif
|
||||
#if defined(ASM_BOOKE_DEC_VECTOR)
|
||||
extern void pit_exception_vector_prolog_code();
|
||||
extern unsigned int pit_exception_vector_prolog_code_size[];
|
||||
#endif
|
||||
#if defined(ASM_BOOKE_FIT_VECTOR)
|
||||
extern void fit_exception_vector_prolog_code();
|
||||
extern unsigned int fit_exception_vector_prolog_code_size[];
|
||||
#endif
|
||||
|
||||
/* codemove is like memmove, but it also gets the cache line size
|
||||
* as 4th parameter to synchronize them. If this last parameter is
|
||||
* zero, it performs more or less like memmove. No copy is performed if
|
||||
* source and destination addresses are equal. However the caches
|
||||
* are synchronized. Note that the size is always rounded up to the
|
||||
* next mutiple of 4.
|
||||
*/
|
||||
extern void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
extern void exception_nop_enable(const rtems_raw_except_connect_data* ptr);
|
||||
extern int exception_always_enabled(const rtems_raw_except_connect_data* ptr);
|
||||
extern void initialize_exceptions();
|
||||
|
||||
typedef struct _BSP_Exception_frame {
|
||||
unsigned EXC_SRR0;
|
||||
unsigned EXC_SRR1;
|
||||
unsigned _EXC_number;
|
||||
unsigned GPR0;
|
||||
unsigned GPR1;
|
||||
unsigned GPR2;
|
||||
unsigned GPR3;
|
||||
unsigned GPR4;
|
||||
unsigned GPR5;
|
||||
unsigned GPR6;
|
||||
unsigned GPR7;
|
||||
unsigned GPR8;
|
||||
unsigned GPR9;
|
||||
unsigned GPR10;
|
||||
unsigned GPR11;
|
||||
unsigned GPR12;
|
||||
unsigned GPR13;
|
||||
unsigned GPR14;
|
||||
unsigned GPR15;
|
||||
unsigned GPR16;
|
||||
unsigned GPR17;
|
||||
unsigned GPR18;
|
||||
unsigned GPR19;
|
||||
unsigned GPR20;
|
||||
unsigned GPR21;
|
||||
unsigned GPR22;
|
||||
unsigned GPR23;
|
||||
unsigned GPR24;
|
||||
unsigned GPR25;
|
||||
unsigned GPR26;
|
||||
unsigned GPR27;
|
||||
unsigned GPR28;
|
||||
unsigned GPR29;
|
||||
unsigned GPR30;
|
||||
unsigned GPR31;
|
||||
unsigned EXC_CR;
|
||||
unsigned EXC_CTR;
|
||||
unsigned EXC_XER;
|
||||
unsigned EXC_LR;
|
||||
unsigned EXC_MSR;
|
||||
unsigned EXC_DAR;
|
||||
} BSP_Exception_frame;
|
||||
|
||||
typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr);
|
||||
extern exception_handler_t globalExceptHdl;
|
||||
/*
|
||||
* Compatibility with pc386
|
||||
*/
|
||||
typedef BSP_Exception_frame CPU_Exception_frame;
|
||||
typedef exception_handler_t cpuExcHandlerType;
|
||||
|
||||
/*
|
||||
* dummy functions for exception interface
|
||||
*/
|
||||
void exception_nop_enable(const rtems_raw_except_connect_data* ptr);
|
||||
int exception_always_enabled(const rtems_raw_except_connect_data* ptr);
|
||||
|
||||
#endif /* ASM */
|
||||
|
||||
#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* vectors_init.c Exception hanlding initialisation (and generic handler).
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* CopyRight (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
#include <bsp/vectors.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <libcpu/spr.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
|
||||
static rtems_raw_except_global_settings exception_config;
|
||||
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
|
||||
|
||||
exception_handler_t globalExceptHdl;
|
||||
|
||||
/* T. Straumann: provide a stack trace
|
||||
* <strauman@slac.stanford.edu>, 6/26/2001
|
||||
*/
|
||||
typedef struct LRFrameRec_ {
|
||||
struct LRFrameRec_ *frameLink;
|
||||
unsigned long *lr;
|
||||
} LRFrameRec, *LRFrame;
|
||||
|
||||
#define STACK_CLAMP 50 /* in case we have a corrupted bottom */
|
||||
|
||||
SPR_RO(LR)
|
||||
|
||||
void
|
||||
BSP_printStackTrace(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
LRFrame f;
|
||||
int i;
|
||||
LRFrame sp;
|
||||
void *lr;
|
||||
|
||||
printk("Stack Trace: \n ");
|
||||
if (excPtr) {
|
||||
printk("IP: 0x%08x, ",excPtr->EXC_SRR0);
|
||||
sp=(LRFrame)excPtr->GPR1;
|
||||
lr=(void*)excPtr->EXC_LR;
|
||||
} else {
|
||||
/* there's no macro for this */
|
||||
__asm__ __volatile__("mr %0, 1":"=r"(sp));
|
||||
lr=(LRFrame)_read_LR();
|
||||
}
|
||||
printk("LR: 0x%08x\n",lr);
|
||||
for (f=(LRFrame)sp, i=0; f->frameLink && i<STACK_CLAMP; f=f->frameLink) {
|
||||
printk("--^ 0x%08x", (long)(f->frameLink->lr));
|
||||
if (!(++i%5))
|
||||
printk("\n");
|
||||
}
|
||||
if (i>=STACK_CLAMP) {
|
||||
printk("Too many stack frames (stack possibly corrupted), giving up...\n");
|
||||
} else {
|
||||
if (i%5)
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void C_exception_handler(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
int recoverable = 0;
|
||||
|
||||
printk("exception handler called for exception %d\n", excPtr->_EXC_number);
|
||||
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
|
||||
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
|
||||
printk("\t R0 = %x\n", excPtr->GPR0);
|
||||
printk("\t R1 = %x\n", excPtr->GPR1);
|
||||
printk("\t R2 = %x\n", excPtr->GPR2);
|
||||
printk("\t R3 = %x\n", excPtr->GPR3);
|
||||
printk("\t R4 = %x\n", excPtr->GPR4);
|
||||
printk("\t R5 = %x\n", excPtr->GPR5);
|
||||
printk("\t R6 = %x\n", excPtr->GPR6);
|
||||
printk("\t R7 = %x\n", excPtr->GPR7);
|
||||
printk("\t R8 = %x\n", excPtr->GPR8);
|
||||
printk("\t R9 = %x\n", excPtr->GPR9);
|
||||
printk("\t R10 = %x\n", excPtr->GPR10);
|
||||
printk("\t R11 = %x\n", excPtr->GPR11);
|
||||
printk("\t R12 = %x\n", excPtr->GPR12);
|
||||
printk("\t R13 = %x\n", excPtr->GPR13);
|
||||
printk("\t R14 = %x\n", excPtr->GPR14);
|
||||
printk("\t R15 = %x\n", excPtr->GPR15);
|
||||
printk("\t R16 = %x\n", excPtr->GPR16);
|
||||
printk("\t R17 = %x\n", excPtr->GPR17);
|
||||
printk("\t R18 = %x\n", excPtr->GPR18);
|
||||
printk("\t R19 = %x\n", excPtr->GPR19);
|
||||
printk("\t R20 = %x\n", excPtr->GPR20);
|
||||
printk("\t R21 = %x\n", excPtr->GPR21);
|
||||
printk("\t R22 = %x\n", excPtr->GPR22);
|
||||
printk("\t R23 = %x\n", excPtr->GPR23);
|
||||
printk("\t R24 = %x\n", excPtr->GPR24);
|
||||
printk("\t R25 = %x\n", excPtr->GPR25);
|
||||
printk("\t R26 = %x\n", excPtr->GPR26);
|
||||
printk("\t R27 = %x\n", excPtr->GPR27);
|
||||
printk("\t R28 = %x\n", excPtr->GPR28);
|
||||
printk("\t R29 = %x\n", excPtr->GPR29);
|
||||
printk("\t R30 = %x\n", excPtr->GPR30);
|
||||
printk("\t R31 = %x\n", excPtr->GPR31);
|
||||
printk("\t CR = %x\n", excPtr->EXC_CR);
|
||||
printk("\t CTR = %x\n", excPtr->EXC_CTR);
|
||||
printk("\t XER = %x\n", excPtr->EXC_XER);
|
||||
printk("\t LR = %x\n", excPtr->EXC_LR);
|
||||
printk("\t MSR = %x\n", excPtr->EXC_MSR);
|
||||
printk("\t DAR = %x\n", excPtr->EXC_DAR);
|
||||
|
||||
BSP_printStackTrace(excPtr);
|
||||
|
||||
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
|
||||
recoverable = 1;
|
||||
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
|
||||
#ifdef TEST_RAW_EXCEPTION_CODE
|
||||
recoverable = 1;
|
||||
#else
|
||||
recoverable = 0;
|
||||
#endif
|
||||
if (!recoverable) {
|
||||
printk("unrecoverable exception!!! Push reset button\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* dummy functions for on/off/isOn calls
|
||||
* these functions just do nothing fulfill the semantic
|
||||
* requirements to enable/disable a certain exception
|
||||
*/
|
||||
void exception_nop_enable(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
}
|
||||
|
||||
int exception_always_enabled(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void initialize_exceptions()
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize pointer used by low level execption handling
|
||||
*/
|
||||
globalExceptHdl = C_exception_handler;
|
||||
/*
|
||||
* Put default_exception_vector_code_prolog at relevant exception
|
||||
* code entry addresses
|
||||
*/
|
||||
exception_config.exceptSize = LAST_VALID_EXC + 1;
|
||||
exception_config.rawExceptHdlTbl = &exception_table[0];
|
||||
exception_config.defaultRawEntry.exceptIndex = 0;
|
||||
exception_config.defaultRawEntry.hdl.vector = 0;
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog;
|
||||
/*
|
||||
* Note that next line the '&' before default_exception_vector_code_prolog_size
|
||||
* is not a bug as it is defined a .set directly in asm...
|
||||
*/
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) default_exception_vector_code_prolog_size;
|
||||
|
||||
for (i=0; i <= exception_config.exceptSize; i++) {
|
||||
if (!ppc_vector_is_valid (i)) {
|
||||
continue;
|
||||
}
|
||||
exception_table[i].exceptIndex = i;
|
||||
#if defined(PPC_HAS_60X_VECTORS)
|
||||
if ( ppc_cpu.has_shadowed_gprs()
|
||||
&& ( ASM_60X_IMISS_VECTOR == i
|
||||
|| ASM_60X_DLMISS_VECTOR == i
|
||||
|| ASM_60X_DSMISS_VECTOR == i ) ) {
|
||||
exception_table[i].hdl.raw_hdl = tgpr_clr_exception_vector_code_prolog;
|
||||
exception_table[i].hdl.raw_hdl_size = (unsigned)tgpr_clr_exception_vector_code_prolog_size;
|
||||
} else {
|
||||
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
|
||||
}
|
||||
#else
|
||||
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
|
||||
#endif
|
||||
exception_table[i].hdl.vector = i;
|
||||
exception_table[i].on = exception_nop_enable;
|
||||
exception_table[i].off = exception_nop_enable;
|
||||
exception_table[i].isOn = exception_always_enabled;
|
||||
}
|
||||
if (!ppc_init_exceptions(&exception_config)) {
|
||||
BSP_panic("Exception handling initialization failed\n");
|
||||
}
|
||||
#ifdef RTEMS_DEBUG
|
||||
else {
|
||||
printk("Exception handling initialization done\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
2009-10-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* new-exceptions/e500_raw_exc_init.c, new-exceptions/raw_exception.c,
|
||||
new-exceptions/raw_exception.h,
|
||||
new-exceptions/bspsupport/vectors_init.c,
|
||||
mpc8xx/exceptions/asm_utils.S, mpc8xx/exceptions/raw_exception.c,
|
||||
mpc8xx/exceptions/raw_exception.h, mpc8260/asm_utils.S,
|
||||
mpc8260/raw_exception.c, mpc8260/raw_exception.h: Removed files.
|
||||
* Makefile.am: Update for removed files.
|
||||
|
||||
2009-10-22 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* new-exceptions/bspsupport/ppc-code-copy.c,
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* asm_utils.s
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
*
|
||||
* This file contains the low-level support for moving exception
|
||||
* exception code to appropriate location.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <libcpu/io.h>
|
||||
|
||||
.globl codemove
|
||||
codemove:
|
||||
.type codemove,@function
|
||||
/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
|
||||
cmplw cr1,r3,r4
|
||||
addi r0,r5,3
|
||||
srwi. r0,r0,2
|
||||
beq cr1,4f /* In place copy is not necessary */
|
||||
beq 7f /* Protect against 0 count */
|
||||
mtctr r0
|
||||
bge cr1,2f
|
||||
|
||||
la r8,-4(r4)
|
||||
la r7,-4(r3)
|
||||
1: lwzu r0,4(r8)
|
||||
stwu r0,4(r7)
|
||||
bdnz 1b
|
||||
b 4f
|
||||
|
||||
2: slwi r0,r0,2
|
||||
add r8,r4,r0
|
||||
add r7,r3,r0
|
||||
3: lwzu r0,-4(r8)
|
||||
stwu r0,-4(r7)
|
||||
bdnz 3b
|
||||
|
||||
/* Now flush the cache: note that we must start from a cache aligned
|
||||
* address. Otherwise we might miss one cache line.
|
||||
*/
|
||||
4: cmpwi r6,0
|
||||
add r5,r3,r5
|
||||
beq 7f /* Always flush prefetch queue in any case */
|
||||
subi r0,r6,1
|
||||
andc r3,r3,r0
|
||||
mr r4,r3
|
||||
5: cmplw r4,r5
|
||||
dcbst 0,r4
|
||||
add r4,r4,r6
|
||||
blt 5b
|
||||
sync /* Wait for all dcbst to complete on bus */
|
||||
mr r4,r3
|
||||
6: cmplw r4,r5
|
||||
icbi 0,r4
|
||||
add r4,r4,r6
|
||||
blt 6b
|
||||
7: sync /* Wait for all icbi to complete on bus */
|
||||
isync
|
||||
blr
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
* raw_exception.c - This file contains implementation of C function to
|
||||
* Instanciate 8xx ppc primary exception entries.
|
||||
* More detailled information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC860
|
||||
* Risc Microporcessor User's Manual
|
||||
* Motorola REF : MPC860UM/AD
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* Modified for mpc8260 by Andy Dachs <a.dachs@sstl.co.uk>
|
||||
* Surrey Satellite Technology Limited (SSTL), 2001
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <string.h> /* memcmp */
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/powerpc.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
|
||||
static rtems_raw_except_connect_data* raw_except_table;
|
||||
static rtems_raw_except_connect_data default_raw_except_entry;
|
||||
static rtems_raw_except_global_settings* local_settings;
|
||||
|
||||
void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
|
||||
int mpc8260_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
switch(vector) {
|
||||
case ASM_RESET_VECTOR: /* fall through */
|
||||
case ASM_MACH_VECTOR:
|
||||
case ASM_PROT_VECTOR:
|
||||
case ASM_ISI_VECTOR:
|
||||
case ASM_EXT_VECTOR:
|
||||
case ASM_ALIGN_VECTOR:
|
||||
case ASM_PROG_VECTOR:
|
||||
case ASM_FLOAT_VECTOR:
|
||||
case ASM_DEC_VECTOR:
|
||||
|
||||
case ASM_SYS_VECTOR:
|
||||
case ASM_TRACE_VECTOR:
|
||||
case ASM_FLOATASSIST_VECTOR:
|
||||
|
||||
case ASM_ITLBMISS_VECTOR:
|
||||
case ASM_DTLBLMISS_VECTOR:
|
||||
case ASM_DTLBSMISS_VECTOR:
|
||||
|
||||
case ASM_IBREAK_VECTOR:
|
||||
case ASM_SYSMANAGE_VECTOR:
|
||||
return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mpc8xx_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
switch (current_ppc_cpu) {
|
||||
case PPC_8260:
|
||||
if (!mpc8260_vector_is_valid(vector)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("Please complete libcpu/powerpc/mpc8xx/exceptions/raw_exception.c\n");
|
||||
printk("current_ppc_cpu = %x\n", current_ppc_cpu);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_set_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if default handler is actually connected. If not issue an error.
|
||||
* You must first get the current handler via mpc8xx_get_current_exception
|
||||
* and then disconnect it using mpc8xx_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
if (memcmp(mpc8xx_get_vector_addr(except->exceptIndex), (void*)default_raw_except_entry.hdl.raw_hdl,default_raw_except_entry.hdl.raw_hdl_size)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
raw_except_table [except->exceptIndex] = *except;
|
||||
/*
|
||||
memmove((void*)mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size
|
||||
);
|
||||
*/
|
||||
codemove((void*)mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
|
||||
except->on(except);
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_get_current_exception (rtems_raw_except_connect_data* except)
|
||||
{
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
*except = raw_except_table [except->exceptIndex];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_delete_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)){
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if handler passed is actually connected. If not issue an error.
|
||||
* You must first get the current handler via mpc8xx_get_current_exception
|
||||
* and then disconnect it using mpc8xx_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
if (memcmp(mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
(void*)except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size)) {
|
||||
return 0;
|
||||
}
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
except->off(except);
|
||||
codemove((void*)mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
default_raw_except_entry.hdl.raw_hdl,
|
||||
default_raw_except_entry.hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
|
||||
|
||||
raw_except_table[except->exceptIndex] = default_raw_except_entry;
|
||||
raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
int mpc8xx_init_exceptions (rtems_raw_except_global_settings* config)
|
||||
{
|
||||
int i;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
/*
|
||||
* store various accelerators
|
||||
*/
|
||||
raw_except_table = config->rawExceptHdlTbl;
|
||||
local_settings = config;
|
||||
default_raw_except_entry = config->defaultRawEntry;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
for (i=0; i <= LAST_VALID_EXC; i++) {
|
||||
if (!mpc8xx_vector_is_valid(i)){
|
||||
continue;
|
||||
}
|
||||
codemove((void*)mpc8xx_get_vector_addr(i),
|
||||
raw_except_table[i].hdl.raw_hdl,
|
||||
raw_except_table[i].hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
|
||||
raw_except_table[i].on(&raw_except_table[i]);
|
||||
}
|
||||
else {
|
||||
raw_except_table[i].off(&raw_except_table[i]);
|
||||
}
|
||||
}
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_get_exception_config (rtems_raw_except_global_settings** config)
|
||||
{
|
||||
*config = local_settings;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* raw_execption.h
|
||||
*
|
||||
* This file contains implementation of C function to
|
||||
* Instanciate 8xx ppc primary exception entries.
|
||||
* More detailled information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC860
|
||||
* Risc Microporcessor User's Manual
|
||||
* Motorola REF : MPC860UM/AD 07/98 Rev .1
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* Modified Andy Dachs <a.dachs@sstl.co.uk>
|
||||
* Surrey Satellite Technology Limited (SSTL), 2001
|
||||
* for MPC8260
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _LIBCPU_RAW_EXCEPTION_H
|
||||
#define _LIBCPU_RAW_EXCEPTION_H
|
||||
|
||||
/*
|
||||
* Exception Vectors as defined in the MCP750 manual
|
||||
*/
|
||||
|
||||
#define ASM_RESET_VECTOR 0x01
|
||||
#define ASM_MACH_VECTOR 0x02
|
||||
#define ASM_PROT_VECTOR 0x03
|
||||
#define ASM_ISI_VECTOR 0x04
|
||||
#define ASM_EXT_VECTOR 0x05
|
||||
#define ASM_ALIGN_VECTOR 0x06
|
||||
#define ASM_PROG_VECTOR 0x07
|
||||
#define ASM_FLOAT_VECTOR 0x08
|
||||
#define ASM_DEC_VECTOR 0x09
|
||||
|
||||
#define ASM_SYS_VECTOR 0x0C
|
||||
#define ASM_TRACE_VECTOR 0x0D
|
||||
#define ASM_FLOATASSIST_VECTOR 0x0E
|
||||
|
||||
#define ASM_ITLBMISS_VECTOR 0x10
|
||||
#define ASM_DTLBLMISS_VECTOR 0x11
|
||||
#define ASM_DTLBSMISS_VECTOR 0x12
|
||||
#define ASM_IBREAK_VECTOR 0x13
|
||||
#define ASM_SYSMANAGE_VECTOR 0x14
|
||||
|
||||
#define LAST_VALID_EXC ASM_SYSMANAGE_VECTOR
|
||||
|
||||
/*
|
||||
* Vector offsets as defined in the MPC8260 manual
|
||||
*/
|
||||
|
||||
#define ASM_RESET_VECTOR_OFFSET (ASM_RESET_VECTOR << 8)
|
||||
#define ASM_MACH_VECTOR_OFFSET (ASM_MACH_VECTOR << 8)
|
||||
#define ASM_PROT_VECTOR_OFFSET (ASM_PROT_VECTOR << 8)
|
||||
#define ASM_ISI_VECTOR_OFFSET (ASM_ISI_VECTOR << 8)
|
||||
#define ASM_EXT_VECTOR_OFFSET (ASM_EXT_VECTOR << 8)
|
||||
#define ASM_ALIGN_VECTOR_OFFSET (ASM_ALIGN_VECTOR << 8)
|
||||
#define ASM_PROG_VECTOR_OFFSET (ASM_PROG_VECTOR << 8)
|
||||
#define ASM_FLOAT_VECTOR_OFFSET (ASM_FLOAT_VECTOR << 8)
|
||||
#define ASM_DEC_VECTOR_OFFSET (ASM_DEC_VECTOR << 8)
|
||||
|
||||
#define ASM_SYS_VECTOR_OFFSET (ASM_SYS_VECTOR << 8)
|
||||
#define ASM_TRACE_VECTOR_OFFSET (ASM_TRACE_VECTOR << 8)
|
||||
#define ASM_FLOATASSIST_VECTOR_OFFSET (ASM_FLOATASSIST_VECTOR << 8)
|
||||
|
||||
#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
|
||||
#define ASM_DTLBLMISS_VECTOR_OFFSET (ASM_DTLBLMISS_VECTOR << 8)
|
||||
#define ASM_DTLBSMISS_VECTOR_OFFSET (ASM_DTLBSMISS_VECTOR << 8)
|
||||
|
||||
#define ASM_IBREAK_VECTOR_OFFSET (ASM_IBREAK_VECTOR << 8)
|
||||
#define ASM_SYSMANAGE_VECTOR_OFFSET (ASM_SYSMANAGE_VECTOR << 8)
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
/*
|
||||
* Type definition for raw exceptions.
|
||||
*/
|
||||
|
||||
typedef unsigned char rtems_vector;
|
||||
struct __rtems_raw_except_connect_data__;
|
||||
typedef void (*rtems_raw_except_func) (void);
|
||||
typedef unsigned char rtems_raw_except_hdl_size;
|
||||
|
||||
typedef struct {
|
||||
rtems_vector vector;
|
||||
rtems_raw_except_func raw_hdl;
|
||||
rtems_raw_except_hdl_size raw_hdl_size;
|
||||
}rtems_raw_except_hdl;
|
||||
|
||||
typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef void (*rtems_raw_except_disable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef int (*rtems_raw_except_is_enabled) (const struct __rtems_raw_except_connect_data__*);
|
||||
|
||||
typedef struct __rtems_raw_except_connect_data__{
|
||||
/*
|
||||
* Exception vector (As defined in the manual)
|
||||
*/
|
||||
rtems_vector exceptIndex;
|
||||
/*
|
||||
* Exception raw handler. See comment on handler properties below in function prototype.
|
||||
*/
|
||||
rtems_raw_except_hdl hdl;
|
||||
/*
|
||||
* function for enabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must enable the except at processor level only.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_enable on;
|
||||
/*
|
||||
* function for disabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must disable the except both at device and PIC level.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_disable off;
|
||||
/*
|
||||
* function enabling to know what exception may currently occur
|
||||
*/
|
||||
rtems_raw_except_is_enabled isOn;
|
||||
}rtems_raw_except_connect_data;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* size of all the table fields (*Tbl) described below.
|
||||
*/
|
||||
unsigned int exceptSize;
|
||||
/*
|
||||
* Default handler used when disconnecting exceptions.
|
||||
*/
|
||||
rtems_raw_except_connect_data defaultRawEntry;
|
||||
/*
|
||||
* Table containing initials/current value.
|
||||
*/
|
||||
rtems_raw_except_connect_data* rawExceptHdlTbl;
|
||||
}rtems_raw_except_global_settings;
|
||||
|
||||
/*
|
||||
* C callable function enabling to set up one raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_set_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to get one current raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_get_current_exception (rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to remove one current raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_delete_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to check if vector is valid
|
||||
*/
|
||||
extern int mpc8xx_vector_is_valid(rtems_vector vector);
|
||||
|
||||
inline static void* mpc8xx_get_vector_addr(rtems_vector vector)
|
||||
{
|
||||
return ((void*) (((unsigned) vector) << 8));
|
||||
}
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
extern int mpc8xx_init_exceptions (rtems_raw_except_global_settings* config);
|
||||
extern int mpc8xx_get_exception_config (rtems_raw_except_global_settings** config);
|
||||
|
||||
# endif /* ASM */
|
||||
|
||||
#endif
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* asm_utils.s
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
*
|
||||
* This file contains the low-level support for moving exception
|
||||
* exception code to appropriate location.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <libcpu/io.h>
|
||||
|
||||
.globl codemove
|
||||
codemove:
|
||||
.type codemove,@function
|
||||
/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
|
||||
cmplw cr1,r3,r4
|
||||
addi r0,r5,3
|
||||
srwi. r0,r0,2
|
||||
beq cr1,4f /* In place copy is not necessary */
|
||||
beq 7f /* Protect against 0 count */
|
||||
mtctr r0
|
||||
bge cr1,2f
|
||||
|
||||
la r8,-4(r4)
|
||||
la r7,-4(r3)
|
||||
1: lwzu r0,4(r8)
|
||||
stwu r0,4(r7)
|
||||
bdnz 1b
|
||||
b 4f
|
||||
|
||||
2: slwi r0,r0,2
|
||||
add r8,r4,r0
|
||||
add r7,r3,r0
|
||||
3: lwzu r0,-4(r8)
|
||||
stwu r0,-4(r7)
|
||||
bdnz 3b
|
||||
|
||||
/* Now flush the cache: note that we must start from a cache aligned
|
||||
* address. Otherwise we might miss one cache line.
|
||||
*/
|
||||
4: cmpwi r6,0
|
||||
add r5,r3,r5
|
||||
beq 7f /* Always flush prefetch queue in any case */
|
||||
subi r0,r6,1
|
||||
andc r3,r3,r0
|
||||
mr r4,r3
|
||||
5: cmplw r4,r5
|
||||
dcbst 0,r4
|
||||
add r4,r4,r6
|
||||
blt 5b
|
||||
sync /* Wait for all dcbst to complete on bus */
|
||||
mr r4,r3
|
||||
6: cmplw r4,r5
|
||||
icbi 0,r4
|
||||
add r4,r4,r6
|
||||
blt 6b
|
||||
7: sync /* Wait for all icbi to complete on bus */
|
||||
isync
|
||||
blr
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* raw_exception.c - This file contains implementation of C function to
|
||||
* Instanciate 8xx ppc primary exception entries.
|
||||
* More detailled information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC860
|
||||
* Risc Microporcessor User's Manual
|
||||
* Motorola REF : MPC860UM/AD
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <rtems/score/powerpc.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
#include <rtems/bspIo.h> /* for printk */
|
||||
#include <string.h>
|
||||
|
||||
void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
|
||||
static rtems_raw_except_connect_data* raw_except_table;
|
||||
static rtems_raw_except_connect_data default_raw_except_entry;
|
||||
static rtems_raw_except_global_settings* local_settings;
|
||||
|
||||
int mpc860_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
switch(vector) {
|
||||
case ASM_RESET_VECTOR: /* fall through */
|
||||
case ASM_MACH_VECTOR:
|
||||
case ASM_PROT_VECTOR:
|
||||
case ASM_ISI_VECTOR:
|
||||
case ASM_EXT_VECTOR:
|
||||
case ASM_ALIGN_VECTOR:
|
||||
case ASM_PROG_VECTOR:
|
||||
case ASM_FLOAT_VECTOR:
|
||||
case ASM_DEC_VECTOR:
|
||||
|
||||
case ASM_SYS_VECTOR:
|
||||
case ASM_TRACE_VECTOR:
|
||||
case ASM_FLOATASSIST_VECTOR:
|
||||
|
||||
case ASM_SOFTEMUL_VECTOR:
|
||||
case ASM_ITLBMISS_VECTOR:
|
||||
case ASM_DTLBMISS_VECTOR:
|
||||
case ASM_ITLBERROR_VECTOR:
|
||||
case ASM_DTLBERROR_VECTOR:
|
||||
|
||||
case ASM_DBREAK_VECTOR:
|
||||
case ASM_IBREAK_VECTOR:
|
||||
case ASM_PERIFBREAK_VECTOR:
|
||||
case ASM_DEVPORT_VECTOR:
|
||||
return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mpc8xx_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
switch (current_ppc_cpu) {
|
||||
case PPC_860:
|
||||
if (!mpc860_vector_is_valid(vector)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("Please complete libcpu/powerpc/mpc8xx/exceptions/raw_exception.c\n");
|
||||
printk("current_ppc_cpu = %x\n", current_ppc_cpu);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_set_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if default handler is actually connected. If not issue an error.
|
||||
* You must first get the current handler via mpc8xx_get_current_exception
|
||||
* and then disconnect it using mpc8xx_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
if (memcmp(mpc8xx_get_vector_addr(except->exceptIndex), (void*)default_raw_except_entry.hdl.raw_hdl,default_raw_except_entry.hdl.raw_hdl_size)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
raw_except_table [except->exceptIndex] = *except;
|
||||
codemove((void*)mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
except->on(except);
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_get_current_exception (rtems_raw_except_connect_data* except)
|
||||
{
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
*except = raw_except_table [except->exceptIndex];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_delete_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if (!mpc8xx_vector_is_valid(except->exceptIndex)){
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if handler passed is actually connected. If not issue an error.
|
||||
* You must first get the current handler via mpc8xx_get_current_exception
|
||||
* and then disconnect it using mpc8xx_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
if (memcmp(mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
(void*)except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size)) {
|
||||
return 0;
|
||||
}
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
except->off(except);
|
||||
codemove((void*)mpc8xx_get_vector_addr(except->exceptIndex),
|
||||
default_raw_except_entry.hdl.raw_hdl,
|
||||
default_raw_except_entry.hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
|
||||
|
||||
raw_except_table[except->exceptIndex] = default_raw_except_entry;
|
||||
raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
int mpc8xx_init_exceptions (rtems_raw_except_global_settings* config)
|
||||
{
|
||||
int i;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
/*
|
||||
* store various accelerators
|
||||
*/
|
||||
raw_except_table = config->rawExceptHdlTbl;
|
||||
local_settings = config;
|
||||
default_raw_except_entry = config->defaultRawEntry;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
for (i=0; i <= LAST_VALID_EXC; i++) {
|
||||
if (!mpc8xx_vector_is_valid(i)){
|
||||
continue;
|
||||
}
|
||||
codemove((void*)mpc8xx_get_vector_addr(i),
|
||||
raw_except_table[i].hdl.raw_hdl,
|
||||
raw_except_table[i].hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
|
||||
raw_except_table[i].on(&raw_except_table[i]);
|
||||
}
|
||||
else {
|
||||
raw_except_table[i].off(&raw_except_table[i]);
|
||||
}
|
||||
}
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mpc8xx_get_exception_config (rtems_raw_except_global_settings** config)
|
||||
{
|
||||
*config = local_settings;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* raw_execption.h
|
||||
*
|
||||
* This file contains implementation of C function to
|
||||
* Instanciate 8xx ppc primary exception entries.
|
||||
* More detailled information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC860
|
||||
* Risc Microporcessor User's Manual
|
||||
* Motorola REF : MPC860UM/AD 07/98 Rev .1
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _LIBCPU_RAW_EXCEPTION_H
|
||||
#define _LIBCPU_RAW_EXCEPTION_H
|
||||
|
||||
/*
|
||||
* Exception Vectors as defined in the MCP750 manual
|
||||
*/
|
||||
|
||||
#define ASM_RESET_VECTOR 0x01
|
||||
#define ASM_MACH_VECTOR 0x02
|
||||
#define ASM_PROT_VECTOR 0x03
|
||||
#define ASM_ISI_VECTOR 0x04
|
||||
#define ASM_EXT_VECTOR 0x05
|
||||
#define ASM_ALIGN_VECTOR 0x06
|
||||
#define ASM_PROG_VECTOR 0x07
|
||||
#define ASM_FLOAT_VECTOR 0x08
|
||||
#define ASM_DEC_VECTOR 0x09
|
||||
|
||||
#define ASM_SYS_VECTOR 0x0C
|
||||
#define ASM_TRACE_VECTOR 0x0D
|
||||
#define ASM_FLOATASSIST_VECTOR 0x0E
|
||||
|
||||
#define ASM_SOFTEMUL_VECTOR 0x10
|
||||
#define ASM_ITLBMISS_VECTOR 0x11
|
||||
#define ASM_DTLBMISS_VECTOR 0x12
|
||||
#define ASM_ITLBERROR_VECTOR 0x13
|
||||
#define ASM_DTLBERROR_VECTOR 0x14
|
||||
|
||||
#define ASM_DBREAK_VECTOR 0x1C
|
||||
#define ASM_IBREAK_VECTOR 0x1D
|
||||
#define ASM_PERIFBREAK_VECTOR 0x1E
|
||||
#define ASM_DEVPORT_VECTOR 0x1F
|
||||
|
||||
#define LAST_VALID_EXC ASM_DEVPORT_VECTOR
|
||||
|
||||
/*
|
||||
* Vector offsets as defined in the MPC860 manual
|
||||
*/
|
||||
|
||||
#define ASM_RESET_VECTOR_OFFSET (ASM_RESET_VECTOR << 8)
|
||||
#define ASM_MACH_VECTOR_OFFSET (ASM_MACH_VECTOR << 8)
|
||||
#define ASM_PROT_VECTOR_OFFSET (ASM_PROT_VECTOR << 8)
|
||||
#define ASM_ISI_VECTOR_OFFSET (ASM_ISI_VECTOR << 8)
|
||||
#define ASM_EXT_VECTOR_OFFSET (ASM_EXT_VECTOR << 8)
|
||||
#define ASM_ALIGN_VECTOR_OFFSET (ASM_ALIGN_VECTOR << 8)
|
||||
#define ASM_PROG_VECTOR_OFFSET (ASM_PROG_VECTOR << 8)
|
||||
#define ASM_FLOAT_VECTOR_OFFSET (ASM_FLOAT_VECTOR << 8)
|
||||
#define ASM_DEC_VECTOR_OFFSET (ASM_DEC_VECTOR << 8)
|
||||
|
||||
#define ASM_SYS_VECTOR_OFFSET (ASM_SYS_VECTOR << 8)
|
||||
#define ASM_TRACE_VECTOR_OFFSET (ASM_TRACE_VECTOR << 8)
|
||||
#define ASM_FLOATASSIST_VECTOR_OFFSET (ASM_FLOATASSIST_VECTOR << 8)
|
||||
|
||||
#define ASM_SOFTEMUL_VECTOR_OFFSET (ASM_SOFTEMUL_VECTOR << 8)
|
||||
#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
|
||||
#define ASM_DTLBMISS_VECTOR_OFFSET (ASM_DTLBMISS_VECTOR << 8)
|
||||
#define ASM_ITLBERROR_VECTOR_OFFSET (ASM_ITLBERROR_VECTOR << 8)
|
||||
#define ASM_DTLBERROR_VECTOR_OFFSET (ASM_DTLBERROR_VECTOR << 8)
|
||||
|
||||
#define ASM_DBREAK_VECTOR_OFFSET (ASM_DBREAK_VECTOR << 8)
|
||||
#define ASM_IBREAK_VECTOR_OFFSET (ASM_IBREAK_VECTOR << 8)
|
||||
#define ASM_PERIFBREAK_VECTOR_OFFSET (ASM_PERIFBREAK_VECTOR << 8)
|
||||
#define ASM_DEVPORT_VECTOR_OFFSET (ASM_DEVPORT_VECTOR_OFFSET << 8)
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
/*
|
||||
* Type definition for raw exceptions.
|
||||
*/
|
||||
|
||||
typedef unsigned char rtems_vector;
|
||||
struct __rtems_raw_except_connect_data__;
|
||||
typedef void (*rtems_raw_except_func) (void);
|
||||
typedef unsigned char rtems_raw_except_hdl_size;
|
||||
|
||||
typedef struct {
|
||||
rtems_vector vector;
|
||||
rtems_raw_except_func raw_hdl;
|
||||
rtems_raw_except_hdl_size raw_hdl_size;
|
||||
}rtems_raw_except_hdl;
|
||||
|
||||
typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef void (*rtems_raw_except_disable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef int (*rtems_raw_except_is_enabled) (const struct __rtems_raw_except_connect_data__*);
|
||||
|
||||
typedef struct __rtems_raw_except_connect_data__{
|
||||
/*
|
||||
* Exception vector (As defined in the manual)
|
||||
*/
|
||||
rtems_vector exceptIndex;
|
||||
/*
|
||||
* Exception raw handler. See comment on handler properties below in function prototype.
|
||||
*/
|
||||
rtems_raw_except_hdl hdl;
|
||||
/*
|
||||
* function for enabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must enable the except at processor level only.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_enable on;
|
||||
/*
|
||||
* function for disabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must disable the except both at device and PIC level.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_disable off;
|
||||
/*
|
||||
* function enabling to know what exception may currently occur
|
||||
*/
|
||||
rtems_raw_except_is_enabled isOn;
|
||||
}rtems_raw_except_connect_data;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* size of all the table fields (*Tbl) described below.
|
||||
*/
|
||||
unsigned int exceptSize;
|
||||
/*
|
||||
* Default handler used when disconnecting exceptions.
|
||||
*/
|
||||
rtems_raw_except_connect_data defaultRawEntry;
|
||||
/*
|
||||
* Table containing initials/current value.
|
||||
*/
|
||||
rtems_raw_except_connect_data* rawExceptHdlTbl;
|
||||
}rtems_raw_except_global_settings;
|
||||
|
||||
/*
|
||||
* C callable function enabling to set up one raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_set_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to get one current raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_get_current_exception (rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to remove one current raw idt entry
|
||||
*/
|
||||
extern int mpc8xx_delete_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to check if vector is valid
|
||||
*/
|
||||
extern int mpc8xx_vector_is_valid(rtems_vector vector);
|
||||
|
||||
inline static void* mpc8xx_get_vector_addr(rtems_vector vector)
|
||||
{
|
||||
return ((void*) (((unsigned) vector) << 8));
|
||||
}
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
extern int mpc8xx_init_exceptions (rtems_raw_except_global_settings* config);
|
||||
extern int mpc8xx_get_exception_config (rtems_raw_except_global_settings** config);
|
||||
|
||||
# endif /* ASM */
|
||||
|
||||
#endif
|
||||
@@ -1,482 +0,0 @@
|
||||
/*
|
||||
* vectors_init.c Exception hanlding initialisation (and generic handler).
|
||||
*
|
||||
* This include file describe the data structure and the functions implemented
|
||||
* by rtems to handle exceptions.
|
||||
*
|
||||
* Copyright (C) 1999 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <rtems.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <libcpu/spr.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
|
||||
#include "vectors.h"
|
||||
#include "ppc_exc_bspsupp.h"
|
||||
|
||||
static rtems_raw_except_global_settings exception_config;
|
||||
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
|
||||
|
||||
uint32_t ppc_exc_cache_wb_check = 1;
|
||||
|
||||
#if 0
|
||||
typedef struct ppc_exc_connect_data_ {
|
||||
rtems_raw_except_connect_data raw;
|
||||
ppc_exc_handler_t c_hdl;
|
||||
} ppc_exc_connect_data;
|
||||
#endif
|
||||
|
||||
exception_handler_t globalExceptHdl;
|
||||
|
||||
/* T. Straumann: provide a stack trace
|
||||
* <strauman@slac.stanford.edu>, 6/26/2001
|
||||
*/
|
||||
typedef struct LRFrameRec_ {
|
||||
struct LRFrameRec_ *frameLink;
|
||||
unsigned long *lr;
|
||||
} LRFrameRec, *LRFrame;
|
||||
|
||||
#define STACK_CLAMP 50 /* in case we have a corrupted bottom */
|
||||
|
||||
SPR_RW(SPRG1)
|
||||
SPR_RW(SPRG2)
|
||||
SPR_RO(LR)
|
||||
SPR_RO(DAR)
|
||||
SPR_RO(DEAR_BOOKE)
|
||||
SPR_RO(DEAR_405)
|
||||
|
||||
uint32_t ppc_exc_get_DAR_dflt(void)
|
||||
{
|
||||
if ( ppc_cpu_is_60x() )
|
||||
return _read_DAR();
|
||||
else switch ( ppc_cpu_is_bookE() ) {
|
||||
default: break;
|
||||
case PPC_BOOKE_STD:
|
||||
case PPC_BOOKE_E500:
|
||||
return _read_DEAR_BOOKE();
|
||||
case PPC_BOOKE_405:
|
||||
return _read_DEAR_405();
|
||||
}
|
||||
return 0xdeadbeef;
|
||||
}
|
||||
|
||||
uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt;
|
||||
|
||||
void
|
||||
BSP_printStackTrace(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
LRFrame f;
|
||||
int i;
|
||||
LRFrame sp;
|
||||
void *lr;
|
||||
|
||||
printk("Stack Trace: \n ");
|
||||
if (excPtr) {
|
||||
printk("IP: 0x%08x, ",excPtr->EXC_SRR0);
|
||||
sp=(LRFrame)excPtr->GPR1;
|
||||
lr=(void*)excPtr->EXC_LR;
|
||||
} else {
|
||||
/* there's no macro for this */
|
||||
__asm__ __volatile__("mr %0, 1":"=r"(sp));
|
||||
lr=(LRFrame)_read_LR();
|
||||
}
|
||||
printk("LR: 0x%08x\n",lr);
|
||||
for (f=(LRFrame)sp, i=0; f->frameLink && i<STACK_CLAMP; f=f->frameLink) {
|
||||
printk("--^ 0x%08x", (long)(f->frameLink->lr));
|
||||
if (!(++i%5))
|
||||
printk("\n");
|
||||
}
|
||||
if (i>=STACK_CLAMP) {
|
||||
printk("Too many stack frames (stack possibly corrupted), giving up...\n");
|
||||
} else {
|
||||
if (i%5)
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void C_exception_handler(BSP_Exception_frame* excPtr)
|
||||
{
|
||||
static int nest = 0;
|
||||
|
||||
int recoverable = 0;
|
||||
rtems_id id = 0;
|
||||
int synch;
|
||||
unsigned n;
|
||||
rtems_status_code sc;
|
||||
|
||||
/* Catch recursion */
|
||||
nest++;
|
||||
|
||||
if ( nest > 2 ) {
|
||||
/* maybe printk() or dereferencing excPtr caused an exception;
|
||||
* die silently...
|
||||
*/
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
synch = (int)excPtr->_EXC_number >= 0 ;
|
||||
n = excPtr->_EXC_number & 0x7fff;
|
||||
|
||||
printk("Exception handler called for exception %d (0x%x)\n", n, n);
|
||||
printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0);
|
||||
printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1);
|
||||
|
||||
if ( nest > 1 ) {
|
||||
printk("Recursion in the exception handler detected; I'll spin now...\n");
|
||||
while ( 1 )
|
||||
;
|
||||
}
|
||||
|
||||
/* Try to find out more about the context where this happened */
|
||||
printk("\t Context: ");
|
||||
if ( rtems_interrupt_is_in_progress() ) {
|
||||
printk("ISR");
|
||||
} else if ( !_Thread_Executing ) {
|
||||
printk("Initialization (_Thread_Executing not available yet)");
|
||||
} else {
|
||||
if ( RTEMS_SUCCESSFUL != (sc=rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id)) ) {
|
||||
printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc);
|
||||
id = 0;
|
||||
} else {
|
||||
printk("Task ID 0x%08x", id);
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
/* Dump registers */
|
||||
|
||||
printk("\t R0 = %08x", excPtr->GPR0);
|
||||
if ( synch ) {
|
||||
printk(" R1 = %08x", excPtr->GPR1);
|
||||
printk(" R2 = %08x", excPtr->GPR2);
|
||||
} else {
|
||||
printk(" ");
|
||||
printk(" ");
|
||||
}
|
||||
printk(" R3 = %08x\n", excPtr->GPR3);
|
||||
printk("\t R4 = %08x", excPtr->GPR4);
|
||||
printk(" R5 = %08x", excPtr->GPR5);
|
||||
printk(" R6 = %08x", excPtr->GPR6);
|
||||
printk(" R7 = %08x\n", excPtr->GPR7);
|
||||
printk("\t R8 = %08x", excPtr->GPR8);
|
||||
printk(" R9 = %08x", excPtr->GPR9);
|
||||
printk(" R10 = %08x", excPtr->GPR10);
|
||||
printk(" R11 = %08x\n", excPtr->GPR11);
|
||||
printk("\t R12 = %08x", excPtr->GPR12);
|
||||
if ( synch ) {
|
||||
printk(" R13 = %08x", excPtr->GPR13);
|
||||
printk(" R14 = %08x", excPtr->GPR14);
|
||||
printk(" R15 = %08x\n", excPtr->GPR15);
|
||||
printk("\t R16 = %08x", excPtr->GPR16);
|
||||
printk(" R17 = %08x", excPtr->GPR17);
|
||||
printk(" R18 = %08x", excPtr->GPR18);
|
||||
printk(" R19 = %08x\n", excPtr->GPR19);
|
||||
printk("\t R20 = %08x", excPtr->GPR20);
|
||||
printk(" R21 = %08x", excPtr->GPR21);
|
||||
printk(" R22 = %08x", excPtr->GPR22);
|
||||
printk(" R23 = %08x\n", excPtr->GPR23);
|
||||
printk("\t R24 = %08x", excPtr->GPR24);
|
||||
printk(" R25 = %08x", excPtr->GPR25);
|
||||
printk(" R26 = %08x", excPtr->GPR26);
|
||||
printk(" R27 = %08x\n", excPtr->GPR27);
|
||||
printk("\t R28 = %08x", excPtr->GPR28);
|
||||
printk(" R29 = %08x", excPtr->GPR29);
|
||||
printk(" R30 = %08x", excPtr->GPR30);
|
||||
printk(" R31 = %08x\n", excPtr->GPR31);
|
||||
} else {
|
||||
printk("\n");
|
||||
}
|
||||
printk("\t CR = %08x\n", excPtr->EXC_CR);
|
||||
printk("\t CTR = %08x\n", excPtr->EXC_CTR);
|
||||
printk("\t XER = %08x\n", excPtr->EXC_XER);
|
||||
printk("\t LR = %08x\n", excPtr->EXC_LR);
|
||||
|
||||
/* Would be great to print DAR but unfortunately,
|
||||
* that is not portable across different CPUs.
|
||||
* AFAIK on classic PPC DAR is SPR 19, on the
|
||||
* 405 we have DEAR = SPR 0x3d5 and booE says
|
||||
* DEAR = SPR 61 :-(
|
||||
*/
|
||||
if ( ppc_exc_get_DAR ) {
|
||||
printk("\t DAR = %08x\n", ppc_exc_get_DAR());
|
||||
}
|
||||
|
||||
BSP_printStackTrace(excPtr);
|
||||
|
||||
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
|
||||
recoverable = 1;
|
||||
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
|
||||
#ifdef TEST_RAW_EXCEPTION_CODE
|
||||
recoverable = 1;
|
||||
#else
|
||||
recoverable = 0;
|
||||
#endif
|
||||
if (!recoverable) {
|
||||
if ( id ) {
|
||||
printk("Suspending faulting task (0x%08x)\n", id);
|
||||
/* Unnest here because rtems_task_suspend() never returns */
|
||||
nest--;
|
||||
rtems_task_suspend(id);
|
||||
} else {
|
||||
printk("unrecoverable exception!!! Push reset button\n");
|
||||
while(1);
|
||||
}
|
||||
} else {
|
||||
nest--;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* dummy functions for on/off/isOn calls
|
||||
* these functions just do nothing fulfill the semantic
|
||||
* requirements to enable/disable a certain exception
|
||||
*/
|
||||
void exception_nop_enable(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
}
|
||||
|
||||
int exception_always_enabled(const rtems_raw_except_connect_data* ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Raw exception framework wants to keep a pointer to
|
||||
* the prologue so we must keep the ones we generate
|
||||
* from templates around...
|
||||
*/
|
||||
#define NUM_PROLOG 8 /* just a reasonable limit */
|
||||
static int n_prolog = 0;
|
||||
static ppc_exc_min_prolog_t prologues[NUM_PROLOG];
|
||||
|
||||
static ppc_exc_min_prolog_template_t prolog_templates[][2] = {
|
||||
[ PPC_EXC_CLASSIC ] =
|
||||
{
|
||||
ppc_exc_min_prolog_sync_tmpl_std,
|
||||
ppc_exc_min_prolog_async_tmpl_std,
|
||||
},
|
||||
[ PPC_EXC_405_CRITICAL ] =
|
||||
{
|
||||
ppc_exc_min_prolog_sync_tmpl_p405_crit,
|
||||
ppc_exc_min_prolog_async_tmpl_p405_crit,
|
||||
},
|
||||
[ PPC_EXC_BOOKE_CRITICAL ] =
|
||||
{
|
||||
ppc_exc_min_prolog_sync_tmpl_bookE_crit,
|
||||
ppc_exc_min_prolog_async_tmpl_bookE_crit,
|
||||
},
|
||||
[ PPC_EXC_E500_MACHCHK ] =
|
||||
{
|
||||
ppc_exc_min_prolog_sync_tmpl_e500_mchk,
|
||||
ppc_exc_min_prolog_async_tmpl_e500_mchk,
|
||||
},
|
||||
};
|
||||
|
||||
static rtems_raw_except_func
|
||||
make_prologue(int vector, ppc_raw_exception_category cat)
|
||||
{
|
||||
int async = (cat & PPC_EXC_ASYNC) ? 1 : 0 ;
|
||||
ppc_exc_min_prolog_template_t tmpl;
|
||||
|
||||
cat &= ~PPC_EXC_ASYNC;
|
||||
|
||||
if ( n_prolog >= NUM_PROLOG ) {
|
||||
rtems_panic("Not enough exception prologue slots; increase NUM_PROLOG (%s)\n",__FILE__);
|
||||
}
|
||||
|
||||
if ( ! (tmpl = prolog_templates[cat][async]) ) {
|
||||
rtems_panic("No exception prologue template for category 0x%02x found\n", cat);
|
||||
}
|
||||
|
||||
ppc_exc_min_prolog_expand(prologues[n_prolog], tmpl, vector);
|
||||
|
||||
return (rtems_raw_except_func)prologues[n_prolog++];
|
||||
}
|
||||
|
||||
void ppc_exc_table_init(
|
||||
rtems_raw_except_connect_data *exception_table,
|
||||
int nEntries)
|
||||
{
|
||||
unsigned i,v;
|
||||
ppc_raw_exception_category cat;
|
||||
uintptr_t vaddr;
|
||||
|
||||
/*
|
||||
* Initialize pointer used by low level execption handling
|
||||
*/
|
||||
globalExceptHdl = C_exception_handler;
|
||||
/*
|
||||
* Put default_exception_vector_code_prolog at relevant exception
|
||||
* code entry addresses
|
||||
*/
|
||||
exception_config.exceptSize = nEntries;
|
||||
exception_config.rawExceptHdlTbl = exception_table;
|
||||
exception_config.defaultRawEntry.exceptIndex = 0;
|
||||
exception_config.defaultRawEntry.hdl.vector = 0;
|
||||
|
||||
if (ppc_cpu_has_ivpr_and_ivor()) {
|
||||
/* Use packed version with 16-byte boundaries for CPUs with IVPR and IVOR registers */
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl = ppc_exc_min_prolog_auto_packed;
|
||||
} else {
|
||||
/* Note that the 'auto' handler cannot be used for everything; in particular,
|
||||
* it assumes classic exceptions with a vector offset aligned on a 256-byte
|
||||
* boundary.
|
||||
*/
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl = ppc_exc_min_prolog_auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the cast of an array address to an unsigned
|
||||
* is not a bug as it is defined by a .set directly in asm...
|
||||
*/
|
||||
exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
|
||||
|
||||
for (i=0; i < exception_config.exceptSize; i++) {
|
||||
|
||||
if ( PPC_EXC_INVALID == (cat = ppc_vector_is_valid ((v=exception_table[i].hdl.vector))) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
exception_table[i].exceptIndex = i;
|
||||
exception_table[v].hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
|
||||
|
||||
/* special cases */
|
||||
if ( ppc_cpu_has_shadowed_gprs()
|
||||
&& ( ASM_60X_IMISS_VECTOR == v
|
||||
|| ASM_60X_DLMISS_VECTOR == v
|
||||
|| ASM_60X_DSMISS_VECTOR == v ) ) {
|
||||
exception_table[i].hdl.raw_hdl = ppc_exc_tgpr_clr_prolog;
|
||||
exception_table[i].hdl.raw_hdl_size = (unsigned)ppc_exc_tgpr_clr_prolog_size;
|
||||
} else {
|
||||
|
||||
vaddr = (uintptr_t)ppc_get_vector_addr( v );
|
||||
|
||||
/*
|
||||
* default prolog can handle classic, synchronous exceptions
|
||||
* with a vector offset aligned on a 256-byte boundary.
|
||||
*/
|
||||
if (cat == PPC_EXC_CLASSIC && ((vaddr & 0xff) == 0 || (ppc_cpu_has_ivpr_and_ivor() && (vaddr & 0xf) == 0))) {
|
||||
exception_table[i].hdl.raw_hdl_size = exception_config.defaultRawEntry.hdl.raw_hdl_size;
|
||||
exception_table[i].hdl.raw_hdl = exception_config.defaultRawEntry.hdl.raw_hdl;
|
||||
} else {
|
||||
exception_table[i].hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
|
||||
exception_table[i].hdl.raw_hdl = make_prologue( v, cat );
|
||||
}
|
||||
|
||||
}
|
||||
exception_table[i].on = exception_nop_enable;
|
||||
exception_table[i].off = exception_nop_enable;
|
||||
exception_table[i].isOn = exception_always_enabled;
|
||||
}
|
||||
if (!ppc_init_exceptions(&exception_config)) {
|
||||
BSP_panic("Exception handling initialization failed\n");
|
||||
}
|
||||
#ifdef RTEMS_DEBUG
|
||||
else {
|
||||
printk("Exception handling initialization done\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ppc_exc_initialize(
|
||||
uint32_t interrupt_disable_mask,
|
||||
uint32_t interrupt_stack_start,
|
||||
uint32_t interrupt_stack_size
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int n = sizeof(exception_table)/sizeof(exception_table[0]);
|
||||
|
||||
uint32_t interrupt_stack_end = 0;
|
||||
uint32_t interrupt_stack_pointer = 0;
|
||||
uint32_t *p = NULL;
|
||||
uint32_t r13, sda_base;
|
||||
|
||||
/* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure
|
||||
* early init code put it there.
|
||||
*/
|
||||
asm volatile(
|
||||
" lis %0, _SDA_BASE_@h \n"
|
||||
" ori %0, %0, _SDA_BASE_@l \n"
|
||||
" mr %1, 13 \n"
|
||||
:"=r"(sda_base),"=r"(r13)
|
||||
);
|
||||
|
||||
if ( sda_base != r13 ) {
|
||||
printk("ppc_exc_initialize(): INTERNAL ERROR\n");
|
||||
printk(" your BSP seems to not have loaded _SDA_BASE_\n");
|
||||
printk(" into R13 as required by SVR4/EABI. Check early init code...\n");
|
||||
printk(" _SDA_BASE_: 0x%08x, R13: 0x%08x\n", sda_base, r13);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/* Interrupt stack end and pointer */
|
||||
interrupt_stack_end = interrupt_stack_start + interrupt_stack_size;
|
||||
|
||||
interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
|
||||
|
||||
/* Ensure proper interrupt stack alignment */
|
||||
interrupt_stack_pointer &= ~(CPU_STACK_ALIGNMENT - 1);
|
||||
|
||||
/* Tag interrupt stack bottom */
|
||||
p = (uint32_t *) interrupt_stack_pointer;
|
||||
*p = 0;
|
||||
|
||||
/* Move interrupt stack values to special purpose registers */
|
||||
_write_SPRG1( interrupt_stack_pointer);
|
||||
_write_SPRG2( interrupt_stack_start);
|
||||
|
||||
/* Interrupt disable mask */
|
||||
ppc_interrupt_set_disable_mask( interrupt_disable_mask);
|
||||
|
||||
/* Use current MMU / RI settings when running C exception handlers */
|
||||
ppc_exc_msr_bits = _read_MSR() & ( MSR_DR | MSR_IR | MSR_RI );
|
||||
|
||||
for ( i=0; i<n; i++ )
|
||||
exception_table[i].hdl.vector = i;
|
||||
ppc_exc_table_init(exception_table, n);
|
||||
|
||||
/* If we are on a classic PPC with MSR_DR enabled then
|
||||
* assert that the mapping for at least this task's
|
||||
* stack is write-back-caching enabled (see README/CAVEATS)
|
||||
* Do this only if the cache is physically enabled.
|
||||
* Since it is not easy to figure that out in a
|
||||
* generic way we need help from the BSP: BSPs
|
||||
* which run entirely w/o the cache may set
|
||||
* ppc_exc_cache_wb_check to zero prior to calling
|
||||
* this routine.
|
||||
*
|
||||
* We run this check only after exception handling is
|
||||
* initialized so that we have some chance to get
|
||||
* information printed if it fails.
|
||||
*
|
||||
* Note that it is unsafe to ignore this issue; if
|
||||
* the check fails, do NOT disable it unless caches
|
||||
* are always physically disabled.
|
||||
*/
|
||||
if ( ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits) ) {
|
||||
/* The size of 63 assumes cache lines are at most 32 bytes */
|
||||
uint8_t dummy[63];
|
||||
uintptr_t p = (uintptr_t)dummy;
|
||||
/* If the dcbz instruction raises an alignment exception
|
||||
* then the stack is mapped as write-thru or caching-disabled.
|
||||
* The low-level code is not capable of dealing with this
|
||||
* ATM.
|
||||
*/
|
||||
p = (p + 31) & ~31;
|
||||
asm volatile("dcbz 0, %0"::"b"(p));
|
||||
/* If we make it thru here then things seem to be OK */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#include <libcpu/cpuIdent.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
|
||||
#define MTIVPR(prefix) asm volatile("mtivpr %0"::"r"(prefix));
|
||||
#define MTIVOR(x, vec) asm volatile("mtivor"#x" %0"::"r"(vec));
|
||||
|
||||
/* Use during early init for initializing the e500 IVOR/IVPR registers */
|
||||
void
|
||||
e500_setup_raw_exceptions(void)
|
||||
{
|
||||
unsigned c;
|
||||
if ( ! (c = ppc_cpu_is_bookE()) || PPC_BOOKE_405 == c )
|
||||
return;
|
||||
|
||||
/* Set interupt vector prefix register */
|
||||
MTIVPR( ppc_exc_vector_base);
|
||||
|
||||
/* setup vectors to be compatible with classic PPC */
|
||||
MTIVOR(0, ppc_get_vector_addr(ASM_BOOKE_CRIT_VECTOR)); /* Critical input not (yet) supported; use reset vector */
|
||||
MTIVOR(1, ppc_get_vector_addr(ASM_MACH_VECTOR));
|
||||
MTIVOR(2, ppc_get_vector_addr(ASM_PROT_VECTOR));
|
||||
MTIVOR(3, ppc_get_vector_addr(ASM_ISI_VECTOR));
|
||||
MTIVOR(4, ppc_get_vector_addr(ASM_EXT_VECTOR));
|
||||
MTIVOR(5, ppc_get_vector_addr(ASM_ALIGN_VECTOR));
|
||||
MTIVOR(6, ppc_get_vector_addr(ASM_PROG_VECTOR));
|
||||
MTIVOR(7, ppc_get_vector_addr(ASM_FLOAT_VECTOR));
|
||||
MTIVOR(8, ppc_get_vector_addr(ASM_SYS_VECTOR));
|
||||
MTIVOR(9, ppc_get_vector_addr(0x0b));
|
||||
MTIVOR(10, ppc_get_vector_addr(ASM_BOOKE_DEC_VECTOR));
|
||||
MTIVOR(11, ppc_get_vector_addr(ASM_BOOKE_FIT_VECTOR));
|
||||
MTIVOR(12, ppc_get_vector_addr(ASM_BOOKE_WDOG_VECTOR));
|
||||
MTIVOR(13, ppc_get_vector_addr(ASM_60X_DSMISS_VECTOR));
|
||||
MTIVOR(14, ppc_get_vector_addr(ASM_60X_DLMISS_VECTOR));
|
||||
MTIVOR(15, ppc_get_vector_addr(ASM_TRACE_VECTOR));
|
||||
MTIVOR(32, ppc_get_vector_addr(ASM_60X_VEC_VECTOR));
|
||||
MTIVOR(33, ppc_get_vector_addr(0x16));
|
||||
MTIVOR(34, ppc_get_vector_addr(0x15));
|
||||
MTIVOR(35, ppc_get_vector_addr(ASM_60X_PERFMON_VECTOR));
|
||||
}
|
||||
|
||||
void e200_setup_raw_exceptions(void)
|
||||
{
|
||||
if (current_ppc_cpu != PPC_e200z6) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Interupt vector prefix register */
|
||||
MTIVPR( ppc_exc_vector_base);
|
||||
|
||||
/* Interupt vector offset register */
|
||||
MTIVOR( 0, 0); /* Critical input */
|
||||
MTIVOR( 1, ppc_get_vector_addr( ASM_MACH_VECTOR));
|
||||
MTIVOR( 2, ppc_get_vector_addr( ASM_PROT_VECTOR));
|
||||
MTIVOR( 3, ppc_get_vector_addr( ASM_ISI_VECTOR));
|
||||
MTIVOR( 4, ppc_get_vector_addr( ASM_EXT_VECTOR));
|
||||
MTIVOR( 5, ppc_get_vector_addr( ASM_ALIGN_VECTOR));
|
||||
MTIVOR( 6, ppc_get_vector_addr( ASM_PROG_VECTOR));
|
||||
MTIVOR( 7, ppc_get_vector_addr( ASM_FLOAT_VECTOR));
|
||||
MTIVOR( 8, ppc_get_vector_addr( ASM_SYS_VECTOR));
|
||||
MTIVOR( 9, 0); /* APU unavailable */
|
||||
MTIVOR( 10, ppc_get_vector_addr( ASM_BOOKE_DEC_VECTOR));
|
||||
MTIVOR( 11, ppc_get_vector_addr( ASM_BOOKE_FIT_VECTOR));
|
||||
MTIVOR( 12, ppc_get_vector_addr( ASM_BOOKE_WDOG_VECTOR));
|
||||
MTIVOR( 13, ppc_get_vector_addr( ASM_BOOKE_ITLBMISS_VECTOR));
|
||||
MTIVOR( 14, ppc_get_vector_addr( ASM_BOOKE_DTLBMISS_VECTOR));
|
||||
MTIVOR( 15, ppc_get_vector_addr( ASM_TRACE_VECTOR));
|
||||
MTIVOR( 32, ppc_get_vector_addr( ASM_E200_SPE_UNAVAILABLE_VECTOR));
|
||||
MTIVOR( 33, ppc_get_vector_addr( ASM_E200_SPE_DATA_VECTOR));
|
||||
MTIVOR( 34, ppc_get_vector_addr( ASM_E200_SPE_ROUND_VECTOR));
|
||||
}
|
||||
@@ -1,569 +0,0 @@
|
||||
/*
|
||||
* raw_exception.c - This file contains implementation of C function to
|
||||
* Instantiate 60x ppc primary exception entries.
|
||||
* More detailed information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC750
|
||||
* Risc Microporcessor User's Manual
|
||||
* Motorola REF : MPC750UM/AD 8/97
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
|
||||
* to support 603, 603e, 604, 604e exceptions
|
||||
*
|
||||
* moved to "libcpu/powerpc/new-exceptions and consolidated
|
||||
* by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
|
||||
* to be common for all PPCs with new excpetions
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <rtems.h>
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/powerpc.h>
|
||||
#include <rtems/score/isr.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <libcpu/raw_exception.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* DO NOT INTRODUCE #ifdef <cpu_flavor> in this file */
|
||||
|
||||
/* enum ppc_raw_exception_category should fit into this type;
|
||||
* we are setting up arrays of these for all known CPUs
|
||||
* hence the attempt to save a few bytes.
|
||||
*/
|
||||
typedef uint8_t cat_ini_t;
|
||||
|
||||
static rtems_raw_except_connect_data* raw_except_table;
|
||||
static rtems_raw_except_connect_data default_raw_except_entry;
|
||||
static rtems_raw_except_global_settings* local_settings;
|
||||
|
||||
void * codemove(void *, const void *, unsigned int, unsigned long);
|
||||
|
||||
bool bsp_exceptions_in_RAM = true;
|
||||
|
||||
/* DEPRECATED VARIABLE; we need this to support
|
||||
* libbsp/powerpc/shared/vectors/vectors.S;
|
||||
* new BSPs should NOT use this.
|
||||
*/
|
||||
uint32_t bsp_raw_vector_is_405_critical = 0;
|
||||
|
||||
uint32_t ppc_exc_vector_base = 0;
|
||||
|
||||
void* ppc_get_vector_addr(rtems_vector vector)
|
||||
{
|
||||
unsigned vaddr;
|
||||
|
||||
vaddr = ((unsigned)vector) << 8;
|
||||
|
||||
switch(vector) {
|
||||
/*
|
||||
* some vectors are located at odd addresses and only available
|
||||
* on some CPU derivates. this construct will handle them
|
||||
* if available
|
||||
*/
|
||||
/* Special case; altivec unavailable doesn't fit :-( */
|
||||
case ASM_60X_VEC_VECTOR:
|
||||
#ifndef ASM_60X_VEC_VECTOR_OFFSET
|
||||
#define ASM_60X_VEC_VECTOR_OFFSET 0xf20
|
||||
#endif
|
||||
if ( ppc_cpu_has_altivec() )
|
||||
vaddr = ASM_60X_VEC_VECTOR_OFFSET;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( PPC_405 == current_ppc_cpu ) {
|
||||
switch ( vector ) {
|
||||
case ASM_BOOKE_FIT_VECTOR:
|
||||
#ifndef ASM_PPC405_FIT_VECTOR_OFFSET
|
||||
#define ASM_PPC405_FIT_VECTOR_OFFSET 0x1010
|
||||
#endif
|
||||
vaddr = ASM_PPC405_FIT_VECTOR_OFFSET;
|
||||
break;
|
||||
case ASM_BOOKE_WDOG_VECTOR:
|
||||
#ifndef ASM_PPC405_WDOG_VECTOR_OFFSET
|
||||
#define ASM_PPC405_WDOG_VECTOR_OFFSET 0x1020
|
||||
#endif
|
||||
vaddr = ASM_PPC405_WDOG_VECTOR_OFFSET;
|
||||
break;
|
||||
case ASM_TRACE_VECTOR:
|
||||
#ifndef ASM_PPC405_TRACE_VECTOR_OFFSET
|
||||
#define ASM_PPC405_TRACE_VECTOR_OFFSET 0x2000
|
||||
#endif
|
||||
vaddr = ASM_PPC405_TRACE_VECTOR_OFFSET;
|
||||
break;
|
||||
case ASM_PPC405_APU_UNAVAIL_VECTOR:
|
||||
vaddr = ASM_60X_VEC_VECTOR_OFFSET;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bsp_exceptions_in_RAM) {
|
||||
if (ppc_cpu_has_ivpr_and_ivor()) {
|
||||
return ((void*) ((vaddr >> 4) + ppc_exc_vector_base));
|
||||
} else {
|
||||
return ((void*) (vaddr + ppc_exc_vector_base));
|
||||
}
|
||||
}
|
||||
|
||||
return ((void*) (vaddr + 0xfff00000));
|
||||
}
|
||||
|
||||
static const cat_ini_t mpc_860_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_RESET_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_FLOATASSIST_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_8XX_SOFTEMUL_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_ITLBMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_DTLBMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_ITLBERROR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_DTLBERROR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_8XX_DBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_IBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_PERIFBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_8XX_DEVPORT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
};
|
||||
|
||||
|
||||
static const cat_ini_t mpc_5xx_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_RESET_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_5XX_FLOATASSIST_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_5XX_SOFTEMUL_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_5XX_IPROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_5XX_DPROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_5XX_DBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_5XX_IBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_5XX_MEBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_5XX_NMEBREAK_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
};
|
||||
|
||||
static const cat_ini_t ppc_405_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_BOOKE_CRIT_VECTOR ] = PPC_EXC_405_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_405_CRITICAL,
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_PPC405_APU_UNAVAIL_VECTOR] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
|
||||
|
||||
[ ASM_BOOKE_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, /* PIT */
|
||||
[ ASM_BOOKE_FIT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, /* FIT */
|
||||
[ ASM_BOOKE_WDOG_VECTOR ] = PPC_EXC_405_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_DTLBMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_BOOKE_ITLBMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_405_CRITICAL,
|
||||
};
|
||||
|
||||
|
||||
#define PPC_BASIC_VECS \
|
||||
[ ASM_RESET_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, \
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, \
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_CLASSIC, \
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_CLASSIC
|
||||
|
||||
static ppc_raw_exception_category altivec_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
if ( ppc_cpu_has_altivec() ) {
|
||||
switch(vector) {
|
||||
case ASM_60X_VEC_VECTOR:
|
||||
case ASM_60X_VEC_ASSIST_VECTOR:
|
||||
return PPC_EXC_CLASSIC;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PPC_EXC_INVALID;
|
||||
}
|
||||
|
||||
static const cat_ini_t mpc_750_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
PPC_BASIC_VECS,
|
||||
[ ASM_60X_SYSMGMT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_60X_ADDR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ITM_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
};
|
||||
|
||||
static const cat_ini_t psim_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_RESET_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_PERFMON_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_60X_SYSMGMT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_60X_IMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_DLMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_DSMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ADDR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ITM_VECTOR ] = PPC_EXC_INVALID,
|
||||
};
|
||||
|
||||
static const cat_ini_t mpc_603_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
PPC_BASIC_VECS,
|
||||
[ ASM_60X_PERFMON_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_60X_SYSMGMT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_60X_IMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_DLMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_DSMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ADDR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ITM_VECTOR ] = PPC_EXC_INVALID,
|
||||
};
|
||||
|
||||
static const cat_ini_t mpc_604_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
PPC_BASIC_VECS,
|
||||
[ ASM_60X_PERFMON_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_IMISS_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_60X_DLMISS_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_60X_DSMISS_VECTOR ] = PPC_EXC_INVALID,
|
||||
[ ASM_60X_SYSMGMT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_60X_ADDR_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_ITM_VECTOR ] = PPC_EXC_INVALID,
|
||||
};
|
||||
|
||||
static const cat_ini_t e200_vector_categories [LAST_VALID_EXC + 1] = {
|
||||
[ASM_MACH_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ASM_PROT_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_ISI_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ASM_BOOKE_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_BOOKE_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
|
||||
/* FIXME: Depending on HDI0[DAPUEN] this is a critical or debug exception */
|
||||
[ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_BOOKE_CRITICAL,
|
||||
|
||||
[ASM_E200_SPE_UNAVAILABLE_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E200_SPE_DATA_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E200_SPE_ROUND_VECTOR] = PPC_EXC_CLASSIC,
|
||||
};
|
||||
|
||||
static const cat_ini_t e300_vector_categories [LAST_VALID_EXC + 1] = {
|
||||
PPC_BASIC_VECS,
|
||||
[ASM_E300_CRIT_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ASM_E300_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E300_IMISS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E300_DLMISS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E300_DSMISS_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E300_ADDR_VECTOR] = PPC_EXC_CLASSIC,
|
||||
[ASM_E300_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
};
|
||||
|
||||
static const cat_ini_t e500_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_MACH_VECTOR ] = PPC_EXC_E500_MACHCHK,
|
||||
|
||||
[ ASM_BOOKE_CRIT_VECTOR ] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_WDOG_VECTOR ] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
|
||||
[ ASM_TRACE_VECTOR ] = PPC_EXC_BOOKE_CRITICAL,
|
||||
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_FIT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ALIGN_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_PROG_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_FLOAT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_SYS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ /* APU unavailable */ 0x0b ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ ASM_60X_DLMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_DSMISS_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_VEC_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_60X_PERFMON_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
|
||||
[ /* emb FP data */ 0x15 ] = PPC_EXC_CLASSIC,
|
||||
[ /* emb FP round */ 0x16 ] = PPC_EXC_CLASSIC,
|
||||
};
|
||||
|
||||
ppc_raw_exception_category ppc_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
ppc_raw_exception_category rval = PPC_EXC_INVALID;
|
||||
|
||||
if ( vector > LAST_VALID_EXC )
|
||||
return PPC_EXC_INVALID;
|
||||
|
||||
switch (current_ppc_cpu) {
|
||||
case PPC_7400:
|
||||
if ( ( rval = altivec_vector_is_valid(vector)) )
|
||||
return rval;
|
||||
/* else fall thru */
|
||||
case PPC_750:
|
||||
rval = mpc_750_vector_categories[vector];
|
||||
break;
|
||||
case PPC_7455: /* Kate Feng */
|
||||
case PPC_7457:
|
||||
if ( ( rval = altivec_vector_is_valid(vector) ) )
|
||||
return rval;
|
||||
/* else fall thru */
|
||||
case PPC_604:
|
||||
case PPC_604e:
|
||||
case PPC_604r:
|
||||
rval = mpc_604_vector_categories[vector];
|
||||
break;
|
||||
case PPC_603:
|
||||
case PPC_603e:
|
||||
case PPC_603le:
|
||||
case PPC_603ev:
|
||||
case PPC_8260:
|
||||
/* case PPC_8240: -- same value as 8260 */
|
||||
case PPC_8245:
|
||||
rval = mpc_603_vector_categories[vector];
|
||||
break;
|
||||
case PPC_e300c1:
|
||||
case PPC_e300c2:
|
||||
case PPC_e300c3:
|
||||
rval = e300_vector_categories[vector];
|
||||
break;
|
||||
case PPC_PSIM:
|
||||
rval = psim_vector_categories[vector];
|
||||
break;
|
||||
case PPC_8540:
|
||||
rval = e500_vector_categories[vector];
|
||||
break;
|
||||
case PPC_e200z6:
|
||||
rval = e200_vector_categories[vector];
|
||||
break;
|
||||
case PPC_5XX:
|
||||
rval = mpc_5xx_vector_categories[vector];
|
||||
break;
|
||||
case PPC_860:
|
||||
rval = mpc_860_vector_categories[vector];
|
||||
break;
|
||||
case PPC_405:
|
||||
case PPC_405GP:
|
||||
case PPC_405EX:
|
||||
rval = ppc_405_vector_categories[vector];
|
||||
break;
|
||||
default:
|
||||
printk("Please complete "
|
||||
"libcpu/powerpc/new-exceptions/raw_exception.c\n"
|
||||
"current_ppc_cpu = %x\n", current_ppc_cpu);
|
||||
return PPC_EXC_INVALID;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
int ppc_set_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level k;
|
||||
|
||||
if ( PPC_EXC_INVALID == ppc_vector_is_valid(except->hdl.vector) ) {
|
||||
printk("ppc_set_exception: vector %d is not valid\n",
|
||||
except->hdl.vector);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if default handler is actually connected. If not issue an error.
|
||||
* You must first get the current handler via mpc60x_get_current_exception
|
||||
* and then disconnect it using mpc60x_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
|
||||
if (memcmp(ppc_get_vector_addr(except->hdl.vector),
|
||||
(void*)default_raw_except_entry.hdl.raw_hdl,
|
||||
default_raw_except_entry.hdl.raw_hdl_size)) {
|
||||
printk("ppc_set_exception: raw vector not installed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_interrupt_disable(k);
|
||||
|
||||
raw_except_table [except->exceptIndex] = *except;
|
||||
codemove(ppc_get_vector_addr(except->hdl.vector),
|
||||
except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
if (except->on)
|
||||
except->on(except);
|
||||
|
||||
rtems_interrupt_enable(k);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ppc_get_current_exception (rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level k;
|
||||
int i;
|
||||
|
||||
if ( PPC_EXC_INVALID == ppc_vector_is_valid(except->hdl.vector) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0; i < local_settings->exceptSize; i++) {
|
||||
if ( raw_except_table[i].hdl.vector == except->hdl.vector ) {
|
||||
rtems_interrupt_disable(k);
|
||||
if ( raw_except_table[i].hdl.vector == except->hdl.vector ) {
|
||||
*except = raw_except_table[i];
|
||||
rtems_interrupt_enable(k);
|
||||
return 1;
|
||||
}
|
||||
rtems_interrupt_enable(k);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ppc_delete_exception (const rtems_raw_except_connect_data* except)
|
||||
{
|
||||
rtems_interrupt_level k;
|
||||
|
||||
if ( PPC_EXC_INVALID == ppc_vector_is_valid(except->hdl.vector) ) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check if handler passed is actually connected. If not issue an error.
|
||||
* You must first get the current handler via ppc_get_current_exception
|
||||
* and then disconnect it using ppc_delete_exception.
|
||||
* RATIONALE : to always have the same transition by forcing the user
|
||||
* to get the previous handler before accepting to disconnect.
|
||||
*/
|
||||
if (memcmp(ppc_get_vector_addr(except->hdl.vector),
|
||||
(void*)except->hdl.raw_hdl,
|
||||
except->hdl.raw_hdl_size)) {
|
||||
return 0;
|
||||
}
|
||||
rtems_interrupt_disable(k);
|
||||
|
||||
if (except->off)
|
||||
except->off(except);
|
||||
codemove(ppc_get_vector_addr(except->hdl.vector),
|
||||
default_raw_except_entry.hdl.raw_hdl,
|
||||
default_raw_except_entry.hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
|
||||
|
||||
raw_except_table[except->exceptIndex] = default_raw_except_entry;
|
||||
raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
|
||||
raw_except_table[except->exceptIndex].hdl.vector = except->hdl.vector;
|
||||
|
||||
rtems_interrupt_enable(k);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
int ppc_init_exceptions (rtems_raw_except_global_settings* config)
|
||||
{
|
||||
rtems_interrupt_level k;
|
||||
int i;
|
||||
unsigned c;
|
||||
|
||||
/*
|
||||
* store various accelerators
|
||||
*/
|
||||
raw_except_table = config->rawExceptHdlTbl;
|
||||
local_settings = config;
|
||||
default_raw_except_entry = config->defaultRawEntry;
|
||||
|
||||
rtems_interrupt_disable(k);
|
||||
|
||||
/* FIXME special case selection method */
|
||||
if (current_ppc_cpu == PPC_e200z6) {
|
||||
e200_setup_raw_exceptions();
|
||||
} else if ( (c = ppc_cpu_is_bookE()) && PPC_BOOKE_405 != c ) {
|
||||
e500_setup_raw_exceptions();
|
||||
}
|
||||
|
||||
/* Need to support libbsp/powerpc/shared/vectors.S
|
||||
* (hopefully this can go away some day)
|
||||
* We also rely on LAST_VALID_EXC < 32
|
||||
*/
|
||||
for ( i=0; i <= LAST_VALID_EXC; i++ ) {
|
||||
if ( PPC_EXC_405_CRITICAL == (ppc_vector_is_valid( i ) & ~PPC_EXC_ASYNC) )
|
||||
bsp_raw_vector_is_405_critical |= (1<<i);
|
||||
}
|
||||
|
||||
for (i=0; i < config->exceptSize; i++) {
|
||||
if ( PPC_EXC_INVALID == ppc_vector_is_valid(raw_except_table[i].hdl.vector) ) {
|
||||
continue;
|
||||
}
|
||||
codemove(ppc_get_vector_addr(raw_except_table[i].hdl.vector),
|
||||
raw_except_table[i].hdl.raw_hdl,
|
||||
raw_except_table[i].hdl.raw_hdl_size,
|
||||
PPC_CACHE_ALIGNMENT);
|
||||
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
|
||||
if (raw_except_table[i].on)
|
||||
raw_except_table[i].on(&raw_except_table[i]);
|
||||
}
|
||||
else {
|
||||
if (raw_except_table[i].off)
|
||||
raw_except_table[i].off(&raw_except_table[i]);
|
||||
}
|
||||
}
|
||||
rtems_interrupt_enable(k);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ppc_get_exception_config (rtems_raw_except_global_settings** config)
|
||||
{
|
||||
*config = local_settings;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* raw_execption.h
|
||||
*
|
||||
* This file contains implementation of C function to
|
||||
* Instantiate 60x ppc primary exception entries.
|
||||
* More detailed information can be found on motorola
|
||||
* site and more precisely in the following book :
|
||||
*
|
||||
* MPC750
|
||||
* Risc Microporcessor User's Manual
|
||||
* Mtorola REF : MPC750UM/AD 8/97
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
|
||||
* to support 603, 603e, 604, 604e exceptions
|
||||
*
|
||||
* moved to "libcpu/powerpc/new-exceptions and consolidated
|
||||
* by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
|
||||
* to be common for all PPCs with new excpetions
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _LIBCPU_RAW_EXCEPTION_H
|
||||
#define _LIBCPU_RAW_EXCEPTION_H
|
||||
|
||||
#include <rtems/powerpc/powerpc.h>
|
||||
|
||||
/* DO NOT INTRODUCE #ifdef <cpu_flavor> in this file */
|
||||
|
||||
#define ASM_RESET_VECTOR 0x01
|
||||
#define ASM_MACH_VECTOR 0x02
|
||||
#define ASM_PROT_VECTOR 0x03
|
||||
#define ASM_ISI_VECTOR 0x04
|
||||
#define ASM_EXT_VECTOR 0x05
|
||||
#define ASM_ALIGN_VECTOR 0x06
|
||||
#define ASM_PROG_VECTOR 0x07
|
||||
#define ASM_FLOAT_VECTOR 0x08
|
||||
#define ASM_DEC_VECTOR 0x09
|
||||
#define ASM_SYS_VECTOR 0x0C
|
||||
#define ASM_TRACE_VECTOR 0x0D
|
||||
|
||||
#define ASM_BOOKE_CRIT_VECTOR 0x01
|
||||
/* We could use the std. decrementer vector # on bookE, too,
|
||||
* but the bookE decrementer has slightly different semantics
|
||||
* so we use a different vector (which happens to be
|
||||
* the PIT vector on the 405 which is like the booke decrementer)
|
||||
*/
|
||||
#define ASM_BOOKE_DEC_VECTOR 0x10
|
||||
#define ASM_BOOKE_ITLBMISS_VECTOR 0x11
|
||||
#define ASM_BOOKE_DTLBMISS_VECTOR 0x12
|
||||
#define ASM_BOOKE_FIT_VECTOR 0x13
|
||||
#define ASM_BOOKE_WDOG_VECTOR 0x14
|
||||
|
||||
#define ASM_PPC405_APU_UNAVAIL_VECTOR ASM_60X_VEC_ASSIST_VECTOR
|
||||
|
||||
#define ASM_8XX_FLOATASSIST_VECTOR 0x0E
|
||||
#define ASM_8XX_SOFTEMUL_VECTOR 0x10
|
||||
#define ASM_8XX_ITLBMISS_VECTOR 0x11
|
||||
#define ASM_8XX_DTLBMISS_VECTOR 0x12
|
||||
#define ASM_8XX_ITLBERROR_VECTOR 0x13
|
||||
#define ASM_8XX_DTLBERROR_VECTOR 0x14
|
||||
#define ASM_8XX_DBREAK_VECTOR 0x1C
|
||||
#define ASM_8XX_IBREAK_VECTOR 0x1D
|
||||
#define ASM_8XX_PERIFBREAK_VECTOR 0x1E
|
||||
#define ASM_8XX_DEVPORT_VECTOR 0x1F
|
||||
|
||||
#define ASM_5XX_FLOATASSIST_VECTOR 0x0E
|
||||
#define ASM_5XX_SOFTEMUL_VECTOR 0x10
|
||||
#define ASM_5XX_IPROT_VECTOR 0x13
|
||||
#define ASM_5XX_DPROT_VECTOR 0x14
|
||||
#define ASM_5XX_DBREAK_VECTOR 0x1C
|
||||
#define ASM_5XX_IBREAK_VECTOR 0x1D
|
||||
#define ASM_5XX_MEBREAK_VECTOR 0x1E
|
||||
#define ASM_5XX_NMEBREAK_VECTOR 0x1F
|
||||
|
||||
|
||||
#define ASM_60X_VEC_VECTOR 0x0A
|
||||
#define ASM_60X_PERFMON_VECTOR 0x0F
|
||||
#define ASM_60X_IMISS_VECTOR 0x10
|
||||
#define ASM_60X_DLMISS_VECTOR 0x11
|
||||
#define ASM_60X_DSMISS_VECTOR 0x12
|
||||
#define ASM_60X_ADDR_VECTOR 0x13
|
||||
#define ASM_60X_SYSMGMT_VECTOR 0x14
|
||||
#define ASM_60X_VEC_ASSIST_VECTOR 0x16
|
||||
#define ASM_60X_ITM_VECTOR 0x17
|
||||
|
||||
/* e200 */
|
||||
#define ASM_E200_SPE_UNAVAILABLE_VECTOR 0x15
|
||||
#define ASM_E200_SPE_DATA_VECTOR 0x16
|
||||
#define ASM_E200_SPE_ROUND_VECTOR 0x17
|
||||
|
||||
/* e300 */
|
||||
#define ASM_E300_CRIT_VECTOR 0x0A
|
||||
#define ASM_E300_PERFMON_VECTOR 0x0F
|
||||
#define ASM_E300_IMISS_VECTOR ASM_60X_IMISS_VECTOR /* Special case: Shadowed GPRs */
|
||||
#define ASM_E300_DLMISS_VECTOR ASM_60X_DLMISS_VECTOR /* Special case: Shadowed GPRs */
|
||||
#define ASM_E300_DSMISS_VECTOR ASM_60X_DSMISS_VECTOR /* Special case: Shadowed GPRs */
|
||||
#define ASM_E300_ADDR_VECTOR 0x13
|
||||
#define ASM_E300_SYSMGMT_VECTOR 0x14
|
||||
|
||||
/*
|
||||
* If you change that number make sure to adjust the wrapper code in ppc_exc.S
|
||||
* and that ppc_exc_handler_table will be correctly initialized.
|
||||
*/
|
||||
#define LAST_VALID_EXC 0x1F
|
||||
|
||||
/* DO NOT USE -- this symbol is DEPRECATED
|
||||
* (only used by libbsp/shared/vectors/vectors.S
|
||||
* which should not be used by new BSPs).
|
||||
*/
|
||||
#define ASM_60X_VEC_VECTOR_OFFSET 0xf20
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
/*
|
||||
* Type definition for raw exceptions.
|
||||
*/
|
||||
|
||||
typedef unsigned char rtems_vector;
|
||||
struct __rtems_raw_except_connect_data__;
|
||||
typedef void (*rtems_raw_except_func) (void);
|
||||
typedef unsigned long rtems_raw_except_hdl_size;
|
||||
|
||||
typedef struct {
|
||||
rtems_vector vector;
|
||||
rtems_raw_except_func raw_hdl;
|
||||
rtems_raw_except_hdl_size raw_hdl_size;
|
||||
}rtems_raw_except_hdl;
|
||||
|
||||
typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef void (*rtems_raw_except_disable) (const struct __rtems_raw_except_connect_data__*);
|
||||
typedef int (*rtems_raw_except_is_enabled) (const struct __rtems_raw_except_connect_data__*);
|
||||
|
||||
typedef struct __rtems_raw_except_connect_data__{
|
||||
/*
|
||||
* Exception vector (As defined in the manual)
|
||||
*/
|
||||
rtems_vector exceptIndex;
|
||||
/*
|
||||
* Exception raw handler. See comment on handler properties below in function prototype.
|
||||
*/
|
||||
rtems_raw_except_hdl hdl;
|
||||
/*
|
||||
* function for enabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must enable the except at processor level only.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_enable on;
|
||||
/*
|
||||
* function for disabling raw exceptions. In order to be consistent
|
||||
* with the fact that the raw connexion can defined in the
|
||||
* libcpu library, this library should have no knowledge of
|
||||
* board specific hardware to manage exceptions and thus the
|
||||
* "on" routine must disable the except both at device and PIC level.
|
||||
*
|
||||
*/
|
||||
rtems_raw_except_disable off;
|
||||
/*
|
||||
* function enabling to know what exception may currently occur
|
||||
*/
|
||||
rtems_raw_except_is_enabled isOn;
|
||||
}rtems_raw_except_connect_data;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* size of all the table fields (*Tbl) described below.
|
||||
*/
|
||||
unsigned int exceptSize;
|
||||
/*
|
||||
* Default handler used when disconnecting exceptions.
|
||||
*/
|
||||
rtems_raw_except_connect_data defaultRawEntry;
|
||||
/*
|
||||
* Table containing initials/current value.
|
||||
*/
|
||||
rtems_raw_except_connect_data* rawExceptHdlTbl;
|
||||
}rtems_raw_except_global_settings;
|
||||
|
||||
/*
|
||||
* Exceptions of different categories use different SRR registers
|
||||
* to save machine state (:-()
|
||||
*
|
||||
* For now, the CPU descriptions assume this fits into 8 bits.
|
||||
*/
|
||||
typedef enum {
|
||||
PPC_EXC_INVALID = 0,
|
||||
PPC_EXC_CLASSIC = 1,
|
||||
PPC_EXC_405_CRITICAL = 2,
|
||||
PPC_EXC_BOOKE_CRITICAL = 3,
|
||||
PPC_EXC_E500_MACHCHK = 4,
|
||||
PPC_EXC_ASYNC = 0x80,
|
||||
} ppc_raw_exception_category;
|
||||
|
||||
/*
|
||||
* C callable function enabling to set up one raw idt entry
|
||||
*/
|
||||
extern int ppc_set_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to get one current raw idt entry
|
||||
*/
|
||||
extern int ppc_get_current_exception (rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to remove one current raw idt entry
|
||||
*/
|
||||
extern int ppc_delete_exception (const rtems_raw_except_connect_data*);
|
||||
|
||||
/*
|
||||
* C callable function enabling to check if vector is valid
|
||||
* and returns category.
|
||||
*/
|
||||
extern ppc_raw_exception_category ppc_vector_is_valid(rtems_vector vector);
|
||||
|
||||
/*
|
||||
* Exception global init.
|
||||
*/
|
||||
extern int ppc_init_exceptions (rtems_raw_except_global_settings* config);
|
||||
extern int ppc_get_exception_config (rtems_raw_except_global_settings** config);
|
||||
|
||||
void* ppc_get_vector_addr(rtems_vector vector);
|
||||
|
||||
int ppc_is_e500();
|
||||
void e200_setup_raw_exceptions(void);
|
||||
void e500_setup_raw_exceptions(void);
|
||||
|
||||
/* This variable is initialized to 'TRUE' by default;
|
||||
* BSPs which have their vectors in ROM should set it
|
||||
* to FALSE prior to initializing raw exceptions.
|
||||
*
|
||||
* I suspect the only candidate is the simulator.
|
||||
* After all, the value of this variable is used to
|
||||
* determine where to install the prologue code and
|
||||
* installing to ROM on anyting that's real ROM
|
||||
* will fail anyways.
|
||||
*
|
||||
* This should probably go away... (T.S. 2007/11/30)
|
||||
*/
|
||||
extern bool bsp_exceptions_in_RAM;
|
||||
|
||||
/**
|
||||
* @brief Vector base address for CPUs (for example e200 and e500) with IVPR
|
||||
* and IVOR registers.
|
||||
*/
|
||||
extern uint32_t ppc_exc_vector_base;
|
||||
|
||||
# endif /* ASM */
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user