.altmacro .macro SAVE_GP n sd x\n, \n*8(sp) .endm .macro LOAD_GP n ld x\n, \n*8(sp) .endm .section .text .globl trap_from_kernel .globl trap_from_user .globl return_to_user .align 2 # just like a function call trap_from_kernel: # save s* addi sp, sp, -17*8 sd ra, 1*8(sp) sd t0, 2*8(sp) sd t1, 3*8(sp) sd t2, 4*8(sp) sd t3, 5*8(sp) sd t4, 6*8(sp) sd t5, 7*8(sp) sd t6, 8*8(sp) sd a0, 9*8(sp) sd a1, 10*8(sp) sd a2, 11*8(sp) sd a3, 12*8(sp) sd a4, 13*8(sp) sd a5, 14*8(sp) sd a6, 15*8(sp) sd a7, 16*8(sp) call kernel_trap_entry # restore s* ld ra, 1*8(sp) ld t0, 2*8(sp) ld t1, 3*8(sp) ld t2, 4*8(sp) ld t3, 5*8(sp) ld t4, 6*8(sp) ld t5, 7*8(sp) ld t6, 8*8(sp) ld a0, 9*8(sp) ld a1, 10*8(sp) ld a2, 11*8(sp) ld a3, 12*8(sp) ld a4, 13*8(sp) ld a5, 14*8(sp) ld a6, 15*8(sp) ld a7, 16*8(sp) addi sp, sp, 17*8 sret trap_from_user: # swap sp and sscratch(previously stored user TrapContext's address in return_to_user) csrrw sp, sscratch, sp sd x1, 1*8(sp) .set n, 3 .rept 29 SAVE_GP %n .set n, n+1 .endr csrr t0, sstatus csrr t1, sepc sd t0, 32*8(sp) # save sstatus into the TrapContext sd t1, 33*8(sp) # save sepc into the TrapContext csrr t2, sscratch sd t2, 2*8(sp) # save user stack pointer into the TrapContext ld ra, 35*8(sp) ld s0, 36*8(sp) ld s1, 37*8(sp) ld s2, 38*8(sp) ld s3, 39*8(sp) ld s4, 40*8(sp) ld s5, 41*8(sp) ld s6, 42*8(sp) ld s7, 43*8(sp) ld s8, 44*8(sp) ld s9, 45*8(sp) ld s10, 46*8(sp) ld s11, 47*8(sp) ld fp, 48*8(sp) ld tp, 49*8(sp) ld sp, 34*8(sp) ret # a0: pointer to TrapContext in user space (constant) return_to_user: # sscratch store the TrapContext's address csrw sscratch, a0 # offset in TrapContext's order sd sp, 34*8(a0) sd ra, 35*8(a0) sd s0, 36*8(a0) sd s1, 37*8(a0) sd s2, 38*8(a0) sd s3, 39*8(a0) sd s4, 40*8(a0) sd s5, 41*8(a0) sd s6, 42*8(a0) sd s7, 43*8(a0) sd s8, 44*8(a0) sd s9, 45*8(a0) sd s10, 46*8(a0) sd s11, 47*8(a0) sd fp, 48*8(a0) sd tp, 49*8(a0) mv sp, a0 # now sp points to TrapContext in kernel space # restore sstatus and sepc ld t0, 32*8(sp) ld t1, 33*8(sp) csrw sstatus, t0 csrw sepc, t1 # save x* expect x0 and sp ld x1, 1*8(sp) .set n, 3 .rept 29 LOAD_GP %n .set n, n+1 .endr ld sp, 2*8(sp) sret