1/* 2 * Copyright 2018, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13/* 14 * 15 * Copyright 2016, 2017 Hesham Almatary, Data61/CSIRO <hesham.almatary@data61.csiro.au> 16 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com> 17 */ 18 19#include <config.h> 20#include <model/statedata.h> 21#include <arch/fastpath/fastpath.h> 22#include <arch/kernel/traps.h> 23#include <machine/debug.h> 24#include <api/syscall.h> 25#include <util.h> 26#include <arch/machine/hardware.h> 27 28#include <benchmark/benchmark_track.h> 29#include <benchmark/benchmark_utilisation.h> 30 31/** DONT_TRANSLATE */ 32void VISIBLE NORETURN restore_user_context(void) 33{ 34 word_t cur_thread_reg = (word_t) NODE_STATE(ksCurThread)->tcbArch.tcbContext.registers; 35 36 c_exit_hook(); 37 38 NODE_UNLOCK_IF_HELD; 39 40 asm volatile( 41 "mv t0, %[cur_thread] \n" 42 LOAD_S " ra, (0*%[REGSIZE])(t0) \n" 43 LOAD_S " sp, (1*%[REGSIZE])(t0) \n" 44 LOAD_S " gp, (2*%[REGSIZE])(t0) \n" 45 /* skip tp */ 46 /* skip x5/t0 */ 47 LOAD_S " t2, (6*%[REGSIZE])(t0) \n" 48 LOAD_S " s0, (7*%[REGSIZE])(t0) \n" 49 LOAD_S " s1, (8*%[REGSIZE])(t0) \n" 50 LOAD_S " a0, (9*%[REGSIZE])(t0) \n" 51 LOAD_S " a1, (10*%[REGSIZE])(t0) \n" 52 LOAD_S " a2, (11*%[REGSIZE])(t0) \n" 53 LOAD_S " a3, (12*%[REGSIZE])(t0) \n" 54 LOAD_S " a4, (13*%[REGSIZE])(t0) \n" 55 LOAD_S " a5, (14*%[REGSIZE])(t0) \n" 56 LOAD_S " a6, (15*%[REGSIZE])(t0) \n" 57 LOAD_S " a7, (16*%[REGSIZE])(t0) \n" 58 LOAD_S " s2, (17*%[REGSIZE])(t0) \n" 59 LOAD_S " s3, (18*%[REGSIZE])(t0) \n" 60 LOAD_S " s4, (19*%[REGSIZE])(t0) \n" 61 LOAD_S " s5, (20*%[REGSIZE])(t0) \n" 62 LOAD_S " s6, (21*%[REGSIZE])(t0) \n" 63 LOAD_S " s7, (22*%[REGSIZE])(t0) \n" 64 LOAD_S " s8, (23*%[REGSIZE])(t0) \n" 65 LOAD_S " s9, (24*%[REGSIZE])(t0) \n" 66 LOAD_S " s10, (25*%[REGSIZE])(t0)\n" 67 LOAD_S " s11, (26*%[REGSIZE])(t0)\n" 68 LOAD_S " t3, (27*%[REGSIZE])(t0) \n" 69 LOAD_S " t4, (28*%[REGSIZE])(t0) \n" 70 LOAD_S " t5, (29*%[REGSIZE])(t0) \n" 71 LOAD_S " t6, (30*%[REGSIZE])(t0) \n" 72 /* Get next restored tp */ 73 LOAD_S " t1, (3*%[REGSIZE])(t0) \n" 74 /* get restored tp */ 75 "add tp, t1, x0 \n" 76 /* get sepc */ 77 LOAD_S " t1, (34*%[REGSIZE])(t0)\n" 78 "csrw sepc, t1 \n" 79 80 /* Write back sscratch with cur_thread_reg to get it back on the next trap entry */ 81 "csrw sscratch, t0 \n" 82 83 LOAD_S " t1, (32*%[REGSIZE])(t0) \n" 84 "csrw sstatus, t1\n" 85 86 LOAD_S " t1, (5*%[REGSIZE])(t0) \n" 87 LOAD_S " t0, (4*%[REGSIZE])(t0) \n" 88 "sret" 89 : /* no output */ 90 : [REGSIZE] "i" (sizeof(word_t)), 91 [cur_thread] "r" (cur_thread_reg) 92 : "memory" 93 ); 94 95 UNREACHABLE(); 96} 97 98void VISIBLE NORETURN 99c_handle_interrupt(void) 100{ 101 NODE_LOCK_IRQ; 102 103 c_entry_hook(); 104 105 handleInterruptEntry(); 106 107 restore_user_context(); 108 UNREACHABLE(); 109} 110 111void VISIBLE NORETURN 112c_handle_exception(void) 113{ 114 NODE_LOCK_SYS; 115 116 c_entry_hook(); 117 118 handle_exception(); 119 120 restore_user_context(); 121 UNREACHABLE(); 122} 123 124void NORETURN 125slowpath(syscall_t syscall) 126{ 127 /* check for undefined syscall */ 128 if (unlikely(syscall < SYSCALL_MIN || syscall > SYSCALL_MAX)) { 129 handleUnknownSyscall(syscall); 130 } else { 131 handleSyscall(syscall); 132 } 133 134 restore_user_context(); 135 UNREACHABLE(); 136} 137 138void VISIBLE NORETURN 139c_handle_syscall(word_t cptr, word_t msgInfo, word_t unused1, word_t unused2, word_t unused3, word_t unused4, word_t unused5, syscall_t syscall) 140{ 141 NODE_LOCK_SYS; 142 143 c_entry_hook(); 144 145#ifdef CONFIG_FASTPATH 146 if (syscall == (syscall_t)SysCall) { 147 fastpath_call(cptr, msgInfo); 148 UNREACHABLE(); 149 } else if (syscall == (syscall_t)SysReplyRecv) { 150 fastpath_reply_recv(cptr, msgInfo); 151 UNREACHABLE(); 152 } 153#endif /* CONFIG_FASTPATH */ 154 slowpath(syscall); 155 UNREACHABLE(); 156} 157