summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/ss555
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-03-13 16:24:16 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-03-19 07:00:20 +0100
commitbd1508019cfb219b41da7cb6f1a9895a69c64534 (patch)
tree6c3f15e745ef11dc3d7c3b706fde54c95dac055d /bsps/powerpc/ss555
parentbsps/powerpc: Remove unused files (diff)
downloadrtems-bd1508019cfb219b41da7cb6f1a9895a69c64534.tar.bz2
bsps/powerpc: Move exceptions support to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/powerpc/ss555')
-rw-r--r--bsps/powerpc/ss555/start/vectors.S201
-rw-r--r--bsps/powerpc/ss555/start/vectors_init.c137
2 files changed, 338 insertions, 0 deletions
diff --git a/bsps/powerpc/ss555/start/vectors.S b/bsps/powerpc/ss555/start/vectors.S
new file mode 100644
index 0000000000..35d2f23a30
--- /dev/null
+++ b/bsps/powerpc/ss555/start/vectors.S
@@ -0,0 +1,201 @@
+/*
+ * vectors.S
+ *
+ * This file contains the assembly code for the PowerPC exception veneers
+ * for RTEMS.
+ *
+ *
+ * MPC5xx port sponsored by Defence Research and Development Canada - Suffield
+ * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
+ *
+ * Derived from libbsp/powerpc/mbx8xx/vectors/vectors.S,
+ *
+ * (c) 1999, Eric Valette valette@crf.canon.fr
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+#include <libcpu/vectors.h>
+
+#define SYNC \
+ sync; \
+ isync
+
+
+/*
+ * Hardware exception vector table.
+ *
+ * The MPC555 can be configured to use a compressed vector table with 8
+ * bytes per entry, rather than the usual 0x100 bytes of other PowerPC
+ * devices. The following macro uses this feature to save the better part
+ * of 8 kbytes of flash ROM.
+ *
+ * Each vector table entry has room for only a simple branch instruction
+ * which branches to a prologue specific to that exception. This
+ * exception-specific prologue begins the context save, loads the exception
+ * number into a register, and jumps to a common exception prologue, below.
+ */
+
+ .macro vectors num=0, total=NUM_EXCEPTIONS /* create vector table */
+
+/* vector table entry */
+ .section .vectors, "ax"
+
+ ba specific_prologue\@ /* run specific prologue */
+ .long 0 /* each entry is 8 bytes */
+
+/* exception-specific prologue */
+ .text
+
+specific_prologue\@:
+ stwu r1, -EXCEPTION_FRAME_END(r1) /* open stack frame */
+ stw r4, GPR4_OFFSET(r1) /* preserve register */
+ li r4, \num /* get exception number */
+ b common_prologue /* run common prologue */
+
+/* invoke macro recursively to create remainder of table */
+ .if \total - (\num + 1)
+ vectors "(\num + 1)", \total
+ .endif
+
+ .endm
+
+
+/* invoke macro to create entire vector table */
+ vectors
+
+
+/*
+ * Common exception prologue.
+ *
+ * Because the MPC555 vector table is in flash ROM, it's not possible to
+ * change the exception handlers by overwriting them at run-time, so this
+ * common exception prologue uses a table of exception handler pointers to
+ * provide equivalent flexibility.
+ *
+ * When the actual exception handler is run, R1 points to the base of a new
+ * exception stack frame, in which R3, R4 and LR have been saved. R4 holds
+ * the exception number.
+ */
+ .text
+
+common_prologue:
+ stw r3, GPR3_OFFSET(r1) /* preserve registers */
+ mflr r3
+ stw r3, EXC_LR_OFFSET(r1)
+
+ slwi r3, r4, 2 /* make table offset */
+ addis r3, r3, exception_handler_table@ha /* point to entry */
+ addi r3, r3, exception_handler_table@l
+ lwz r3, 0(r3) /* get entry */
+ mtlr r3 /* run it */
+ blr
+
+
+/*
+ * Default exception handler.
+ *
+ * The function initialize_exceptions() initializes all of the entries in
+ * the exception handler table with pointers to this routine, which saves
+ * the remainder of the interrupted code's state, then calls
+ * C_default_exception_handler() to dump registers.
+ *
+ * On entry, R1 points to a new exception stack frame in which R3, R4, and
+ * LR have been saved. R4 holds the exception number.
+ */
+ .text
+
+PUBLIC_VAR(default_exception_handler)
+SYM (default_exception_handler):
+ /*
+ * Save the interrupted code's program counter and MSR. Beyond this
+ * point, all exceptions are recoverable. Use an RCPU-specific SPR
+ * to set the RI bit in the MSR to indicate the recoverable state.
+ */
+ mfsrr0 r3
+ stw r3, SRR0_FRAME_OFFSET(r1)
+ mfsrr1 r3
+ stw r3, SRR1_FRAME_OFFSET(r1)
+
+ mtspr eid, r3 /* set MSR[RI], clear MSR[EE] */
+ SYNC
+
+ /*
+ * Save the remainder of the general-purpose registers.
+ *
+ * Compute the value of R1 at exception entry before storing it in
+ * the frame.
+ *
+ * Note that R2 should never change (it's the EABI pointer to
+ * .sdata2), but we save it just in case.
+ *
+ * Recall that R3 and R4 were saved by the specific- and
+ * common-exception handlers before entry to this routine.
+ */
+ stw r0, GPR0_OFFSET(r1)
+ addi r0, r1, EXCEPTION_FRAME_END
+ stw r0, GPR1_OFFSET(r1)
+ stw r2, GPR2_OFFSET(r1)
+ stmw r5, GPR5_OFFSET(r1) /* save R5 to R31 */
+
+ /*
+ * Save the remainder of the UISA special-purpose registers. Recall
+ * that LR was saved before entry.
+ */
+ mfcr r0
+ stw r0, EXC_CR_OFFSET(r1)
+ mfctr r0
+ stw r0, EXC_CTR_OFFSET(r1)
+ mfxer r0
+ stw r0, EXC_XER_OFFSET(r1)
+
+ /*
+ * Call C-language portion of the default exception handler, passing
+ * in the address of the frame.
+ *
+ * To simplify things a bit, we assume that the target routine is
+ * within +/- 32 Mbyte from here, which is a reasonable assumption
+ * on the MPC555.
+ */
+ stw r4, EXCEPTION_NUMBER_OFFSET(r1) /* save exception number */
+ addi r3, r1, 0x8 /* get frame address */
+ bl C_default_exception_handler /* call handler */
+
+ /*
+ * Restore UISA special-purpose registers.
+ */
+ lwz r0, EXC_XER_OFFSET(r1)
+ mtxer r0
+ lwz r0, EXC_CTR_OFFSET(r1)
+ mtctr r0
+ lwz r0, EXC_CR_OFFSET(r1)
+ mtcr r0
+ lwz r0, EXC_LR_OFFSET(r1)
+ mtlr r0
+
+ /*
+ * Restore most general-purpose registers.
+ */
+ lmw r2, GPR2_OFFSET(r1)
+
+ /*
+ * Restore the interrupted code's program counter and MSR, but first
+ * use an RCPU-specific special-purpose register to clear the RI
+ * bit, indicating that exceptions are temporarily non-recoverable.
+ */
+ mtspr nri, r0 /* clear MSR[RI] */
+ SYNC
+
+ lwz r0, SRR1_FRAME_OFFSET(r1)
+ mtsrr1 r0
+ lwz r0, SRR0_FRAME_OFFSET(r1)
+ mtsrr0 r0
+
+ /*
+ * Restore the final GPR, close the stack frame, and return to the
+ * interrupted code.
+ */
+ lwz r0, GPR0_OFFSET(r1)
+ addi r1, r1, EXCEPTION_FRAME_END
+ SYNC
+ rfi
diff --git a/bsps/powerpc/ss555/start/vectors_init.c b/bsps/powerpc/ss555/start/vectors_init.c
new file mode 100644
index 0000000000..342ca5509a
--- /dev/null
+++ b/bsps/powerpc/ss555/start/vectors_init.c
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+/*
+ * MPC5xx port sponsored by Defence Research and Development Canada - Suffield
+ * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
+ *
+ * Derived from libbsp/powerpc/mbx8xx/vectors/vectors_init.c:
+ *
+ * CopyRight (C) 1999 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.org/license/LICENSE.
+ */
+#include <inttypes.h>
+#include <rtems/bspIo.h>
+#include <libcpu/vectors.h>
+#include <libcpu/raw_exception.h>
+#include <bsp/irq.h>
+
+extern rtems_exception_handler_t default_exception_handler;
+
+static rtems_raw_except_global_settings exception_config;
+static rtems_raw_except_connect_data exception_table[NUM_EXCEPTIONS];
+rtems_exception_handler_t* exception_handler_table[NUM_EXCEPTIONS];
+
+void C_default_exception_handler(CPU_Exception_frame* excPtr)
+{
+ int recoverable = 0;
+
+ printk("exception handler called for exception %" PRIu32 "\n",
+ excPtr->_EXC_number);
+ printk("\t Next PC or Address of fault = %" PRIxPTR "\n", excPtr->EXC_SRR0);
+ printk("\t Saved MSR = %" PRIxPTR "\n", excPtr->EXC_SRR1);
+ printk("\t R0 = %" PRIxPTR "\n", excPtr->GPR0);
+ printk("\t R1 = %" PRIxPTR "\n", excPtr->GPR1);
+ printk("\t R2 = %" PRIxPTR "\n", excPtr->GPR2);
+ printk("\t R3 = %" PRIxPTR "\n", excPtr->GPR3);
+ printk("\t R4 = %" PRIxPTR "\n", excPtr->GPR4);
+ printk("\t R5 = %" PRIxPTR "\n", excPtr->GPR5);
+ printk("\t R6 = %" PRIxPTR "\n", excPtr->GPR6);
+ printk("\t R7 = %" PRIxPTR "\n", excPtr->GPR7);
+ printk("\t R8 = %" PRIxPTR "\n", excPtr->GPR8);
+ printk("\t R9 = %" PRIxPTR "\n", excPtr->GPR9);
+ printk("\t R10 = %" PRIxPTR "\n", excPtr->GPR10);
+ printk("\t R11 = %" PRIxPTR "\n", excPtr->GPR11);
+ printk("\t R12 = %" PRIxPTR "\n", excPtr->GPR12);
+ printk("\t R13 = %" PRIxPTR "\n", excPtr->GPR13);
+ printk("\t R14 = %" PRIxPTR "\n", excPtr->GPR14);
+ printk("\t R15 = %" PRIxPTR "\n", excPtr->GPR15);
+ printk("\t R16 = %" PRIxPTR "\n", excPtr->GPR16);
+ printk("\t R17 = %" PRIxPTR "\n", excPtr->GPR17);
+ printk("\t R18 = %" PRIxPTR "\n", excPtr->GPR18);
+ printk("\t R19 = %" PRIxPTR "\n", excPtr->GPR19);
+ printk("\t R20 = %" PRIxPTR "\n", excPtr->GPR20);
+ printk("\t R21 = %" PRIxPTR "\n", excPtr->GPR21);
+ printk("\t R22 = %" PRIxPTR "\n", excPtr->GPR22);
+ printk("\t R23 = %" PRIxPTR "\n", excPtr->GPR23);
+ printk("\t R24 = %" PRIxPTR "\n", excPtr->GPR24);
+ printk("\t R25 = %" PRIxPTR "\n", excPtr->GPR25);
+ printk("\t R26 = %" PRIxPTR "\n", excPtr->GPR26);
+ printk("\t R27 = %" PRIxPTR "\n", excPtr->GPR27);
+ printk("\t R28 = %" PRIxPTR "\n", excPtr->GPR28);
+ printk("\t R29 = %" PRIxPTR "\n", excPtr->GPR29);
+ printk("\t R30 = %" PRIxPTR "\n", excPtr->GPR30);
+ printk("\t R31 = %" PRIxPTR "\n", excPtr->GPR31);
+ printk("\t CR = %" PRIx32 "\n", excPtr->EXC_CR);
+ printk("\t CTR = %" PRIxPTR "\n", excPtr->EXC_CTR);
+ printk("\t XER = %" PRIx32 "\n", excPtr->EXC_XER);
+ printk("\t LR = %" PRIxPTR "\n", excPtr->EXC_LR);
+ 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);
+ }
+}
+
+static void nop_except_enable(const rtems_raw_except_connect_data* ptr)
+{
+}
+
+static int except_always_enabled(const rtems_raw_except_connect_data* ptr)
+{
+ return 1;
+}
+
+void initialize_exceptions(void)
+{
+ int i;
+
+ /*
+ * Initialize all entries of the exception table with a description of the
+ * default exception handler.
+ */
+ exception_config.exceptSize = NUM_EXCEPTIONS;
+ 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_handler;
+
+ for (i = 0; i < exception_config.exceptSize; i++) {
+ printk("installing exception number %d\n", i);
+ 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;
+ }
+
+ /*
+ * Now pass the initialized exception table to the exceptions module which
+ * will install the handler pointers in the exception handler table.
+ */
+ if (!mpc5xx_init_exceptions(&exception_config)) {
+ /*
+ * At this stage we may not call CPU_Panic because it uses exceptions!!!
+ */
+ printk("Exception handling initialization failed\n");
+ printk("System locked\n"); while(1);
+ }
+ else {
+ printk("Exception handling initialization done\n");
+ }
+}