forked from Imagelibrary/rtems
add new files for exception handler
This commit is contained in:
47
c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h
Normal file
47
c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup bsp_interrupt
|
||||||
|
*
|
||||||
|
* @brief BSP interrupt support configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
|
||||||
|
#define LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <bsp/irq.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup bsp_interrupt
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimum vector number.
|
||||||
|
*/
|
||||||
|
#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum vector number.
|
||||||
|
*/
|
||||||
|
#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H */
|
||||||
47
c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h
Normal file
47
c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup bsp_interrupt
|
||||||
|
*
|
||||||
|
* @brief BSP interrupt support configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
|
||||||
|
#define LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <bsp/irq.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup bsp_interrupt
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimum vector number.
|
||||||
|
*/
|
||||||
|
#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum vector number.
|
||||||
|
*/
|
||||||
|
#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H */
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user