cpukit/microblaze: Add exception framework

This patch updates the CPU_Exception_frame to include all necessary
registers, combines hardware snd software exception handlers into a
shared vector, provides an architecture-specific hook for taking
control of exception handling, and moves exception handling over to
actually using the CPU_Exception_frame instead of a minimal interrupt
stack frame. As the significant contents of _exception_handler.S have
been entirely rewritten, the copyright information on this file has been
updated to reflect that.
This commit is contained in:
Kinsey Moore
2022-02-04 11:30:59 -06:00
committed by Joel Sherrill
parent 37543e1968
commit 127980c799
7 changed files with 286 additions and 113 deletions
@@ -1,52 +1,103 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* SPDX-License-Identifier: BSD-2-Clause */
/* Copyright (c) 2001, 2009 Xilinx, Inc. All rights reserved.
/**
* @file
*
* @ingroup RTEMSBSPsMicroBlaze
*
* @brief MicroBlaze exception handler implementation
*/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
/*
* Copyright (C) 2022 On-Line Applications Research Corporation (OAR)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
1. Redistributions source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Xilinx nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/score/cpu.h>
.text
.globl _exception_handler # Exception Handler Label
.align 2
_exception_handler:
#ifndef __rtems__
rtsd r17, 0
/* Subtract exception frame */
addik r1, r1, -(CPU_EXCEPTION_FRAME_SIZE)
/* Store program state */
swi r2, r1, MICROBLAZE_EXCEPTION_FRAME_R2
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_R3
swi r4, r1, MICROBLAZE_EXCEPTION_FRAME_R4
swi r5, r1, MICROBLAZE_EXCEPTION_FRAME_R5
swi r6, r1, MICROBLAZE_EXCEPTION_FRAME_R6
swi r7, r1, MICROBLAZE_EXCEPTION_FRAME_R7
swi r8, r1, MICROBLAZE_EXCEPTION_FRAME_R8
swi r9, r1, MICROBLAZE_EXCEPTION_FRAME_R9
swi r10, r1, MICROBLAZE_EXCEPTION_FRAME_R10
swi r11, r1, MICROBLAZE_EXCEPTION_FRAME_R11
swi r12, r1, MICROBLAZE_EXCEPTION_FRAME_R12
swi r13, r1, MICROBLAZE_EXCEPTION_FRAME_R13
swi r14, r1, MICROBLAZE_EXCEPTION_FRAME_R14
swi r15, r1, MICROBLAZE_EXCEPTION_FRAME_R15
swi r16, r1, MICROBLAZE_EXCEPTION_FRAME_R16
swi r17, r1, MICROBLAZE_EXCEPTION_FRAME_R17
swi r18, r1, MICROBLAZE_EXCEPTION_FRAME_R18
swi r19, r1, MICROBLAZE_EXCEPTION_FRAME_R19
swi r20, r1, MICROBLAZE_EXCEPTION_FRAME_R20
swi r21, r1, MICROBLAZE_EXCEPTION_FRAME_R21
swi r22, r1, MICROBLAZE_EXCEPTION_FRAME_R22
swi r23, r1, MICROBLAZE_EXCEPTION_FRAME_R23
swi r24, r1, MICROBLAZE_EXCEPTION_FRAME_R24
swi r25, r1, MICROBLAZE_EXCEPTION_FRAME_R25
swi r26, r1, MICROBLAZE_EXCEPTION_FRAME_R26
swi r27, r1, MICROBLAZE_EXCEPTION_FRAME_R27
swi r28, r1, MICROBLAZE_EXCEPTION_FRAME_R28
swi r29, r1, MICROBLAZE_EXCEPTION_FRAME_R29
swi r30, r1, MICROBLAZE_EXCEPTION_FRAME_R30
swi r31, r1, MICROBLAZE_EXCEPTION_FRAME_R31
/* Retrieve and store MSR */
mfs r3, rmsr
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_MSR
/* Retrieve and store EAR */
mfs r3, rear
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_EAR
/* Retrieve and store ESR */
mfs r3, resr
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_ESR
/* Retrieve and store BTR */
mfs r3, rbtr
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_BTR
/* Calculate and store original stack pointer */
addik r3, r1, CPU_EXCEPTION_FRAME_SIZE
swi r3, r1, MICROBLAZE_EXCEPTION_FRAME_R1
/* set parameter 1 to CPU Exception frame */
addi r5, r1, 0
/* call into the debug framework */
braid _MicroBlaze_Exception_handle
nop
#else /* __rtems__ */
/* Subtract stack frame */
addik r1, r1, -52
swi r5, r1, 8
addi r5, r0, 0xFFFF
braid _ISR_Handler
nop
#endif /* __rtems__ */
@@ -1,52 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2001, 2009 Xilinx, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Xilinx nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.text
.globl _hw_exception_handler # HW Exception Handler Label
.align 2
_hw_exception_handler:
#ifndef __rtems__
rtsd r17, 0
nop
#else /* __rtems__ */
/* Subtract stack frame */
addik r1, r1, -52
swi r5, r1, 8
addi r5, r0, 0xFFFF
braid _ISR_Handler
nop
#endif /* __rtems__ */
+6 -1
View File
@@ -76,7 +76,12 @@ _vector_interrupt:
.section .vectors.hw_exception, "ax"
.align 2
_vector_hw_exception:
brai _hw_exception_handler
/*
* Hardware and software exceptions are handled identically with the MSR[EiP]
* bit differentiating them and determining which register should be used for
* return.
*/
brai _exception_handler
.section .text
.globl _start1
+85
View File
@@ -38,6 +38,10 @@
#include "config.h"
#endif
#include <inttypes.h>
#include <rtems/bspIo.h>
#include <rtems/fatal.h>
#include <rtems/score/isr.h>
#include <rtems/score/tls.h>
#include <rtems/score/wkspace.h>
@@ -75,6 +79,60 @@ void _CPU_Context_Initialize(
void _CPU_Exception_frame_print( const CPU_Exception_frame *ctx )
{
printk(
"\n"
"R0 = 0x%08" PRIx32 " R17 = %p\n"
"R1 = 0x%08" PRIx32 " R18 = 0x%08" PRIx32 "\n"
"R2 = 0x%08" PRIx32 " R19 = 0x%08" PRIx32 "\n"
"R3 = 0x%08" PRIx32 " R20 = 0x%08" PRIx32 "\n"
"R4 = 0x%08" PRIx32 " R21 = 0x%08" PRIx32 "\n"
"R5 = 0x%08" PRIx32 " R22 = 0x%08" PRIx32 "\n"
"R6 = 0x%08" PRIx32 " R23 = 0x%08" PRIx32 "\n"
"R7 = 0x%08" PRIx32 " R24 = 0x%08" PRIx32 "\n"
"R8 = 0x%08" PRIx32 " R25 = 0x%08" PRIx32 "\n"
"R9 = 0x%08" PRIx32 " R26 = 0x%08" PRIx32 "\n"
"R10 = 0x%08" PRIx32 " R27 = 0x%08" PRIx32 "\n"
"R11 = 0x%08" PRIx32 " R28 = 0x%08" PRIx32 "\n"
"R12 = 0x%08" PRIx32 " R29 = 0x%08" PRIx32 "\n"
"R13 = 0x%08" PRIx32 " R30 = 0x%08" PRIx32 "\n"
"R14 = %p" " R31 = 0x%08" PRIx32 "\n"
"R15 = %p" " ESR = 0x%08" PRIx32 "\n"
"R16 = %p" " EAR = %p\n",
0, ctx->r17,
ctx->r1, ctx->r18,
ctx->r2, ctx->r19,
ctx->r3, ctx->r20,
ctx->r4, ctx->r21,
ctx->r5, ctx->r22,
ctx->r6, ctx->r23,
ctx->r7, ctx->r24,
ctx->r8, ctx->r25,
ctx->r9, ctx->r26,
ctx->r10, ctx->r27,
ctx->r11, ctx->r28,
ctx->r12, ctx->r29,
ctx->r13, ctx->r30,
ctx->r14, ctx->r31,
ctx->r15, ctx->esr,
ctx->r16, ctx->ear
);
printk(
"MSR = 0x%08" PRIx32 " %s%s%s%s%s%s%s%s%s%s%s%s\n",
ctx->msr,
( ctx->msr & MICROBLAZE_MSR_VM ) ? "VM " : "",
( ctx->msr & MICROBLAZE_MSR_UM ) ? "UM " : "",
( ctx->msr & MICROBLAZE_MSR_PVR ) ? "PVR " : "",
( ctx->msr & MICROBLAZE_MSR_EIP ) ? "EiP " : "",
( ctx->msr & MICROBLAZE_MSR_EE ) ? "EE " : "",
( ctx->msr & MICROBLAZE_MSR_DCE ) ? "DCE " : "",
( ctx->msr & MICROBLAZE_MSR_DZO ) ? "DZO " : "",
( ctx->msr & MICROBLAZE_MSR_ICE ) ? "ICE " : "",
( ctx->msr & MICROBLAZE_MSR_FSL ) ? "FSL " : "",
( ctx->msr & MICROBLAZE_MSR_BIP ) ? "BiP " : "",
( ctx->msr & MICROBLAZE_MSR_C ) ? "C " : "",
( ctx->msr & MICROBLAZE_MSR_IE ) ? "IE " : ""
);
}
void _CPU_ISR_Set_level( uint32_t level )
@@ -118,3 +176,30 @@ void *_CPU_Thread_Idle_body( uintptr_t ignored )
while ( true ) {
}
}
MicroBlaze_Exception_handler installed_exception_handler = NULL;
void _MicroBlaze_Exception_install_handler(
MicroBlaze_Exception_handler new_handler,
MicroBlaze_Exception_handler *old_handler
)
{
if ( old_handler != NULL ) {
*old_handler = installed_exception_handler;
}
installed_exception_handler = new_handler;
}
void _MicroBlaze_Exception_handle( CPU_Exception_frame *ef )
{
/* EiP is not set for user exceptions which are unused and not hooked */
if (
( ef->msr & MICROBLAZE_MSR_EIP ) != 0
&& installed_exception_handler != NULL
) {
installed_exception_handler( ef );
}
rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) ef );
}
-13
View File
@@ -54,9 +54,6 @@ _ISR_Handler:
swi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15
swi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18
xori r3, r5, 0xFFFF
beqi r3, do_exception
/* Disable dispatching */
lwi r3, r0, _Per_CPU_Information + 16
addik r3, r3, 1
@@ -180,13 +177,3 @@ thread_dispatch:
addik r1, r1, 52
bri quick_exit
do_exception:
/* exception no longer in progress */
mfs r3, rmsr
andni r3, r3, 0x200
mts rmsr, r3
addi r5, r0, 9
add r6, r0, r1
brai _Terminate
@@ -65,6 +65,44 @@
#define CPU_MODES_INTERRUPT_MASK 0x00000001
#define MICROBLAZE_EXCEPTION_FRAME_R1 0
#define MICROBLAZE_EXCEPTION_FRAME_R2 4
#define MICROBLAZE_EXCEPTION_FRAME_R3 8
#define MICROBLAZE_EXCEPTION_FRAME_R4 12
#define MICROBLAZE_EXCEPTION_FRAME_R5 16
#define MICROBLAZE_EXCEPTION_FRAME_R6 20
#define MICROBLAZE_EXCEPTION_FRAME_R7 24
#define MICROBLAZE_EXCEPTION_FRAME_R8 28
#define MICROBLAZE_EXCEPTION_FRAME_R9 32
#define MICROBLAZE_EXCEPTION_FRAME_R10 36
#define MICROBLAZE_EXCEPTION_FRAME_R11 40
#define MICROBLAZE_EXCEPTION_FRAME_R12 44
#define MICROBLAZE_EXCEPTION_FRAME_R13 48
#define MICROBLAZE_EXCEPTION_FRAME_R14 52
#define MICROBLAZE_EXCEPTION_FRAME_R15 56
#define MICROBLAZE_EXCEPTION_FRAME_R16 60
#define MICROBLAZE_EXCEPTION_FRAME_R17 64
#define MICROBLAZE_EXCEPTION_FRAME_R18 68
#define MICROBLAZE_EXCEPTION_FRAME_R19 72
#define MICROBLAZE_EXCEPTION_FRAME_R20 76
#define MICROBLAZE_EXCEPTION_FRAME_R21 80
#define MICROBLAZE_EXCEPTION_FRAME_R22 84
#define MICROBLAZE_EXCEPTION_FRAME_R23 88
#define MICROBLAZE_EXCEPTION_FRAME_R24 92
#define MICROBLAZE_EXCEPTION_FRAME_R25 96
#define MICROBLAZE_EXCEPTION_FRAME_R26 100
#define MICROBLAZE_EXCEPTION_FRAME_R27 104
#define MICROBLAZE_EXCEPTION_FRAME_R28 108
#define MICROBLAZE_EXCEPTION_FRAME_R29 112
#define MICROBLAZE_EXCEPTION_FRAME_R30 116
#define MICROBLAZE_EXCEPTION_FRAME_R31 120
#define MICROBLAZE_EXCEPTION_FRAME_MSR 124
#define MICROBLAZE_EXCEPTION_FRAME_EAR 128
#define MICROBLAZE_EXCEPTION_FRAME_ESR 132
#define MICROBLAZE_EXCEPTION_FRAME_BTR 136
#define CPU_EXCEPTION_FRAME_SIZE 140
#ifndef ASM
#ifdef __cplusplus
@@ -139,8 +177,23 @@ typedef struct {
#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
#define MICROBLAZE_MSR_IE (1 << 1)
#define MICROBLAZE_MSR_EE (1 << 8)
/*
* bit definitions in the documentation are reversed for all special registers
* such that bit 0 is the most significant bit
*/
#define MICROBLAZE_MSR_VM ( 1 << 13 )
#define MICROBLAZE_MSR_UM ( 1 << 11 )
#define MICROBLAZE_MSR_PVR ( 1 << 10 )
#define MICROBLAZE_MSR_EIP ( 1 << 9 )
#define MICROBLAZE_MSR_EE ( 1 << 8 )
#define MICROBLAZE_MSR_DCE ( 1 << 7 )
#define MICROBLAZE_MSR_DZO ( 1 << 6 )
#define MICROBLAZE_MSR_ICE ( 1 << 5 )
#define MICROBLAZE_MSR_FSL ( 1 << 4 )
#define MICROBLAZE_MSR_BIP ( 1 << 3 )
#define MICROBLAZE_MSR_C ( 1 << 2 )
#define MICROBLAZE_MSR_IE ( 1 << 1 )
#define _CPU_MSR_GET( _msr_value ) \
do { \
@@ -228,8 +281,42 @@ void _CPU_Context_Initialize(
#define CPU_PER_CPU_CONTROL_SIZE 0
typedef struct {
/* TODO: enumerate registers */
uint32_t r[32];
/* r0 is unnecessary since it is always 0 */
uint32_t r1;
uint32_t r2;
uint32_t r3; /* return 1/scratch */
uint32_t r4; /* return 2/scratch */
uint32_t r5; /* param 1/scratch */
uint32_t r6; /* param 2/scratch */
uint32_t r7; /* param 3/scratch */
uint32_t r8; /* param 4/scratch */
uint32_t r9; /* param 5/scratch */
uint32_t r10; /* param 6/scratch */
uint32_t r11; /* scratch */
uint32_t r12; /* scratch */
uint32_t r13;
uint32_t *r14; /* Interrupt Link Register */
uint32_t *r15; /* Link Register */
uint32_t *r16; /* Trap/Debug Link Register */
uint32_t *r17; /* Exception Link Register */
uint32_t r18;
uint32_t r19;
uint32_t r20;
uint32_t r21;
uint32_t r22;
uint32_t r23;
uint32_t r24;
uint32_t r25;
uint32_t r26;
uint32_t r27;
uint32_t r28;
uint32_t r29;
uint32_t r30;
uint32_t r31;
uint32_t msr; /* Machine Status Register */
uint32_t *ear; /* Exception Address Register */
uint32_t esr; /* Exception Status Register */
uint32_t *btr; /* Branch Target Register */
} CPU_Exception_frame;
/* end of Priority handler macros */
@@ -246,6 +333,17 @@ void _CPU_ISR_install_vector(
CPU_ISR_handler *old_handler
);
typedef void ( *MicroBlaze_Exception_handler )( CPU_Exception_frame *ef );
void _MicroBlaze_Exception_install_handler(
MicroBlaze_Exception_handler new_handler,
MicroBlaze_Exception_handler *old_handler
);
void _MicroBlaze_Exception_handle(
CPU_Exception_frame *ef
);
void _CPU_Context_switch(
Context_Control *run,
Context_Control *heir
@@ -26,7 +26,6 @@ source:
- bsps/microblaze/microblaze_fpga/fdt/bsp_fdt.c
- bsps/microblaze/microblaze_fpga/irq/irq.c
- bsps/microblaze/microblaze_fpga/start/_exception_handler.S
- bsps/microblaze/microblaze_fpga/start/_hw_exception_handler.S
- bsps/microblaze/microblaze_fpga/start/_interrupt_handler.S
- bsps/microblaze/microblaze_fpga/start/bspreset.c
- bsps/microblaze/microblaze_fpga/start/bspstart.c