entry.S (3068B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 #include <hw/riscv.h> 5 #include <xos/status.h> 6 7 .global trap_entry 8 trap_entry: 9 // swap the user sp with the kernel sp 10 // stored in SSCRATCH 11 csrrw sp, sscratch, sp 12 13 // reserve stack space for a full eframe_t 14 addi sp, sp, - (32 * 4) 15 16 // save caller-save registers 17 sw ra, 0x00(sp) 18 sw t0, 0x04(sp) 19 sw t1, 0x08(sp) 20 sw t2, 0x0C(sp) 21 sw t3, 0x10(sp) 22 sw t4, 0x14(sp) 23 sw t5, 0x18(sp) 24 sw t6, 0x1C(sp) 25 sw a0, 0x20(sp) 26 sw a1, 0x24(sp) 27 sw a2, 0x28(sp) 28 sw a3, 0x2C(sp) 29 sw a4, 0x30(sp) 30 sw a5, 0x34(sp) 31 sw a6, 0x38(sp) 32 sw a7, 0x3C(sp) 33 34 // save user pc which hw stashed in SEPC 35 // and user sp which we stashed in SSCRATCH 36 csrr t1, sepc 37 csrr t2, sscratch 38 sw t1, 0x40(sp) 39 sw t2, 0x44(sp) 40 41 // save callee-save registers 42 sw gp, 0x48(sp) 43 sw tp, 0x4C(sp) 44 sw s0, 0x50(sp) 45 sw s1, 0x54(sp) 46 sw s2, 0x58(sp) 47 sw s3, 0x5C(sp) 48 sw s4, 0x60(sp) 49 sw s5, 0x64(sp) 50 sw s6, 0x68(sp) 51 sw s7, 0x6C(sp) 52 sw s8, 0x70(sp) 53 sw s9, 0x74(sp) 54 sw s10, 0x78(sp) 55 sw s11, 0x7C(sp) 56 57 // setup kernel thread pointer 58 // thread struct is at top of kstack 59 addi tp, sp, (32 * 4) 60 61 // if the scause high bit is clear, it is an exception 62 csrr t1, scause 63 bge t1, zero, exception_entry 64 65 // otherwise it is an interrupt, call interrupt_handler() 66 jal interrupt_handler 67 68 .globl trap_exit 69 trap_exit: 70 // TODO: check tp->reschedule flag 71 72 // restore initial kernel sp to sscratch 73 // (which is the same as the kernel tp) 74 csrw sscratch, tp 75 76 // restore callee-save registers 77 lw gp, 0x48(sp) 78 lw tp, 0x4C(sp) 79 lw s0, 0x50(sp) 80 lw s1, 0x54(sp) 81 lw s2, 0x58(sp) 82 lw s3, 0x5C(sp) 83 lw s4, 0x60(sp) 84 lw s5, 0x64(sp) 85 lw s6, 0x68(sp) 86 lw s7, 0x6C(sp) 87 lw s8, 0x70(sp) 88 lw s9, 0x74(sp) 89 lw s10, 0x78(sp) 90 lw s11, 0x7C(sp) 91 92 // user pc goes into sepc for sret 93 lw t1, 0x40(sp) 94 csrw sepc, t1 95 96 // restore the caller-save registers 97 lw ra, 0x00(sp) 98 lw t0, 0x04(sp) 99 lw t1, 0x08(sp) 100 lw t2, 0x0C(sp) 101 lw t3, 0x10(sp) 102 lw t4, 0x14(sp) 103 lw t5, 0x18(sp) 104 lw t6, 0x1C(sp) 105 lw a0, 0x20(sp) 106 lw a1, 0x24(sp) 107 lw a2, 0x28(sp) 108 lw a3, 0x2C(sp) 109 lw a4, 0x30(sp) 110 lw a5, 0x34(sp) 111 lw a6, 0x38(sp) 112 lw a7, 0x3C(sp) 113 114 // finally restore the user sp 115 lw sp, 0x44(sp) 116 117 // and return from trap 118 sret 119 120 exception_entry: 121 // if scause is ECALL_UMODE, it is a system call 122 addi t2, zero, EXCn_ECALL_UMODE 123 andi t3, t1, 0xFF 124 beq t2, t3, syscall_entry 125 126 mv a0, sp 127 la ra, trap_exit 128 j exception_handler 129 130 syscall_table: 131 #define __SYSCALL(n,rtype,name,args) .word sys_##name 132 #include <xos/syscall-tmpl.h> 133 syscall_table_end: 134 135 syscall_entry: 136 li t1, SYSCALL_COUNT 137 bgeu t0, t1, illegal_syscall 138 139 // fn = [syscall_table + (syscall_number << 2)] 140 slli t0, t0, 2 141 la t1, syscall_table 142 add t2, t1, t0 143 lw t3, 0(t2) 144 145 jalr t3 146 147 // result -> user.a0 148 sw a0, 0x20(sp) 149 // user.pc += 4 150 lw t0, 0x40(sp) 151 addi t0, t0, 4 152 sw t0, 0x40(sp) 153 154 j trap_exit 155 156 illegal_syscall: 157 addi t0, zero, XOS_ERR_BAD_SYSCALL 158 sw t0, 0x20(sp) 159 j trap_exit 160 161 .globl user_mode_entry 162 user_mode_entry: 163 mv sp, a0 164 addi tp, sp, (32 * 4) 165 j trap_exit