Back to home page

LXR

 
 

    


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

0001 /**
0002  * @file
0003  *
0004  * @addtogroup RTEMSScoreCPURISCV
0005  *
0006  * @brief RISC-V exception support implementation.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2018 embedded brains GmbH & Co. KG
0011 
0012  * Copyright (c) 2015 University of York.
0013  * Hesham Almatary <hesham@alumni.york.ac.uk>
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0025  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0028  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0029  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0030  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0031  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0032  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0033  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0034  * SUCH DAMAGE.
0035  */
0036 
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040 
0041 #include <rtems/asm.h>
0042 #include <rtems/score/percpu.h>
0043 
0044 PUBLIC(_RISCV_Exception_handler)
0045 
0046     .section    .text, "ax", @progbits
0047     .align  2
0048     .option arch, +zicsr
0049 
0050 TYPE_FUNC(_RISCV_Exception_handler)
0051 SYM(_RISCV_Exception_handler):
0052     addi    sp, sp, -CPU_INTERRUPT_FRAME_SIZE
0053 
0054     /* Save */
0055     SREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
0056     SREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
0057     SREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
0058     SREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
0059     csrr    a0, mcause
0060     csrr    a1, mstatus
0061     csrr    a2, mepc
0062     GET_SELF_CPU_CONTROL    s0
0063     SREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
0064 #if __riscv_flen > 0
0065     frcsr   s1
0066 #endif
0067     SREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
0068     SREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
0069     SREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
0070     SREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
0071     SREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
0072     SREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
0073     SREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
0074     SREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
0075     SREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
0076     SREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
0077     SREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
0078     SREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
0079     SREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
0080     SREG    a1, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
0081     SREG    a2, RISCV_INTERRUPT_FRAME_MEPC(sp)
0082 #if __riscv_flen > 0
0083     sw  s1, RISCV_INTERRUPT_FRAME_FCSR(sp)
0084     FSREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
0085     FSREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
0086     FSREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
0087     FSREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
0088     FSREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
0089     FSREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
0090     FSREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
0091     FSREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
0092     FSREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
0093     FSREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
0094     FSREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
0095     FSREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
0096     FSREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
0097     FSREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
0098     FSREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
0099     FSREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
0100     FSREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
0101     FSREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
0102     FSREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
0103     FSREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
0104 #endif
0105 
0106     /* Check if this is a synchronous or interrupt exception */
0107     bgez    a0, .Lsynchronous_exception
0108 
0109     /* Increment interrupt nest and thread dispatch disable level */
0110     lw  t0, PER_CPU_ISR_NEST_LEVEL(s0)
0111     lw  t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
0112     addi    t2, t0, 1
0113     addi    t1, t1, 1
0114     sw  t2, PER_CPU_ISR_NEST_LEVEL(s0)
0115     sw  t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
0116 
0117     CLEAR_RESERVATIONS  s0
0118 
0119     /*
0120      * Remember current stack pointer in non-volatile register s1.  Switch
0121      * to interrupt stack if necessary.
0122      */
0123     mv  s1, sp
0124     bnez    t0, .Linterrupt_stack_switch_done
0125     LREG    sp, PER_CPU_INTERRUPT_STACK_HIGH(s0)
0126 .Linterrupt_stack_switch_done:
0127 
0128     mv  a1, s0
0129     call    _RISCV_Interrupt_dispatch
0130 
0131     /* Load some per-CPU variables */
0132     lw  t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
0133     lbu t1, PER_CPU_DISPATCH_NEEDED(s0)
0134     lw  t2, PER_CPU_ISR_DISPATCH_DISABLE(s0)
0135     lw  t3, PER_CPU_ISR_NEST_LEVEL(s0)
0136 
0137     /* Restore stack pointer */
0138     mv  sp, s1
0139 
0140     /* Decrement levels and determine thread dispatch state */
0141     xor t1, t1, t0
0142     addi    t0, t0, -1
0143     or  t1, t1, t0
0144     or  t1, t1, t2
0145     addi    t3, t3, -1
0146 
0147     /* Store thread dispatch disable and ISR nest levels */
0148     sw  t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
0149     sw  t3, PER_CPU_ISR_NEST_LEVEL(s0)
0150 
0151     /*
0152      * Check thread dispatch necessary, ISR dispatch disable and thread
0153      * dispatch disable level.
0154      */
0155     bnez    t1, .Lthread_dispatch_done
0156 
0157 .Ldo_thread_dispatch:
0158 
0159     /* Set ISR dispatch disable and thread dispatch disable level to one */
0160     li  t0, 1
0161     sw  t0, PER_CPU_ISR_DISPATCH_DISABLE(s0)
0162     sw  t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
0163 
0164     /* Call _Thread_Do_dispatch(), this function will enable interrupts */
0165     mv  a0, s0
0166     li  a1, RISCV_MSTATUS_MIE
0167     call    _Thread_Do_dispatch
0168 
0169     /* Disable interrupts */
0170     csrrc   zero, mstatus, RISCV_MSTATUS_MIE
0171 
0172 #ifdef RTEMS_SMP
0173     GET_SELF_CPU_CONTROL    s0
0174 #endif
0175 
0176     /* Check if we have to do the thread dispatch again */
0177     lbu t0, PER_CPU_DISPATCH_NEEDED(s0)
0178     bnez    t0, .Ldo_thread_dispatch
0179 
0180     /* We are done with thread dispatching */
0181     sw  zero, PER_CPU_ISR_DISPATCH_DISABLE(s0)
0182 
0183 .Lthread_dispatch_done:
0184 
0185     /* Restore */
0186     LREG    a0, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
0187     LREG    a1, RISCV_INTERRUPT_FRAME_MEPC(sp)
0188     LREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
0189     LREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
0190     LREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
0191     LREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
0192     LREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
0193     LREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
0194     LREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
0195     LREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
0196     LREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
0197     LREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
0198     LREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
0199     LREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
0200     LREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
0201     LREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
0202     LREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
0203     LREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
0204     csrw    mstatus, a0
0205     csrw    mepc, a1
0206 #if __riscv_flen > 0
0207     lw  a0, RISCV_INTERRUPT_FRAME_FCSR(sp)
0208     FLREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
0209     FLREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
0210     FLREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
0211     FLREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
0212     FLREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
0213     FLREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
0214     FLREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
0215     FLREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
0216     FLREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
0217     FLREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
0218     FLREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
0219     FLREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
0220     FLREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
0221     FLREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
0222     FLREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
0223     FLREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
0224     FLREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
0225     FLREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
0226     FLREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
0227     FLREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
0228     fscsr   a0
0229 #endif
0230     LREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
0231     LREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
0232 
0233     addi    sp, sp, CPU_INTERRUPT_FRAME_SIZE
0234 
0235     mret
0236 
0237 .Lsynchronous_exception:
0238 
0239     SREG    a0, RISCV_EXCEPTION_FRAME_MCAUSE(sp)
0240     addi    a0, sp, CPU_INTERRUPT_FRAME_SIZE
0241     SREG    a0, RISCV_EXCEPTION_FRAME_SP(sp)
0242     SREG    gp, RISCV_EXCEPTION_FRAME_GP(sp)
0243     SREG    tp, RISCV_EXCEPTION_FRAME_TP(sp)
0244     SREG    s2, RISCV_EXCEPTION_FRAME_S2(sp)
0245     SREG    s3, RISCV_EXCEPTION_FRAME_S3(sp)
0246     SREG    s4, RISCV_EXCEPTION_FRAME_S4(sp)
0247     SREG    s5, RISCV_EXCEPTION_FRAME_S5(sp)
0248     SREG    s6, RISCV_EXCEPTION_FRAME_S6(sp)
0249     SREG    s7, RISCV_EXCEPTION_FRAME_S7(sp)
0250     SREG    s8, RISCV_EXCEPTION_FRAME_S8(sp)
0251     SREG    s9, RISCV_EXCEPTION_FRAME_S9(sp)
0252     SREG    s10, RISCV_EXCEPTION_FRAME_S10(sp)
0253     SREG    s11, RISCV_EXCEPTION_FRAME_S11(sp)
0254 #if __riscv_flen > 0
0255     FSREG   fs0, RISCV_EXCEPTION_FRAME_FS0(sp)
0256     FSREG   fs1, RISCV_EXCEPTION_FRAME_FS1(sp)
0257     FSREG   fs2, RISCV_EXCEPTION_FRAME_FS2(sp)
0258     FSREG   fs3, RISCV_EXCEPTION_FRAME_FS3(sp)
0259     FSREG   fs4, RISCV_EXCEPTION_FRAME_FS4(sp)
0260     FSREG   fs5, RISCV_EXCEPTION_FRAME_FS5(sp)
0261     FSREG   fs6, RISCV_EXCEPTION_FRAME_FS6(sp)
0262     FSREG   fs7, RISCV_EXCEPTION_FRAME_FS7(sp)
0263     FSREG   fs8, RISCV_EXCEPTION_FRAME_FS8(sp)
0264     FSREG   fs9, RISCV_EXCEPTION_FRAME_FS9(sp)
0265     FSREG   fs10, RISCV_EXCEPTION_FRAME_FS10(sp)
0266     FSREG   fs11, RISCV_EXCEPTION_FRAME_FS11(sp)
0267 #endif
0268 
0269     li  a0, 9
0270     mv  a1, sp
0271     call    _Terminate