Back to home page

LXR

 
 

    


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

0001 /*
0002  * Copyright (c) 2018 embedded brains GmbH & Co. KG
0003  *
0004  * Copyright (c) 2015 University of York.
0005  * Hesham ALmatary <hesham@alumni.york.ac.uk>
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0020  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0021  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0022  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0023  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0024  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0025  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0026  * SUCH DAMAGE.
0027  */
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #include <rtems/asm.h>
0034 #include <rtems/score/percpu.h>
0035 
0036     .section    .text, "ax", @progbits
0037     .align  2
0038     .option arch, +zicsr
0039 
0040 PUBLIC(_CPU_Context_switch)
0041 PUBLIC(_CPU_Context_switch_no_return)
0042 PUBLIC(_CPU_Context_restore)
0043 #ifdef RTEMS_SMP
0044 PUBLIC(_RISCV_Start_multitasking)
0045 #endif
0046 
0047 SYM(_CPU_Context_switch):
0048 SYM(_CPU_Context_switch_no_return):
0049     GET_SELF_CPU_CONTROL    a2
0050     lw  a3, PER_CPU_ISR_DISPATCH_DISABLE(a2)
0051 
0052 #if __riscv_flen > 0
0053     frcsr   a4
0054 #endif
0055 
0056     SREG    ra, RISCV_CONTEXT_RA(a0)
0057     SREG    sp, RISCV_CONTEXT_SP(a0)
0058     SREG    s0, RISCV_CONTEXT_S0(a0)
0059     SREG    s1, RISCV_CONTEXT_S1(a0)
0060     SREG    s2, RISCV_CONTEXT_S2(a0)
0061     SREG    s3, RISCV_CONTEXT_S3(a0)
0062     SREG    s4, RISCV_CONTEXT_S4(a0)
0063     SREG    s5, RISCV_CONTEXT_S5(a0)
0064     SREG    s6, RISCV_CONTEXT_S6(a0)
0065     SREG    s7, RISCV_CONTEXT_S7(a0)
0066     SREG    s8, RISCV_CONTEXT_S8(a0)
0067     SREG    s9, RISCV_CONTEXT_S9(a0)
0068     SREG    s10, RISCV_CONTEXT_S10(a0)
0069     SREG    s11, RISCV_CONTEXT_S11(a0)
0070 
0071 #if __riscv_flen > 0
0072     sw  a4, RISCV_CONTEXT_FCSR(a0)
0073     FSREG   fs0, RISCV_CONTEXT_FS0(a0)
0074     FSREG   fs1, RISCV_CONTEXT_FS1(a0)
0075     FSREG   fs2, RISCV_CONTEXT_FS2(a0)
0076     FSREG   fs3, RISCV_CONTEXT_FS3(a0)
0077     FSREG   fs4, RISCV_CONTEXT_FS4(a0)
0078     FSREG   fs5, RISCV_CONTEXT_FS5(a0)
0079     FSREG   fs6, RISCV_CONTEXT_FS6(a0)
0080     FSREG   fs7, RISCV_CONTEXT_FS7(a0)
0081     FSREG   fs8, RISCV_CONTEXT_FS8(a0)
0082     FSREG   fs9, RISCV_CONTEXT_FS9(a0)
0083     FSREG   fs10, RISCV_CONTEXT_FS10(a0)
0084     FSREG   fs11, RISCV_CONTEXT_FS11(a0)
0085 #endif
0086 
0087     sw  a3, RISCV_CONTEXT_ISR_DISPATCH_DISABLE(a0)
0088 
0089 #ifdef RTEMS_SMP
0090     /*
0091      * The executing thread no longer executes on this processor.  Switch
0092      * the stack to the temporary interrupt stack of this processor.  Mark
0093      * the context of the executing thread as not executing.
0094      */
0095     addi    sp, a2, PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE
0096     amoswap.w.rl    zero, zero, RISCV_CONTEXT_IS_EXECUTING(a0)
0097 
0098 .Ltry_update_is_executing:
0099 
0100     /* Try to update the is executing indicator of the heir context */
0101     li  a3, 1
0102     amoswap.w.aq    a3, a3, RISCV_CONTEXT_IS_EXECUTING(a1)
0103     bnez    a3, .Lcheck_is_executing
0104 #endif
0105 
0106 .Lrestore:
0107 
0108     lw  a3, RISCV_CONTEXT_ISR_DISPATCH_DISABLE(a1)
0109 
0110     LREG    ra, RISCV_CONTEXT_RA(a1)
0111     LREG    sp, RISCV_CONTEXT_SP(a1)
0112     LREG    tp, RISCV_CONTEXT_TP(a1)
0113     LREG    s0, RISCV_CONTEXT_S0(a1)
0114     LREG    s1, RISCV_CONTEXT_S1(a1)
0115     LREG    s2, RISCV_CONTEXT_S2(a1)
0116     LREG    s3, RISCV_CONTEXT_S3(a1)
0117     LREG    s4, RISCV_CONTEXT_S4(a1)
0118     LREG    s5, RISCV_CONTEXT_S5(a1)
0119     LREG    s6, RISCV_CONTEXT_S6(a1)
0120     LREG    s7, RISCV_CONTEXT_S7(a1)
0121     LREG    s8, RISCV_CONTEXT_S8(a1)
0122     LREG    s9, RISCV_CONTEXT_S9(a1)
0123     LREG    s10, RISCV_CONTEXT_S10(a1)
0124     LREG    s11, RISCV_CONTEXT_S11(a1)
0125 
0126 #if __riscv_flen > 0
0127     lw  a4, RISCV_CONTEXT_FCSR(a1)
0128     FLREG   fs0, RISCV_CONTEXT_FS0(a1)
0129     FLREG   fs1, RISCV_CONTEXT_FS1(a1)
0130     FLREG   fs2, RISCV_CONTEXT_FS2(a1)
0131     FLREG   fs3, RISCV_CONTEXT_FS3(a1)
0132     FLREG   fs4, RISCV_CONTEXT_FS4(a1)
0133     FLREG   fs5, RISCV_CONTEXT_FS5(a1)
0134     FLREG   fs6, RISCV_CONTEXT_FS6(a1)
0135     FLREG   fs7, RISCV_CONTEXT_FS7(a1)
0136     FLREG   fs8, RISCV_CONTEXT_FS8(a1)
0137     FLREG   fs9, RISCV_CONTEXT_FS9(a1)
0138     FLREG   fs10, RISCV_CONTEXT_FS10(a1)
0139     FLREG   fs11, RISCV_CONTEXT_FS11(a1)
0140     fscsr   a4
0141 #endif
0142 
0143     sw  a3, PER_CPU_ISR_DISPATCH_DISABLE(a2)
0144 
0145     CLEAR_RESERVATIONS  a2
0146 
0147     ret
0148 
0149 SYM(_CPU_Context_restore):
0150     mv  a1, a0
0151     GET_SELF_CPU_CONTROL    a2
0152     j   .Lrestore
0153 
0154 #ifdef RTEMS_SMP
0155 .Lcheck_is_executing:
0156 
0157     /* Check the is executing indicator of the heir context */
0158     lw  a3, RISCV_CONTEXT_IS_EXECUTING(a1)
0159     beqz    a3, .Ltry_update_is_executing
0160 
0161     /* We may have a new heir */
0162 
0163     /* Read the executing and heir */
0164     LREG    a4, PER_CPU_OFFSET_EXECUTING(a2)
0165     LREG    a5, PER_CPU_OFFSET_HEIR(a2)
0166 
0167     /*
0168      * Update the executing only if necessary to avoid cache line
0169      * monopolization.
0170      */
0171     beq a4, a5, .Ltry_update_is_executing
0172 
0173     /* Calculate the heir context pointer */
0174     sub a4, a1, a4
0175     add a1, a5, a4
0176 
0177     /* Update the executing */
0178     sw  a5, PER_CPU_OFFSET_EXECUTING(a2)
0179 
0180     j   .Ltry_update_is_executing
0181 
0182 SYM(_RISCV_Start_multitasking):
0183     mv  a1, a0
0184     GET_SELF_CPU_CONTROL    a2
0185 
0186     /* Switch the stack to the temporary interrupt stack of this processor */
0187     addi    sp, a2, PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE
0188 
0189     /* Enable interrupts */
0190     csrrs   zero, mstatus, RISCV_MSTATUS_MIE
0191 
0192     j   .Ltry_update_is_executing
0193 #endif