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:
Sebastian Huber
2012-11-23 09:32:52 +01:00
parent 4263155e96
commit 4bd4c9e1f9
7 changed files with 150 additions and 24 deletions

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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