Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:24

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreCPUMicroBlaze
0007  *
0008  * @brief MicroBlaze exception extensions implementation
0009  */
0010 
0011 /*
0012  * Copyright (C) 2022 On-Line Applications Research Corporation (OAR)
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <rtems/fatal.h>
0041 #include <rtems/score/threadimpl.h>
0042 
0043 RTEMS_NO_RETURN void _CPU_Exception_resume( CPU_Exception_frame *frame )
0044 {
0045   /* Break in progress */
0046   if ( ( frame->msr & MICROBLAZE_MSR_BIP ) != 0 ) {
0047     _MicroBlaze_Exception_resume_from_break( frame );
0048   }
0049 
0050   /* Exception in progress */
0051   if ( ( frame->msr & MICROBLAZE_MSR_EIP ) != 0 ) {
0052     _MicroBlaze_Exception_resume_from_exception( frame );
0053   }
0054 
0055   /* Execution should never reach this point */
0056   rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) frame );
0057 }
0058 
0059 void _CPU_Exception_disable_thread_dispatch( void )
0060 {
0061   Per_CPU_Control *cpu_self = _Per_CPU_Get();
0062 
0063   /* Increment interrupt nest and thread dispatch disable level */
0064   ++cpu_self->thread_dispatch_disable_level;
0065   ++cpu_self->isr_nest_level;
0066 }
0067 
0068 /* -1 means not mappable/recoverable */
0069 int _CPU_Exception_frame_get_signal( CPU_Exception_frame *ef )
0070 {
0071   uint32_t EC = ef->esr & MICROBLAZE_ESR_EC_MASK;
0072 
0073   /* Break in progress */
0074   if ( ( ef->msr & MICROBLAZE_MSR_BIP ) != 0 ) {
0075     return -1;
0076   }
0077 
0078   switch ( EC ) {
0079    case 0x0:  /* Stream */
0080    case 0x7:  /* Privileged or Stack Protection */
0081      return -1;
0082 
0083    case 0x5:  /* Divide */
0084    case 0x6:  /* FPU */
0085      return SIGFPE;
0086 
0087    case 0x3:  /* Instruction Abort */
0088    case 0x4:  /* Data Abort */
0089      return SIGSEGV;
0090 
0091    case 0x1:  /* Unaligned access */
0092    case 0x2:  /* Illegal op-code */
0093    default:
0094      return SIGILL;
0095   }
0096 }
0097 
0098 void _CPU_Exception_frame_set_resume( CPU_Exception_frame *ef, void *address )
0099 {
0100   /* Break in progress */
0101   if ( ( ef->msr & MICROBLAZE_MSR_BIP ) != 0 ) {
0102     ef->r16 = address;
0103     return;
0104   }
0105 
0106   /* Exception in progress */
0107   if ( ( ef->msr & MICROBLAZE_MSR_EIP ) != 0 ) {
0108     ef->r17 = address;
0109     return;
0110   }
0111 
0112   Per_CPU_Control *cpu_self = _Per_CPU_Get();
0113 
0114   /* Interrupt in progress must be determined by stack pointer location */
0115   if (
0116     ef->r1 >= (uint32_t) cpu_self->interrupt_stack_low
0117     && ef->r1 < (uint32_t) cpu_self->interrupt_stack_high
0118   ) {
0119     ef->r14 = address;
0120     return;
0121   }
0122 
0123   /* Default to normal link register */
0124   ef->r15 = address;
0125 }
0126 
0127 /*
0128  * This returns the target return address, not necessarily the address of the
0129  * instruction that caused exception. These are the same if it's a MMU exception
0130  * and the BTR overrides the return address if the exception occurred in a delay
0131  * slot. */
0132 uint32_t *_MicroBlaze_Get_return_address( CPU_Exception_frame *ef )
0133 {
0134   /* Break in progress */
0135   if ( ( ef->msr & MICROBLAZE_MSR_BIP ) != 0 ) {
0136     return ef->r16;
0137   }
0138 
0139   /* Exception in progress */
0140   if ( ( ef->msr & MICROBLAZE_MSR_EIP ) != 0 ) {
0141     if ( ( ef->esr & MICROBLAZE_ESR_DS ) != 0 ) {
0142       return ef->btr;
0143     }
0144 
0145     return ef->r17;
0146   }
0147 
0148   Per_CPU_Control *cpu_self = _Per_CPU_Get();
0149 
0150   /* Interrupt in progress must be determined by stack pointer location */
0151   if (
0152     ef->r1 >= (uint32_t) cpu_self->interrupt_stack_low
0153     && ef->r1 < (uint32_t) cpu_self->interrupt_stack_high
0154   ) {
0155     return ef->r14;
0156   }
0157 
0158   /* Default to normal link register */
0159   return ef->r15;
0160 }
0161 
0162 /*
0163  * This can only change the resume address in the case of an exception in a
0164  * branch delay slot instruction.
0165  */
0166 void _CPU_Exception_frame_make_resume_next_instruction(
0167   CPU_Exception_frame *ef
0168 )
0169 {
0170   uintptr_t ret_addr = (uintptr_t) _MicroBlaze_Get_return_address( ef );
0171 
0172   _CPU_Exception_frame_set_resume( ef, (uint32_t *) ret_addr );
0173 }