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  *  @brief MIPS CPU Dependent Source
0007  */
0008 
0009 /*
0010  * MIPS CPU Dependent Source
0011  *
0012  *  2002:       Greg Menke (gregory.menke@gsfc.nasa.gov)
0013  *      Overhauled interrupt level and interrupt enable/disable code
0014  *      to more exactly support MIPS.  Our mods were for MIPS1 processors
0015  *      MIPS3 ports are affected, though apps written to the old behavior
0016  *      should still work OK.
0017  *
0018  *  Conversion to MIPS port by Alan Cudmore <alanc@linuxstart.com> and
0019  *           Joel Sherrill <joel@OARcorp.com>.
0020  *
0021  *    These changes made the code conditional on standard cpp predefines,
0022  *    merged the mips1 and mips3 code sequences as much as possible,
0023  *    and moved some of the assembly code to C.  Alan did much of the
0024  *    initial analysis and rework.  Joel took over from there and
0025  *    wrote the JMR3904 BSP so this could be tested.  Joel also
0026  *    added the new interrupt vectoring support in libcpu and
0027  *    tried to better support the various interrupt controllers.
0028  *
0029  *  Original MIP64ORION port by Craig Lebakken <craigl@transition.com>
0030  *           COPYRIGHT (c) 1996 by Transition Networks Inc.
0031  *
0032  *         To anyone who acknowledges that this file is provided "AS IS"
0033  *         without any express or implied warranty:
0034  *             permission to use, copy, modify, and distribute this file
0035  *             for any purpose is hereby granted without fee, provided that
0036  *             the above copyright notice and this notice appears in all
0037  *             copies, and that the name of Transition Networks not be used in
0038  *             advertising or publicity pertaining to distribution of the
0039  *             software without specific, written prior permission.
0040  *             Transition Networks makes no representations about the
0041  *             suitability of this software for any purpose.
0042  *
0043  *  COPYRIGHT (c) 1989-2012.
0044  *  On-Line Applications Research Corporation (OAR).
0045  *
0046  * Redistribution and use in source and binary forms, with or without
0047  * modification, are permitted provided that the following conditions
0048  * are met:
0049  * 1. Redistributions of source code must retain the above copyright
0050  *    notice, this list of conditions and the following disclaimer.
0051  * 2. Redistributions in binary form must reproduce the above copyright
0052  *    notice, this list of conditions and the following disclaimer in the
0053  *    documentation and/or other materials provided with the distribution.
0054  *
0055  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0056  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0057  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0058  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0059  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0060  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0061  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0062  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0063  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0064  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0065  * POSSIBILITY OF SUCH DAMAGE.
0066  */
0067 
0068 #ifdef HAVE_CONFIG_H
0069 #include "config.h"
0070 #endif
0071 
0072 #include <rtems/score/cpuimpl.h>
0073 #include <rtems/score/isr.h>
0074 
0075 #if CPU_HARDWARE_FP
0076 Context_Control_fp _CPU_Null_fp_context;
0077 #endif
0078 
0079 /*
0080 ** Exception stack frame pointer used in cpu_asm to pass the exception stack frame
0081 ** address to the context switch code.
0082 */
0083 #if (__mips == 1) || (__mips == 32)
0084 typedef uint32_t ESF_PTR_TYPE;
0085 #elif (__mips == 3)
0086 typedef uint64_t ESF_PTR_TYPE;
0087 #else
0088 #error "unknown MIPS ISA"
0089 #endif
0090 
0091 ESF_PTR_TYPE __exceptionStackFrame = 0;
0092 /*  _CPU_Initialize
0093  *
0094  *  This routine performs processor dependent initialization.
0095  *
0096  *    thread_dispatch - address of dispatching routine
0097  */
0098 
0099 void _CPU_Initialize(void)
0100 {
0101   /*
0102    *  If there is not an easy way to initialize the FP context
0103    *  during Context_Initialize, then it is usually easier to
0104    *  save an "uninitialized" FP context here and copy it to
0105    *  the task's during Context_Initialize.
0106    */
0107 
0108 #if CPU_HARDWARE_FP
0109   /* FP context initialization support goes here */
0110   _CPU_Null_fp_context.fpcs = 0x1000000;    /* Set FS flag in floating point coprocessor
0111                            control register to prevent underflow and
0112                            inexact exceptions */
0113 #endif
0114 }
0115 
0116 uint32_t   _CPU_ISR_Get_level( void )
0117 {
0118   unsigned int sr;
0119 
0120   mips_get_sr(sr);
0121 
0122   /* printf("current sr=%08X, ",sr); */
0123 
0124 #if (__mips == 3) || (__mips == 32)
0125 /* IE bit and shift down hardware ints into bits 1 thru 6 */
0126   sr = (sr & SR_IE) | ((sr & mips_interrupt_mask()) >> 9);
0127 
0128 #elif __mips == 1
0129 /* IEC bit and shift down hardware ints into bits 1 thru 6 */
0130   sr = (sr & SR_IEC) | ((sr & mips_interrupt_mask()) >> 9);
0131 
0132 #else
0133 #error "CPU ISR level: unknown MIPS level for SR handling"
0134 #endif
0135   return sr;
0136 }
0137 void _CPU_ISR_Set_level( uint32_t   new_level )
0138 {
0139   unsigned int sr, srbits;
0140 
0141   /*
0142   ** mask off the int level bits only so we can
0143   ** preserve software int settings and FP enable
0144   ** for this thread.  Note we don't force software ints
0145   ** enabled when changing level, they were turned on
0146   ** when this task was created, but may have been turned
0147   ** off since, so we'll just leave them alone.
0148   */
0149 
0150   new_level &= 0xff;
0151 
0152   mips_get_sr(sr);
0153 
0154 #if (__mips == 3) || (__mips == 32)
0155   mips_set_sr( (sr & ~SR_IE) );                 /* first disable ie bit (recommended) */
0156 
0157    srbits = sr & ~(0xfc00 | SR_IE);
0158 
0159    sr = srbits | ((new_level==0)? (mips_interrupt_mask() | SR_IE): \
0160          (((new_level<<9) & mips_interrupt_mask()) | \
0161                    ((new_level & 1)?SR_IE:0)));
0162 /*
0163   if ( (new_level & SR_EXL) == (sr & SR_EXL) )
0164     return;
0165 
0166   if ( (new_level & SR_EXL) == 0 ) {
0167     sr &= ~SR_EXL;                    * clear the EXL bit *
0168     mips_set_sr(sr);
0169   } else {
0170 
0171     sr |= SR_EXL|SR_IE;              * enable exception level *
0172     mips_set_sr(sr);                 * first disable ie bit (recommended) *
0173   }
0174 */
0175 
0176 #elif __mips == 1
0177   mips_set_sr( (sr & ~SR_IEC) );
0178   srbits = sr & ~(0xfc00 | SR_IEC);
0179   sr = srbits | ((new_level==0)?0xfc01:( ((new_level<<9) & 0xfc00) | \
0180                                          (new_level & SR_IEC)));
0181 #else
0182 #error "CPU ISR level: unknown MIPS level for SR handling"
0183 #endif
0184   mips_set_sr( sr );
0185 }
0186 
0187 void _CPU_Context_Initialize(
0188   Context_Control  *the_context,
0189   uintptr_t        *stack_base,
0190   uint32_t          size,
0191   uint32_t          new_level,
0192   void             *entry_point,
0193   bool              is_fp,
0194   void             *tls_area
0195 )
0196 {
0197   uintptr_t             stack_tmp;
0198   __MIPS_REGISTER_TYPE  intlvl = new_level & 0xff;
0199   __MIPS_REGISTER_TYPE  c0_sr;
0200 
0201   stack_tmp  = (uintptr_t)stack_base;
0202   stack_tmp += ((size) - CPU_STACK_ALIGNMENT);
0203   stack_tmp &= (__MIPS_REGISTER_TYPE) ~(CPU_STACK_ALIGNMENT - 1);
0204 
0205   the_context->sp = (__MIPS_REGISTER_TYPE) stack_tmp;
0206   the_context->fp = (__MIPS_REGISTER_TYPE) stack_tmp;
0207   the_context->ra = (__MIPS_REGISTER_TYPE) (uintptr_t)entry_point;
0208 
0209   c0_sr =
0210     ((intlvl==0)? (mips_interrupt_mask() | 0x300 | _INTON):
0211       ( ((intlvl<<9) & mips_interrupt_mask()) | 0x300 |
0212       ((intlvl & 1)?_INTON:0)) ) |
0213       SR_CU0 | _EXTRABITS;
0214 #if MIPS_HAS_FPU == 1
0215   if ( is_fp ) {
0216     c0_sr |= SR_CU1;
0217   }
0218 #endif
0219   the_context->c0_sr = c0_sr;
0220 }
0221 /*
0222  *  _CPU_Internal_threads_Idle_thread_body
0223  *
0224  *  NOTES:
0225  *
0226  *  1. This is the same as the regular CPU independent algorithm.
0227  *
0228  *  2. If you implement this using a "halt", "idle", or "shutdown"
0229  *     instruction, then don't forget to put it in an infinite loop.
0230  *
0231  *  3. Be warned. Some processors with onboard DMA have been known
0232  *     to stop the DMA if the CPU were put in IDLE mode.  This might
0233  *     also be a problem with other on-chip peripherals.  So use this
0234  *     hook with caution.
0235  */
0236 
0237 void *_CPU_Thread_Idle_body( uintptr_t ignored )
0238 {
0239 #if (__mips == 3) || (__mips == 32)
0240    for( ; ; )
0241      __asm__ volatile("wait"); /* use wait to enter low power mode */
0242 #elif __mips == 1
0243    for( ; ; )
0244      ;
0245 #else
0246 #error "IDLE: __mips not set to 1 or 3"
0247 #endif
0248 }