diff options
Diffstat (limited to 'c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c')
-rw-r--r-- | c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c new file mode 100644 index 0000000000..5d2de9dc3e --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c @@ -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; +} |