1/* 2 * Copyright (c) 2021 Nuclei Limited. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, 5 * are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "riscv_encoding.h" 32 33#ifndef __riscv_32e 34#define portRegNum 30 35#else 36#define portRegNum 14 37#endif 38 39#define portCONTEXT_SIZE ( portRegNum * REGBYTES ) 40 41 .section .text 42 .align 4 43 44 .type ArchIntLock, %function 45 .global ArchIntLock 46ArchIntLock: 47 csrr a0, mstatus // return value 48 li t0, MSTATUS_MIE // mie 49 csrrc zero, mstatus, t0 50 ret 51 52 .type ArchIntUnLock, %function 53 .global ArchIntUnLock 54ArchIntUnLock: 55 csrr a0, mstatus // return value 56 li t0, MSTATUS_MIE // mie 57 csrrs zero, mstatus, t0 58 ret 59 60 .type ArchIntRestore, %function 61 .global ArchIntRestore 62ArchIntRestore: 63 csrw mstatus, a0 64 ret 65 66 67/* Start the first task. This also clears the bit that indicates the FPU is 68 in use in case the FPU was used before the scheduler was started - which 69 would otherwise result in the unnecessary leaving of space in the stack 70 for lazy saving of FPU registers. */ 71 .type HalStartToRun, %function 72 .global HalStartToRun 73 .align 3 74HalStartToRun: 75 /* Setup Interrupt Stack using 76 The stack that was used by main() 77 before the scheduler is started is 78 no longer required after the scheduler is started. 79 Interrupt stack pointer is stored in CSR_MSCRATCH */ 80 la t0, _sp 81 csrw CSR_MSCRATCH, t0 82 /* get stack pointer */ 83 la t0, g_losTask 84 LOAD t1, 0x0(t0) 85 LOAD sp, 0(t1) 86 //LOAD sp, 0x0(sp) /* Read sp from first TCB member */ 87 88 /* Pop PC from stack and set MEPC */ 89 LOAD t0, 0 * REGBYTES(sp) 90 csrw CSR_MEPC, t0 91 /* Pop mstatus from stack and set it */ 92 LOAD t0, (portRegNum - 1) * REGBYTES(sp) 93 csrw CSR_MSTATUS, t0 94 /* Interrupt still disable here */ 95 /* Restore Registers from Stack */ 96 LOAD x1, 1 * REGBYTES(sp) /* RA */ 97 LOAD x5, 2 * REGBYTES(sp) 98 LOAD x6, 3 * REGBYTES(sp) 99 LOAD x7, 4 * REGBYTES(sp) 100 LOAD x8, 5 * REGBYTES(sp) 101 LOAD x9, 6 * REGBYTES(sp) 102 LOAD x10, 7 * REGBYTES(sp) 103 LOAD x11, 8 * REGBYTES(sp) 104 LOAD x12, 9 * REGBYTES(sp) 105 LOAD x13, 10 * REGBYTES(sp) 106 LOAD x14, 11 * REGBYTES(sp) 107 LOAD x15, 12 * REGBYTES(sp) 108#ifndef __riscv_32e 109 LOAD x16, 13 * REGBYTES(sp) 110 LOAD x17, 14 * REGBYTES(sp) 111 LOAD x18, 15 * REGBYTES(sp) 112 LOAD x19, 16 * REGBYTES(sp) 113 LOAD x20, 17 * REGBYTES(sp) 114 LOAD x21, 18 * REGBYTES(sp) 115 LOAD x22, 19 * REGBYTES(sp) 116 LOAD x23, 20 * REGBYTES(sp) 117 LOAD x24, 21 * REGBYTES(sp) 118 LOAD x25, 22 * REGBYTES(sp) 119 LOAD x26, 23 * REGBYTES(sp) 120 LOAD x27, 24 * REGBYTES(sp) 121 LOAD x28, 25 * REGBYTES(sp) 122 LOAD x29, 26 * REGBYTES(sp) 123 LOAD x30, 27 * REGBYTES(sp) 124 LOAD x31, 28 * REGBYTES(sp) 125#endif 126 127 addi sp, sp, portCONTEXT_SIZE 128 129 mret 130 131.extern HalTaskSwitch 132.align 2 133.global eclic_msip_handler 134eclic_msip_handler: 135 addi sp, sp, -portCONTEXT_SIZE 136 STORE x1, 1 * REGBYTES(sp) /* RA */ 137 STORE x5, 2 * REGBYTES(sp) 138 STORE x6, 3 * REGBYTES(sp) 139 STORE x7, 4 * REGBYTES(sp) 140 STORE x8, 5 * REGBYTES(sp) 141 STORE x9, 6 * REGBYTES(sp) 142 STORE x10, 7 * REGBYTES(sp) 143 STORE x11, 8 * REGBYTES(sp) 144 STORE x12, 9 * REGBYTES(sp) 145 STORE x13, 10 * REGBYTES(sp) 146 STORE x14, 11 * REGBYTES(sp) 147 STORE x15, 12 * REGBYTES(sp) 148#ifndef __riscv_32e 149 STORE x16, 13 * REGBYTES(sp) 150 STORE x17, 14 * REGBYTES(sp) 151 STORE x18, 15 * REGBYTES(sp) 152 STORE x19, 16 * REGBYTES(sp) 153 STORE x20, 17 * REGBYTES(sp) 154 STORE x21, 18 * REGBYTES(sp) 155 STORE x22, 19 * REGBYTES(sp) 156 STORE x23, 20 * REGBYTES(sp) 157 STORE x24, 21 * REGBYTES(sp) 158 STORE x25, 22 * REGBYTES(sp) 159 STORE x26, 23 * REGBYTES(sp) 160 STORE x27, 24 * REGBYTES(sp) 161 STORE x28, 25 * REGBYTES(sp) 162 STORE x29, 26 * REGBYTES(sp) 163 STORE x30, 27 * REGBYTES(sp) 164 STORE x31, 28 * REGBYTES(sp) 165#endif 166 /* Push mstatus to stack */ 167 csrr t0, CSR_MSTATUS 168 STORE t0, (portRegNum - 1) * REGBYTES(sp) 169 170 /* Push additional registers */ 171 172 /* Store sp to task stack */ 173 la t0, g_losTask 174 LOAD t0, 0(t0) 175 STORE sp, 0(t0) 176 177 csrr t0, CSR_MEPC 178 STORE t0, 0(sp) 179 180 /* Switch task context */ 181 jal HalTaskSwitch 182 /* Load new task */ 183 la t0, g_losTask 184 LOAD t0, 0(t0) 185 LOAD sp, 0x0(t0) /* Read sp from first TCB member */ 186 187 /* Pop PC from stack and set MEPC */ 188 LOAD t0, 0 * REGBYTES(sp) 189 csrw CSR_MEPC, t0 190 /* Pop additional registers */ 191 192 /* Pop mstatus from stack and set it */ 193 LOAD t0, (portRegNum - 1) * REGBYTES(sp) 194 csrw CSR_MSTATUS, t0 195 /* Interrupt still disable here */ 196 /* Restore Registers from Stack */ 197 LOAD x1, 1 * REGBYTES(sp) /* RA */ 198 LOAD x5, 2 * REGBYTES(sp) 199 LOAD x6, 3 * REGBYTES(sp) 200 LOAD x7, 4 * REGBYTES(sp) 201 LOAD x8, 5 * REGBYTES(sp) 202 LOAD x9, 6 * REGBYTES(sp) 203 LOAD x10, 7 * REGBYTES(sp) 204 LOAD x11, 8 * REGBYTES(sp) 205 LOAD x12, 9 * REGBYTES(sp) 206 LOAD x13, 10 * REGBYTES(sp) 207 LOAD x14, 11 * REGBYTES(sp) 208 LOAD x15, 12 * REGBYTES(sp) 209#ifndef __riscv_32e 210 LOAD x16, 13 * REGBYTES(sp) 211 LOAD x17, 14 * REGBYTES(sp) 212 LOAD x18, 15 * REGBYTES(sp) 213 LOAD x19, 16 * REGBYTES(sp) 214 LOAD x20, 17 * REGBYTES(sp) 215 LOAD x21, 18 * REGBYTES(sp) 216 LOAD x22, 19 * REGBYTES(sp) 217 LOAD x23, 20 * REGBYTES(sp) 218 LOAD x24, 21 * REGBYTES(sp) 219 LOAD x25, 22 * REGBYTES(sp) 220 LOAD x26, 23 * REGBYTES(sp) 221 LOAD x27, 24 * REGBYTES(sp) 222 LOAD x28, 25 * REGBYTES(sp) 223 LOAD x29, 26 * REGBYTES(sp) 224 LOAD x30, 27 * REGBYTES(sp) 225 LOAD x31, 28 * REGBYTES(sp) 226#endif 227 228 addi sp, sp, portCONTEXT_SIZE 229 mret 230