# # code to switch between user and kernel space. # # this code is mapped at the same virtual address # in user and kernel space so that it can switch # page tables. # # kernel.ld causes trampout to be aligned # to a page boundary. # .globl usertrap .section trampoline .globl trampout trampout: # switch from kernel to user. # usertrapret() calls here. # a0: p->tf in user page table # a1: new value for satp, for user page table # switch to user page table. sfence.vma zero, zero csrw satp, a1 # put the saved user a0 in sscratch, so we # can swap it with our a0 (p->tf) in the last step. ld t0, 112(a0) csrw sscratch, t0 # restore all but a0 from p->tf ld ra, 40(a0) ld sp, 48(a0) ld gp, 56(a0) ld tp, 64(a0) ld t0, 72(a0) ld t1, 80(a0) ld t2, 88(a0) ld s0, 96(a0) ld s1, 104(a0) ld a1, 120(a0) ld a2, 128(a0) ld a3, 136(a0) ld a4, 144(a0) ld a5, 152(a0) ld a6, 160(a0) ld a7, 168(a0) ld s2, 176(a0) ld s3, 184(a0) ld s4, 192(a0) ld s5, 200(a0) ld s6, 208(a0) ld s7, 216(a0) ld s8, 224(a0) ld s9, 232(a0) ld s10, 240(a0) ld s11, 248(a0) ld t3, 256(a0) ld t4, 264(a0) ld t5, 272(a0) ld t6, 280(a0) # restore user a0, and save p->tf csrrw a0, sscratch, a0 # return to user mode and user pc. # caller has set up sstatus and sepc. sret .align 4 .globl trampin trampin: # # trap.c set stvec to point here, so # user interrupts and exceptions start here, # in supervisor mode, but with a # user page table. # # sscratch points to where the process's p->tf is # mapped into user space, at TRAPFRAME. # # swap a0 and sscratch # so that a0 is p->tf csrrw a0, sscratch, a0 # save the user registers in p->tf sd ra, 40(a0) sd sp, 48(a0) sd gp, 56(a0) sd tp, 64(a0) sd t0, 72(a0) sd t1, 80(a0) sd t2, 88(a0) sd s0, 96(a0) sd s1, 104(a0) sd a1, 120(a0) sd a2, 128(a0) sd a3, 136(a0) sd a4, 144(a0) sd a5, 152(a0) sd a6, 160(a0) sd a7, 168(a0) sd s2, 176(a0) sd s3, 184(a0) sd s4, 192(a0) sd s5, 200(a0) sd s6, 208(a0) sd s7, 216(a0) sd s8, 224(a0) sd s9, 232(a0) sd s10, 240(a0) sd s11, 248(a0) sd t3, 256(a0) sd t4, 264(a0) sd t5, 272(a0) sd t6, 280(a0) # save the user a0 in p->tf->a0 csrr t0, sscratch sd t0, 112(a0) # restore kernel stack pointer from p->tf->kernel_sp ld sp, 8(a0) # make tp hold the current hartid, from p->tf->kernel_hartid ld tp, 32(a0) # remember the address of usertrap(), p->tf->kernel_trap ld t0, 16(a0) # restore kernel page table from p->tf->kernel_satp ld t1, 0(a0) sfence.vma zero, zero csrw satp, t1 # a0 is no longer valid, since the kernel page # table does not specially map p->td. # jump to usertrap(), which does not return jr t0