add new files for exception handler

This commit is contained in:
Thomas Doerfler
2009-10-23 09:51:03 +00:00
parent 402ac7b7c8
commit 856cce5068
9 changed files with 1232 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
/**
* @file
*
* @ingroup powerpc_shared
*
* @brief Code copy implementation.
*/
/*
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-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 <string.h>
#include <rtems.h>
#include <libcpu/powerpc-utility.h>
void ppc_code_copy(void *dest, const void *src, size_t n)
{
if (memcmp(dest, src, n) != 0) {
memcpy(dest, src, n);
rtems_cache_flush_multiple_data_lines(dest, n);
ppc_synchronize_data();
rtems_cache_invalidate_multiple_instruction_lines(dest, n);
ppc_synchronize_instructions();
}
}

View File

@@ -0,0 +1,77 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Copyright (C) 2009 embedded brains GmbH.
*
* 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 exceptions.
*
* Derived from file "libcpu/powerpc/new-exceptions/raw_exception.c".
*
* 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/vectors.h>
bool bsp_exceptions_in_RAM = true;
uint32_t ppc_exc_vector_base = 0;
void *ppc_exc_vector_address(unsigned vector)
{
uintptr_t vector_base = 0xfff00000;
uintptr_t vector_offset = vector << 8;
if (ppc_cpu_has_altivec()) {
if (vector == ASM_60X_VEC_VECTOR) {
vector_offset = ASM_60X_VEC_VECTOR_OFFSET;
}
}
if (ppc_cpu_is(PPC_405)) {
switch (vector) {
case ASM_BOOKE_FIT_VECTOR:
vector_offset = ASM_PPC405_FIT_VECTOR_OFFSET;
break;
case ASM_BOOKE_WDOG_VECTOR:
vector_offset = ASM_PPC405_WDOG_VECTOR_OFFSET;
break;
case ASM_TRACE_VECTOR:
vector_offset = ASM_PPC405_TRACE_VECTOR_OFFSET;
break;
case ASM_PPC405_APU_UNAVAIL_VECTOR:
vector_offset = ASM_60X_VEC_VECTOR_OFFSET;
default:
break;
}
}
if (ppc_cpu_has_ivpr_and_ivor()) {
vector_offset >>= 4;
}
if (bsp_exceptions_in_RAM) {
vector_base = ppc_exc_vector_base;
}
return (void *) (vector_base + vector_offset);
}

View File

@@ -0,0 +1,297 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Copyright (C) 2009 embedded brains GmbH.
*
* 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 exceptions.
*
* Derived from file "libcpu/powerpc/new-exceptions/raw_exception.c".
*
* 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>
#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 const ppc_exc_categories ppc_405_category_table = {
[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,
[ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
[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,
};
static const ppc_exc_categories mpc_5xx_category_table = {
[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 ppc_exc_categories mpc_603_category_table = {
PPC_BASIC_VECS,
[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,
};
static const ppc_exc_categories mpc_604_category_table = {
PPC_BASIC_VECS,
[ASM_60X_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
[ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
[ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
};
static const ppc_exc_categories mpc_604_altivec_category_table = {
PPC_BASIC_VECS,
[ASM_60X_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
[ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
[ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
[ASM_60X_VEC_VECTOR] = PPC_EXC_CLASSIC,
[ASM_60X_VEC_ASSIST_VECTOR] = PPC_EXC_CLASSIC,
};
static const ppc_exc_categories mpc_750_category_table = {
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 ppc_exc_categories mpc_750_altivec_category_table = {
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,
[ASM_60X_VEC_VECTOR] = PPC_EXC_CLASSIC,
[ASM_60X_VEC_ASSIST_VECTOR] = PPC_EXC_CLASSIC,
};
static const ppc_exc_categories mpc_860_category_table = {
PPC_BASIC_VECS,
[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 ppc_exc_categories e200_category_table = {
[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 ppc_exc_categories e300_category_table = {
[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_NAKED,
[ASM_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
[ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
[ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC,
[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 ppc_exc_categories e500_category_table = {
[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,
};
static const ppc_exc_categories psim_category_table = {
PPC_BASIC_VECS,
[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,
};
const ppc_exc_categories *ppc_exc_categories_for_cpu(ppc_cpu_id_t cpu)
{
if (ppc_cpu_has_altivec()) {
switch (cpu) {
case PPC_7400:
return &mpc_750_altivec_category_table;
case PPC_7455:
case PPC_7457:
return &mpc_604_altivec_category_table;
default:
break;
}
}
switch (cpu) {
case PPC_7400:
case PPC_750:
return &mpc_750_category_table;
case PPC_7455:
case PPC_7457:
case PPC_604:
case PPC_604e:
case PPC_604r:
return &mpc_604_category_table;
case PPC_603:
case PPC_603e:
case PPC_603le:
case PPC_603ev:
/* case PPC_8240: same value as 8260 */
case PPC_8260:
case PPC_8245:
return &mpc_603_category_table;
case PPC_e300c1:
case PPC_e300c2:
case PPC_e300c3:
return &e300_category_table;
case PPC_PSIM:
return &psim_category_table;
case PPC_8540:
return &e500_category_table;
case PPC_e200z6:
return &e200_category_table;
case PPC_5XX:
return &mpc_5xx_category_table;
case PPC_860:
return &mpc_860_category_table;
case PPC_405:
case PPC_405GP:
case PPC_405EX:
return &ppc_405_category_table;
default:
break;
}
return NULL;
}
ppc_exc_category ppc_exc_category_for_vector(const ppc_exc_categories *categories, unsigned vector)
{
if (vector <= LAST_VALID_EXC) {
return (*categories) [vector];
} else {
return PPC_EXC_INVALID;
}
}

