/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup RTEMSScoreCPUMicroBlaze * * @brief MicroBlaze architecture support implementation */ /* * Copyright (c) 2015, Hesham Almatary * Copyright (C) 2021 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include void _CPU_Initialize( void ) { } void _CPU_Context_Initialize( Context_Control *context, void *stack_area_begin, size_t stack_area_size, uint32_t new_level, void (*entry_point)( void ), bool is_fp, void *tls_area ) { uint32_t stack = (uint32_t) stack_area_begin; uint32_t stack_high = stack + stack_area_size; memset( context, 0, sizeof(*context) ) ; context->r1 = stack_high - 64; context->r15 = (uint32_t) entry_point; uint32_t msr; _CPU_MSR_GET( msr ); context->rmsr = msr; if ( tls_area != NULL ) { context->thread_pointer = _TLS_Initialize_area( tls_area ); } } 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 ) { uint32_t microblaze_switch_reg; _CPU_MSR_GET( microblaze_switch_reg ); if ( level == 0 ) { microblaze_switch_reg |= MICROBLAZE_MSR_IE; } else { microblaze_switch_reg &= ~(MICROBLAZE_MSR_IE); } _CPU_MSR_SET( microblaze_switch_reg ); } uint32_t _CPU_ISR_Get_level( void ) { uint32_t level; _CPU_MSR_GET( level ); /* This is unique. The MSR register contains an interrupt enable flag where * most other architectures have an interrupt disable flag. */ return ( level & MICROBLAZE_MSR_IE ) == 0; } void _CPU_ISR_install_vector( uint32_t vector, CPU_ISR_handler new_handler, CPU_ISR_handler *old_handler ) { *old_handler = _ISR_Vector_table[ vector ]; _ISR_Vector_table[ vector ] = new_handler; } 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 ); } MicroBlaze_Exception_handler installed_debug_handler = NULL; void _MicroBlaze_Debug_install_handler( MicroBlaze_Exception_handler new_handler, MicroBlaze_Exception_handler *old_handler ) { if ( old_handler != NULL ) { *old_handler = installed_debug_handler; } installed_debug_handler = new_handler; } void _MicroBlaze_Debug_handle( CPU_Exception_frame *ef ) { /* BiP is not set for software debug events, set it here */ ef->msr |= MICROBLAZE_MSR_BIP; if ( installed_debug_handler != NULL ) { installed_debug_handler( ef ); } rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) ef ); }