remove depratated powerpc exception API

This commit is contained in:
Thomas Doerfler
2009-10-30 13:52:34 +00:00
parent 5075ec98c7
commit f7ac681b51
32 changed files with 29 additions and 5669 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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.

View 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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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");
}
}

View File

@@ -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.

View 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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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(); */
}

View File

@@ -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

View File

@@ -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...
*/
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 */
}
}

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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