diff options
Diffstat (limited to 'bsps/powerpc/shared/exceptions/ppc_exc_hdl.c')
-rw-r--r-- | bsps/powerpc/shared/exceptions/ppc_exc_hdl.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/bsps/powerpc/shared/exceptions/ppc_exc_hdl.c b/bsps/powerpc/shared/exceptions/ppc_exc_hdl.c new file mode 100644 index 0000000000..ce1f326438 --- /dev/null +++ b/bsps/powerpc/shared/exceptions/ppc_exc_hdl.c @@ -0,0 +1,116 @@ +/* PowerPC exception handling middleware; consult README for more + * information. + * + * Author: Till Straumann <strauman@slac.stanford.edu>, 2007 + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/vectors.h> + +#include <rtems/score/threaddispatch.h> + +/* Provide temp. storage space for a few registers. + * This is used by the assembly code prior to setting up + * the stack. + * One set is needed for each exception type with its + * own SRR0/SRR1 pair since such exceptions may nest. + * + * NOTE: The assembly code needs these variables to + * be in the .sdata section and accesses them + * via R13. + */ +uint32_t ppc_exc_lock_std = 0; +uint32_t ppc_exc_lock_crit = 0; +uint32_t ppc_exc_lock_mchk = 0; + +uint32_t ppc_exc_vector_register_std = 0; +uint32_t ppc_exc_vector_register_crit = 0; +uint32_t ppc_exc_vector_register_mchk = 0; + +#ifndef PPC_EXC_CONFIG_BOOKE_ONLY + +/* MSR bits to enable once critical status info is saved and the stack + * is switched; must be set depending on CPU type + * + * Default is set here for classic PPC CPUs with a MMU + * but is overridden from vectors_init.c + */ +uint32_t ppc_exc_msr_bits = MSR_IR | MSR_DR | MSR_RI; + +#endif /* PPC_EXC_CONFIG_BOOKE_ONLY */ + +int ppc_exc_handler_default(BSP_Exception_frame *f, unsigned int vector) +{ + return -1; +} + +#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER + +exception_handler_t globalExceptHdl = C_exception_handler; + +/* Table of C-handlers */ +ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1] = { + [0 ... LAST_VALID_EXC] = ppc_exc_handler_default +}; + +#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */ + +ppc_exc_handler_t ppc_exc_get_handler(unsigned vector) +{ + if ( + vector <= LAST_VALID_EXC + && ppc_exc_handler_table [vector] != ppc_exc_handler_default + ) { + return ppc_exc_handler_table [vector]; + } else { + return NULL; + } +} + +rtems_status_code ppc_exc_set_handler(unsigned vector, ppc_exc_handler_t handler) +{ + if (vector <= LAST_VALID_EXC) { + if (handler == NULL) { + handler = ppc_exc_handler_default; + } + + if (ppc_exc_handler_table [vector] != handler) { +#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER + ppc_exc_handler_table [vector] = handler; +#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */ + return RTEMS_RESOURCE_IN_USE; +#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */ + } + + return RTEMS_SUCCESSFUL; + } else { + return RTEMS_INVALID_ID; + } +} + +void ppc_exc_wrapup(BSP_Exception_frame *frame) +{ + Per_CPU_Control *cpu_self; + + cpu_self = _Per_CPU_Get(); + + if (cpu_self->isr_dispatch_disable) { + return; + } + + while (cpu_self->dispatch_necessary) { + rtems_interrupt_level level; + + cpu_self->isr_dispatch_disable = 1; + cpu_self->thread_dispatch_disable_level = 1; + _Thread_Do_dispatch(cpu_self, frame->EXC_SRR1); + rtems_interrupt_local_disable(level); + (void) level; + cpu_self = _Per_CPU_Get(); + } + + cpu_self->isr_dispatch_disable = 0; +} |