View File

@@ -0,0 +1,215 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
*
* 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>
exception_handler_t globalExceptHdl = C_exception_handler;
/* 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 */
static uint32_t ppc_exc_get_DAR_dflt(void)
{
if (ppc_cpu_is_60x())
return PPC_SPECIAL_PURPOSE_REGISTER(DAR);
else
switch (ppc_cpu_is_bookE()) {
default:
break;
case PPC_BOOKE_STD:
case PPC_BOOKE_E500:
return PPC_SPECIAL_PURPOSE_REGISTER(DEAR_BOOKE);
case PPC_BOOKE_405:
return PPC_SPECIAL_PURPOSE_REGISTER(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) ppc_link_register();
}
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--;
}
}

View File

@@ -0,0 +1,194 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
*
* Copyright (C) 2009 embedded brains GmbH.
*
* Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
* Derived from file "libcpu/powerpc/new-exceptions/e500_raw_exc_init.c".
*
* 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/vectors.h>
uint32_t ppc_exc_cache_wb_check = 1;
#define MTIVPR(prefix) asm volatile ("mtivpr %0" : : "r" (prefix))
#define MTIVOR(x, vec) asm volatile ("mtivor"#x" %0" : : "r" (vec))
static void ppc_exc_initialize_e500(void)
{
/* Interupt vector prefix register */
MTIVPR(ppc_exc_vector_base);
/* Interupt vector offset register */
MTIVOR(0, ppc_exc_vector_address(ASM_BOOKE_CRIT_VECTOR)); /* Critical input not (yet) supported; use reset vector */
MTIVOR(1, ppc_exc_vector_address(ASM_MACH_VECTOR));
MTIVOR(2, ppc_exc_vector_address(ASM_PROT_VECTOR));
MTIVOR(3, ppc_exc_vector_address(ASM_ISI_VECTOR));
MTIVOR(4, ppc_exc_vector_address(ASM_EXT_VECTOR));
MTIVOR(5, ppc_exc_vector_address(ASM_ALIGN_VECTOR));
MTIVOR(6, ppc_exc_vector_address(ASM_PROG_VECTOR));
MTIVOR(7, ppc_exc_vector_address(ASM_FLOAT_VECTOR));
MTIVOR(8, ppc_exc_vector_address(ASM_SYS_VECTOR));
MTIVOR(9, ppc_exc_vector_address(0x0b));
MTIVOR(10, ppc_exc_vector_address(ASM_BOOKE_DEC_VECTOR));
MTIVOR(11, ppc_exc_vector_address(ASM_BOOKE_FIT_VECTOR));
MTIVOR(12, ppc_exc_vector_address(ASM_BOOKE_WDOG_VECTOR));
MTIVOR(13, ppc_exc_vector_address(ASM_60X_DSMISS_VECTOR));
MTIVOR(14, ppc_exc_vector_address(ASM_60X_DLMISS_VECTOR));
MTIVOR(15, ppc_exc_vector_address(ASM_TRACE_VECTOR));
MTIVOR(32, ppc_exc_vector_address(ASM_60X_VEC_VECTOR));
MTIVOR(33, ppc_exc_vector_address(0x16));
MTIVOR(34, ppc_exc_vector_address(0x15));
MTIVOR(35, ppc_exc_vector_address(ASM_60X_PERFMON_VECTOR));
}
static void ppc_exc_initialize_e200(void)
{
/* Interupt vector prefix register */
MTIVPR(ppc_exc_vector_base);
/* Interupt vector offset register */
MTIVOR(0, 0); /* Critical input */
MTIVOR(1, ppc_exc_vector_address( ASM_MACH_VECTOR));
MTIVOR(2, ppc_exc_vector_address( ASM_PROT_VECTOR));
MTIVOR(3, ppc_exc_vector_address( ASM_ISI_VECTOR));
MTIVOR(4, ppc_exc_vector_address( ASM_EXT_VECTOR));
MTIVOR(5, ppc_exc_vector_address( ASM_ALIGN_VECTOR));
MTIVOR(6, ppc_exc_vector_address( ASM_PROG_VECTOR));
MTIVOR(7, ppc_exc_vector_address( ASM_FLOAT_VECTOR));
MTIVOR(8, ppc_exc_vector_address( ASM_SYS_VECTOR));
MTIVOR(9, 0); /* APU unavailable */
MTIVOR(10, ppc_exc_vector_address( ASM_BOOKE_DEC_VECTOR));
MTIVOR(11, ppc_exc_vector_address( ASM_BOOKE_FIT_VECTOR));
MTIVOR(12, ppc_exc_vector_address( ASM_BOOKE_WDOG_VECTOR));
MTIVOR(13, ppc_exc_vector_address( ASM_BOOKE_ITLBMISS_VECTOR));
MTIVOR(14, ppc_exc_vector_address( ASM_BOOKE_DTLBMISS_VECTOR));
MTIVOR(15, ppc_exc_vector_address( ASM_TRACE_VECTOR));
MTIVOR(32, ppc_exc_vector_address( ASM_E200_SPE_UNAVAILABLE_VECTOR));
MTIVOR(33, ppc_exc_vector_address( ASM_E200_SPE_DATA_VECTOR));
MTIVOR(34, ppc_exc_vector_address( ASM_E200_SPE_ROUND_VECTOR));
}
rtems_status_code ppc_exc_initialize(
uint32_t interrupt_disable_mask,
uintptr_t interrupt_stack_begin,
uintptr_t interrupt_stack_size
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
const ppc_exc_categories *const categories = ppc_exc_current_categories();
uintptr_t const interrupt_stack_end = interrupt_stack_begin + interrupt_stack_size;
uintptr_t interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
unsigned vector = 0;
uint32_t sda_base = 0;
uint32_t r13 = 0;
if (categories == NULL) {
return RTEMS_NOT_IMPLEMENTED;
}
/* 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) {
return RTEMS_NOT_CONFIGURED;
}
/* Ensure proper interrupt stack alignment */
interrupt_stack_pointer &= ~((uint32_t) CPU_STACK_ALIGNMENT - 1);
/* Tag interrupt stack bottom */
*(uint32_t *) interrupt_stack_pointer = 0;
/* Move interrupt stack values to special purpose registers */
PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG1, interrupt_stack_pointer);
PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG2, interrupt_stack_begin);
ppc_interrupt_set_disable_mask(interrupt_disable_mask);
/* Use current MMU / RI settings when running C exception handlers */
ppc_exc_msr_bits = ppc_machine_state_register() & (MSR_DR | MSR_IR | MSR_RI);
if (ppc_cpu_is(PPC_e200z6)) {
ppc_exc_initialize_e200();
} else if (ppc_cpu_is_bookE() == PPC_BOOKE_STD || ppc_cpu_is_bookE() == PPC_BOOKE_E500) {
ppc_exc_initialize_e500();
}
for (vector = 0; vector <= LAST_VALID_EXC; ++vector) {
ppc_exc_category category = ppc_exc_category_for_vector(categories, vector);
if (category != PPC_EXC_INVALID) {
void *const vector_address = ppc_exc_vector_address(vector);
uint32_t prologue [16];
size_t prologue_size = sizeof(prologue);
sc = ppc_exc_make_prologue(vector, category, prologue, &prologue_size);
if (sc != RTEMS_SUCCESSFUL) {
return RTEMS_INTERNAL_ERROR;
}
ppc_code_copy(vector_address, prologue, prologue_size);
}
}
/* 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 + 31U) & ~31U;
asm volatile ("dcbz 0, %0"::"b" (p));
/* If we make it thru here then things seem to be OK */
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -0,0 +1,189 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-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 "ppc_exc_asm_macros.h"
.global ppc_exc_min_prolog_tmpl_naked
ppc_exc_min_prolog_tmpl_naked:
stwu r1, -EXCEPTION_FRAME_END(r1)
stw VECTOR_REGISTER, VECTOR_OFFSET(r1)
li VECTOR_REGISTER, 0
ba wrap_naked
wrap_naked:
/* Save scratch registers */
stw SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1)
stw SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1)
stw SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1)
/* Save volatile registers */
stw r0, GPR0_OFFSET(r1)
stw r3, GPR3_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)
/* Save CR */
mfcr SCRATCH_REGISTER_0
stw SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1)
/* Save SRR0 */
mfspr SCRATCH_REGISTER_0, srr0
stw SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1)
/* Save SRR1 */
mfspr SCRATCH_REGISTER_0, srr1
stw SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(r1)
/* Save CTR */
mfctr SCRATCH_REGISTER_0
stw SCRATCH_REGISTER_0, EXC_CTR_OFFSET(r1)
/* Save XER */
mfxer SCRATCH_REGISTER_0
stw SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1)
/* Save LR */
mflr SCRATCH_REGISTER_0
stw SCRATCH_REGISTER_0, EXC_LR_OFFSET(r1)
/* Load MSR bit mask */
lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
/*
* Change the MSR if necessary (MMU, RI), remember decision in
* non-volatile CR_MSR.
*/
cmpwi CR_MSR, SCRATCH_REGISTER_0, 0
bne CR_MSR, wrap_change_msr_naked
wrap_change_msr_done_naked:
/*
* Call high level exception handler
*/
/*
* Get the handler table index from the vector number. We have to
* discard the exception type. Take only the least significant five
* bits (= LAST_VALID_EXC + 1) from the vector register. Multiply by
* four (= size of function pointer).
*/
rlwinm SCRATCH_REGISTER_1, VECTOR_REGISTER, 2, 25, 29
/* Load handler table address */
LA SCRATCH_REGISTER_0, ppc_exc_handler_table
/* Load handler address */
lwzx SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1
/*
* First parameter = exception frame pointer + FRAME_LINK_SPACE
*
* We add FRAME_LINK_SPACE to the frame pointer because the high level
* handler expects a BSP_Exception_frame structure.
*/
addi r3, r1, FRAME_LINK_SPACE
/*
* Second parameter = vector number (r4 is the VECTOR_REGISTER)
*
* Discard the exception type and store the vector number
* in the vector register. Take only the least significant
* five bits (= LAST_VALID_EXC + 1).
*/
rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
/* Call handler */
mtctr SCRATCH_REGISTER_0
bctrl
/* Restore MSR? */
bne CR_MSR, wrap_restore_msr_naked
wrap_restore_msr_done_naked:
/* Restore XER and CTR */
lwz SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1)
lwz SCRATCH_REGISTER_1, EXC_CTR_OFFSET(r1)
mtxer SCRATCH_REGISTER_0
mtctr SCRATCH_REGISTER_1
/* Restore CR and LR */
lwz SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1)
lwz SCRATCH_REGISTER_1, EXC_LR_OFFSET(r1)
mtcr SCRATCH_REGISTER_0
mtlr SCRATCH_REGISTER_1
/* Restore volatile registers */
lwz r0, GPR0_OFFSET(r1)
lwz r3, GPR3_OFFSET(r1)
lwz r8, GPR8_OFFSET(r1)
lwz r9, GPR9_OFFSET(r1)
lwz r10, GPR10_OFFSET(r1)
lwz r11, GPR11_OFFSET(r1)
lwz r12, GPR12_OFFSET(r1)
/* Restore vector register */
lwz VECTOR_REGISTER, VECTOR_OFFSET(r1)
/* Restore scratch registers and SRRs */
lwz SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1)
lwz SCRATCH_REGISTER_1, SRR1_FRAME_OFFSET(r1)
lwz SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1)
mtspr srr0, SCRATCH_REGISTER_0
lwz SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1)
mtspr srr1, SCRATCH_REGISTER_1
lwz SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1)
/*
* We restore r1 from the frame rather than just popping (adding to
* current r1) since the exception handler might have done strange
* things (e.g. a debugger moving and relocating the stack).
*/
lwz r1, 0(r1)
/* Return */
rfi
wrap_change_msr_naked:
mfmsr SCRATCH_REGISTER_1
or SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
mtmsr SCRATCH_REGISTER_1
sync
isync
b wrap_change_msr_done_naked
wrap_restore_msr_naked:
lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
mfmsr SCRATCH_REGISTER_1
andc SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
mtmsr SCRATCH_REGISTER_1
sync
isync
b wrap_restore_msr_done_naked

