forked from Imagelibrary/rtems
bsps/powerpc: Add PPC_EXC_CONFIG_USE_FIXED_HANDLER
In case a BSP enables this option, then fixed high level exception handler will be used. For normal asynchronous exceptions this is bsp_interrupt_dispatch() and for other exceptions this is the handler from the read-only ppc_exc_handler_table. The global handler is C_exception_handler(). This avoids some dependencies on valid read-write data.
This commit is contained in:
61
c/src/lib/libbsp/powerpc/shared/src/ppc-exc-handler-table.c
Normal file
61
c/src/lib/libbsp/powerpc/shared/src/ppc-exc-handler-table.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||||
|
*
|
||||||
|
* embedded brains GmbH
|
||||||
|
* Obere Lagerstr. 30
|
||||||
|
* 82178 Puchheim
|
||||||
|
* Germany
|
||||||
|
* <rtems@embedded-brains.de>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bsp/vectors.h>
|
||||||
|
|
||||||
|
#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
|
|
||||||
|
static int ppc_exc_interrupt_dispatch(BSP_Exception_frame *f, unsigned vector)
|
||||||
|
{
|
||||||
|
bsp_interrupt_dispatch();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1] = {
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_interrupt_dispatch,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default,
|
||||||
|
ppc_exc_handler_default
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Modified and partially rewritten by Till Straumann, 2007-2008
|
* Modified and partially rewritten by Till Straumann, 2007-2008
|
||||||
*
|
*
|
||||||
* Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008.
|
* Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008-2012.
|
||||||
*
|
*
|
||||||
* Low-level assembly code for PPC exceptions (macros).
|
* Low-level assembly code for PPC exceptions (macros).
|
||||||
*
|
*
|
||||||
@@ -825,6 +825,8 @@ wrap_call_global_handler_\_FLVR:
|
|||||||
/* First parameter = exception frame pointer + FRAME_LINK_SPACE */
|
/* First parameter = exception frame pointer + FRAME_LINK_SPACE */
|
||||||
addi r3, FRAME_REGISTER, FRAME_LINK_SPACE
|
addi r3, FRAME_REGISTER, FRAME_LINK_SPACE
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
|
|
||||||
/* Load global handler address */
|
/* Load global handler address */
|
||||||
LW SCRATCH_REGISTER_0, globalExceptHdl
|
LW SCRATCH_REGISTER_0, globalExceptHdl
|
||||||
|
|
||||||
@@ -836,6 +838,13 @@ wrap_call_global_handler_\_FLVR:
|
|||||||
mtctr SCRATCH_REGISTER_0
|
mtctr SCRATCH_REGISTER_0
|
||||||
bctrl
|
bctrl
|
||||||
|
|
||||||
|
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
|
/* Call fixed global handler */
|
||||||
|
bl C_exception_handler
|
||||||
|
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
b wrap_handler_done_\_FLVR
|
b wrap_handler_done_\_FLVR
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 embedded brains GmbH. All rights reserved.
|
* Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved.
|
||||||
*
|
*
|
||||||
* embedded brains GmbH
|
* embedded brains GmbH
|
||||||
* Obere Lagerstr. 30
|
* Obere Lagerstr. 30
|
||||||
@@ -46,14 +46,21 @@
|
|||||||
*/
|
*/
|
||||||
#define FRAME_OFFSET(reg) GPR2_OFFSET(reg)
|
#define FRAME_OFFSET(reg) GPR2_OFFSET(reg)
|
||||||
|
|
||||||
|
#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
|
.global bsp_interrupt_dispatch
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
.global ppc_exc_min_prolog_async_tmpl_normal
|
.global ppc_exc_min_prolog_async_tmpl_normal
|
||||||
.global ppc_exc_wrap_async_normal
|
.global ppc_exc_wrap_async_normal
|
||||||
|
|
||||||
ppc_exc_min_prolog_async_tmpl_normal:
|
ppc_exc_min_prolog_async_tmpl_normal:
|
||||||
|
|
||||||
stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1)
|
stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1)
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
stw VECTOR_REGISTER, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1)
|
stw VECTOR_REGISTER, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1)
|
||||||
li VECTOR_REGISTER, 0xffff8000
|
li VECTOR_REGISTER, 0xffff8000
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We store the absolute branch target address here. It will be used
|
* We store the absolute branch target address here. It will be used
|
||||||
@@ -87,6 +94,7 @@ ppc_exc_wrap_async_normal:
|
|||||||
|
|
||||||
PPC_GPR_STORE SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
|
PPC_GPR_STORE SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
#ifdef __SPE__
|
#ifdef __SPE__
|
||||||
/*
|
/*
|
||||||
* Save high order part of VECTOR_REGISTER here. The low order part
|
* Save high order part of VECTOR_REGISTER here. The low order part
|
||||||
@@ -95,9 +103,14 @@ ppc_exc_wrap_async_normal:
|
|||||||
evmergehi SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, VECTOR_REGISTER
|
evmergehi SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, VECTOR_REGISTER
|
||||||
stw SCRATCH_0_REGISTER, VECTOR_OFFSET(r1)
|
stw SCRATCH_0_REGISTER, VECTOR_OFFSET(r1)
|
||||||
#endif
|
#endif
|
||||||
|
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
/* The vector register has no special purpose in this case */
|
||||||
|
PPC_GPR_STORE VECTOR_REGISTER, VECTOR_OFFSET(r1)
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
PPC_GPR_STORE HANDLER_REGISTER, HANDLER_OFFSET(r1)
|
PPC_GPR_STORE HANDLER_REGISTER, HANDLER_OFFSET(r1)
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
/*
|
/*
|
||||||
* Load the handler address. Get the handler table index from the
|
* Load the handler address. Get the handler table index from the
|
||||||
* vector number. We have to discard the exception type. Take only
|
* vector number. We have to discard the exception type. Take only
|
||||||
@@ -108,6 +121,7 @@ ppc_exc_wrap_async_normal:
|
|||||||
lis HANDLER_REGISTER, ppc_exc_handler_table@h
|
lis HANDLER_REGISTER, ppc_exc_handler_table@h
|
||||||
ori HANDLER_REGISTER, HANDLER_REGISTER, ppc_exc_handler_table@l
|
ori HANDLER_REGISTER, HANDLER_REGISTER, ppc_exc_handler_table@l
|
||||||
lwzx HANDLER_REGISTER, HANDLER_REGISTER, SCRATCH_0_REGISTER
|
lwzx HANDLER_REGISTER, HANDLER_REGISTER, SCRATCH_0_REGISTER
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
PPC_GPR_STORE SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
|
PPC_GPR_STORE SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
|
||||||
PPC_GPR_STORE SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
|
PPC_GPR_STORE SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
|
||||||
@@ -149,6 +163,7 @@ ppc_exc_wrap_async_normal:
|
|||||||
mfspr SCRATCH_0_REGISTER, SPRG1
|
mfspr SCRATCH_0_REGISTER, SPRG1
|
||||||
iselgt r1, r1, SCRATCH_0_REGISTER
|
iselgt r1, r1, SCRATCH_0_REGISTER
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
/*
|
/*
|
||||||
* Call high level exception handler.
|
* Call high level exception handler.
|
||||||
*
|
*
|
||||||
@@ -159,6 +174,10 @@ ppc_exc_wrap_async_normal:
|
|||||||
rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
|
rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
|
||||||
mtctr HANDLER_REGISTER
|
mtctr HANDLER_REGISTER
|
||||||
bctrl
|
bctrl
|
||||||
|
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
/* Call fixed high level handler */
|
||||||
|
bl bsp_interrupt_dispatch
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
/* Load ISR nest level and thread dispatch disable level */
|
/* Load ISR nest level and thread dispatch disable level */
|
||||||
lis ISR_NEST_HADDR_REGISTER, ISR_NEST_LEVEL@ha
|
lis ISR_NEST_HADDR_REGISTER, ISR_NEST_LEVEL@ha
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include <bsp/vectors.h>
|
#include <bsp/vectors.h>
|
||||||
|
|
||||||
exception_handler_t globalExceptHdl = C_exception_handler;
|
|
||||||
|
|
||||||
void C_exception_handler(BSP_Exception_frame *excPtr)
|
void C_exception_handler(BSP_Exception_frame *excPtr)
|
||||||
{
|
{
|
||||||
rtems_fatal(
|
rtems_fatal(
|
||||||
|
|||||||
@@ -39,16 +39,22 @@ uint32_t ppc_exc_vector_register_mchk = 0;
|
|||||||
*/
|
*/
|
||||||
uint32_t ppc_exc_msr_bits = MSR_IR | MSR_DR | MSR_RI;
|
uint32_t ppc_exc_msr_bits = MSR_IR | MSR_DR | MSR_RI;
|
||||||
|
|
||||||
static int ppc_exc_handler_default(BSP_Exception_frame *f, unsigned int vector)
|
int ppc_exc_handler_default(BSP_Exception_frame *f, unsigned int vector)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
|
|
||||||
|
exception_handler_t globalExceptHdl = C_exception_handler;
|
||||||
|
|
||||||
/* Table of C-handlers */
|
/* Table of C-handlers */
|
||||||
ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1] = {
|
ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1] = {
|
||||||
[0 ... LAST_VALID_EXC] = ppc_exc_handler_default
|
[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)
|
ppc_exc_handler_t ppc_exc_get_handler(unsigned vector)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@@ -65,9 +71,15 @@ rtems_status_code ppc_exc_set_handler(unsigned vector, ppc_exc_handler_t handler
|
|||||||
{
|
{
|
||||||
if (vector <= LAST_VALID_EXC) {
|
if (vector <= LAST_VALID_EXC) {
|
||||||
if (handler == NULL) {
|
if (handler == NULL) {
|
||||||
ppc_exc_handler_table [vector] = ppc_exc_handler_default;
|
handler = ppc_exc_handler_default;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (ppc_exc_handler_table [vector] != handler) {
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
ppc_exc_handler_table [vector] = 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;
|
return RTEMS_SUCCESSFUL;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
|
* Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 embedded brains GmbH.
|
* Copyright (C) 2009-2012 embedded brains GmbH.
|
||||||
*
|
*
|
||||||
* The license and distribution terms for this file may be
|
* The license and distribution terms for this file may be
|
||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
@@ -135,8 +135,12 @@ rtems_status_code ppc_exc_make_prologue(
|
|||||||
&& (ppc_interrupt_get_disable_mask() & MSR_CE) == 0
|
&& (ppc_interrupt_get_disable_mask() & MSR_CE) == 0
|
||||||
) {
|
) {
|
||||||
prologue_template = ppc_exc_min_prolog_async_tmpl_normal;
|
prologue_template = ppc_exc_min_prolog_async_tmpl_normal;
|
||||||
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
|
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
|
||||||
fixup_vector = true;
|
fixup_vector = true;
|
||||||
|
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
prologue_template_size = 8;
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
} else {
|
} else {
|
||||||
prologue_template = ppc_exc_prologue_templates [category];
|
prologue_template = ppc_exc_prologue_templates [category];
|
||||||
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
|
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#ifndef LIBCPU_VECTORS_H
|
#ifndef LIBCPU_VECTORS_H
|
||||||
#define LIBCPU_VECTORS_H
|
#define LIBCPU_VECTORS_H
|
||||||
|
|
||||||
|
#include <bspopts.h>
|
||||||
|
|
||||||
#include <libcpu/powerpc-utility.h>
|
#include <libcpu/powerpc-utility.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -261,11 +263,6 @@ typedef CPU_Exception_frame BSP_Exception_frame;
|
|||||||
*/
|
*/
|
||||||
typedef void (*exception_handler_t)(BSP_Exception_frame*);
|
typedef void (*exception_handler_t)(BSP_Exception_frame*);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Global exception handler.
|
|
||||||
*/
|
|
||||||
extern exception_handler_t globalExceptHdl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default global exception handler.
|
* @brief Default global exception handler.
|
||||||
*/
|
*/
|
||||||
@@ -399,16 +396,20 @@ void ppc_exc_initialize(
|
|||||||
/**
|
/**
|
||||||
* @brief High-level exception handler type.
|
* @brief High-level exception handler type.
|
||||||
*
|
*
|
||||||
* Exception handlers should return zero if the exception was handled and
|
* @retval 0 The exception was handled and normal execution may resume.
|
||||||
* normal execution may resume.
|
* @retval -1 Reject the exception resulting in a call of the global exception
|
||||||
*
|
* handler.
|
||||||
* They should return minus one to reject the exception resulting in the
|
* @retval other Reserved, do not use.
|
||||||
* globalExcHdl() being called.
|
|
||||||
*
|
|
||||||
* Other return values are reserved.
|
|
||||||
*/
|
*/
|
||||||
typedef int (*ppc_exc_handler_t)(BSP_Exception_frame *f, unsigned vector);
|
typedef int (*ppc_exc_handler_t)(BSP_Exception_frame *f, unsigned vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default high-level exception handler.
|
||||||
|
*
|
||||||
|
* @retval -1 Always.
|
||||||
|
*/
|
||||||
|
int ppc_exc_handler_default(BSP_Exception_frame *f, unsigned int vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Bits for MSR update.
|
* @brief Bits for MSR update.
|
||||||
*
|
*
|
||||||
@@ -436,10 +437,27 @@ extern uint32_t ppc_exc_msr_bits;
|
|||||||
*/
|
*/
|
||||||
extern uint32_t ppc_exc_cache_wb_check;
|
extern uint32_t ppc_exc_cache_wb_check;
|
||||||
|
|
||||||
/**
|
#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||||
|
/**
|
||||||
* @brief High-level exception handler table.
|
* @brief High-level exception handler table.
|
||||||
*/
|
*/
|
||||||
extern ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1];
|
extern ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Global exception handler.
|
||||||
|
*/
|
||||||
|
extern exception_handler_t globalExceptHdl;
|
||||||
|
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
/**
|
||||||
|
* @brief High-level exception handler table.
|
||||||
|
*/
|
||||||
|
extern const ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt dispatch routine provided by BSP.
|
||||||
|
*/
|
||||||
|
void bsp_interrupt_dispatch(void);
|
||||||
|
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set high-level exception handler.
|
* @brief Set high-level exception handler.
|
||||||
@@ -457,6 +475,11 @@ extern ppc_exc_handler_t ppc_exc_handler_table [LAST_VALID_EXC + 1];
|
|||||||
*
|
*
|
||||||
* It is legal to set a NULL handler. This leads to the globalExcHdl
|
* It is legal to set a NULL handler. This leads to the globalExcHdl
|
||||||
* being called if an exception for 'vector' occurs.
|
* being called if an exception for 'vector' occurs.
|
||||||
|
*
|
||||||
|
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||||
|
* @retval RTEMS_INVALID_ID Invalid vector number.
|
||||||
|
* @retval RTEMS_RESOURCE_IN_USE Handler table is read-only and handler does
|
||||||
|
* not match.
|
||||||
*/
|
*/
|
||||||
rtems_status_code ppc_exc_set_handler(unsigned vector, ppc_exc_handler_t hdl);
|
rtems_status_code ppc_exc_set_handler(unsigned vector, ppc_exc_handler_t hdl);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user