View File

@@ -0,0 +1,127 @@
/**
* @file
*
* @ingroup ppc_exc
*
* @brief PowerPC Exceptions implementation.
*/
/*
* Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
*
* Copyright (C) 2009 embedded brains GmbH.
*
* 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>
#include <bsp/vectors.h>
/* Offset into minimal prolog where vector number is hardcoded */
#define PPC_EXC_PROLOG_VEC_OFFSET 2
/* Symbols are defined by the linker */
extern const char ppc_exc_min_prolog_size [];
extern const char ppc_exc_tgpr_clr_prolog_size [];
/* Special prologue for handling register shadowing on 603-style CPUs */
extern const uint32_t ppc_exc_tgpr_clr_prolog [];
/*
* Classic prologue which determines the vector dynamically from the offset
* address. This must only be used for classic, synchronous exceptions with a
* vector offset aligned on a 256-byte boundary.
*/
extern const uint32_t ppc_exc_min_prolog_auto [];
extern const uint32_t ppc_exc_min_prolog_auto_packed [];
/* Minimal prologue templates */
extern const uint32_t ppc_exc_min_prolog_async_tmpl_std [];
extern const uint32_t ppc_exc_min_prolog_sync_tmpl_std [];
extern const uint32_t ppc_exc_min_prolog_async_tmpl_p405_crit [];
extern const uint32_t ppc_exc_min_prolog_sync_tmpl_p405_crit [];
extern const uint32_t ppc_exc_min_prolog_async_tmpl_bookE_crit [];
extern const uint32_t ppc_exc_min_prolog_sync_tmpl_bookE_crit [];
extern const uint32_t ppc_exc_min_prolog_sync_tmpl_e500_mchk [];
extern const uint32_t ppc_exc_min_prolog_async_tmpl_e500_mchk [];
extern const uint32_t ppc_exc_min_prolog_tmpl_naked [];
static const uint32_t *const ppc_exc_prologue_templates [] = {
[PPC_EXC_CLASSIC] = ppc_exc_min_prolog_sync_tmpl_std,
[PPC_EXC_CLASSIC_ASYNC] = ppc_exc_min_prolog_async_tmpl_std,
[PPC_EXC_405_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_p405_crit,
[PPC_EXC_405_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_p405_crit,
[PPC_EXC_BOOKE_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_bookE_crit,
[PPC_EXC_BOOKE_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_bookE_crit,
[PPC_EXC_E500_MACHCHK] = ppc_exc_min_prolog_sync_tmpl_e500_mchk,
[PPC_EXC_E500_MACHCHK_ASYNC] = ppc_exc_min_prolog_async_tmpl_e500_mchk,
[PPC_EXC_NAKED] = ppc_exc_min_prolog_tmpl_naked
};
rtems_status_code ppc_exc_make_prologue(
unsigned vector,
ppc_exc_category category,
uint32_t *prologue,
size_t *prologue_size
)
{
const uint32_t *prologue_template = NULL;
size_t prologue_template_size = 0;
uintptr_t vector_address = (uintptr_t) ppc_exc_vector_address(vector);
bool fixup_vector = false;
if (!ppc_exc_is_valid_category(category)) {
return RTEMS_INVALID_NUMBER;
}
if (
ppc_cpu_has_shadowed_gprs()
&& (vector == ASM_60X_IMISS_VECTOR
|| vector == ASM_60X_DLMISS_VECTOR
|| vector == ASM_60X_DSMISS_VECTOR)
) {
prologue_template = ppc_exc_tgpr_clr_prolog;
prologue_template_size = (size_t) ppc_exc_tgpr_clr_prolog_size;
} else if (
category == PPC_EXC_CLASSIC
&& ((vector_address & 0xffU) == 0
|| (ppc_cpu_has_ivpr_and_ivor() && (vector_address & 0xfU) == 0))
) {
if (ppc_cpu_has_ivpr_and_ivor()) {
prologue_template = ppc_exc_min_prolog_auto_packed;
} else {
prologue_template = ppc_exc_min_prolog_auto;
}
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
} else {
prologue_template = ppc_exc_prologue_templates [category];
prologue_template_size = (size_t) ppc_exc_min_prolog_size;
fixup_vector = true;
}
if (prologue_template_size <= *prologue_size) {
*prologue_size = prologue_template_size;
memcpy(prologue, prologue_template, prologue_template_size);
if (fixup_vector) {
if (vector <= 0x7fffU) {
prologue [PPC_EXC_PROLOG_VEC_OFFSET] =
(prologue [PPC_EXC_PROLOG_VEC_OFFSET] & 0xffff8000U)
| (vector & 0x7fffU);
} else {
return RTEMS_INVALID_ID;
}
}
} else {
return RTEMS_INVALID_SIZE;
}
return RTEMS_SUCCESSFUL;
}