kernel/trampoline.S
149 lines
1 #2 # low-level code to handle traps from user space into3 # the kernel, and returns from kernel to user.4 #5 # the kernel maps the page holding this code6 # at the same virtual address (TRAMPOLINE)7 # in user and kernel space so that it continues8 # to work when it switches page tables.9 # kernel.ld causes this code to start at 10 # a page boundary.11 #1213#include "riscv.h"14#include "memlayout.h"1516.section trampsec17.globl trampoline18.globl usertrap19trampoline:20.align 421.globl uservec22uservec: 23 #24 # trap.c sets stvec to point here, so25 # traps from user space start here,26 # in supervisor mode, but with a27 # user page table.28 #2930 # save user a0 in sscratch so31 # a0 can be used to get at TRAPFRAME.32 csrw sscratch, a03334 # each process has a separate p->trapframe memory area,35 # but it's mapped to the same virtual address36 # (TRAPFRAME) in every process's user page table.37 li a0, TRAPFRAME38 39 # save the user registers in TRAPFRAME40 sd ra, 40(a0)41 sd sp, 48(a0)42 sd gp, 56(a0)43 sd tp, 64(a0)44 sd t0, 72(a0)45 sd t1, 80(a0)46 sd t2, 88(a0)47 sd s0, 96(a0)48 sd s1, 104(a0)49 sd a1, 120(a0)50 sd a2, 128(a0)51 sd a3, 136(a0)52 sd a4, 144(a0)53 sd a5, 152(a0)54 sd a6, 160(a0)55 sd a7, 168(a0)56 sd s2, 176(a0)57 sd s3, 184(a0)58 sd s4, 192(a0)59 sd s5, 200(a0)60 sd s6, 208(a0)61 sd s7, 216(a0)62 sd s8, 224(a0)63 sd s9, 232(a0)64 sd s10, 240(a0)65 sd s11, 248(a0)66 sd t3, 256(a0)67 sd t4, 264(a0)68 sd t5, 272(a0)69 sd t6, 280(a0)7071 # save the user a0 in p->trapframe->a072 csrr t0, sscratch73 sd t0, 112(a0)7475 # initialize kernel stack pointer, from p->trapframe->kernel_sp76 ld sp, 8(a0)7778 # make tp hold the current hartid, from p->trapframe->kernel_hartid79 ld tp, 32(a0)8081 # load the address of usertrap(), from p->trapframe->kernel_trap82 ld t0, 16(a0)8384 # fetch the kernel page table address, from p->trapframe->kernel_satp.85 ld t1, 0(a0)8687 # wait for any previous memory operations to complete, so that88 # they use the user page table.89 sfence.vma zero, zero9091 # install the kernel page table.92 csrw satp, t19394 # flush now-stale user entries from the TLB.95 sfence.vma zero, zero9697 # call usertrap()98 jalr t099100.globl userret101userret:102 # usertrap() returns here, with user satp in a0.103 # return from kernel to user.104105 # switch to the user page table.106 sfence.vma zero, zero107 csrw satp, a0108 sfence.vma zero, zero109110 li a0, TRAPFRAME111112 # restore all but a0 from TRAPFRAME113 ld ra, 40(a0)114 ld sp, 48(a0)115 ld gp, 56(a0)116 ld tp, 64(a0)117 ld t0, 72(a0)118 ld t1, 80(a0)119 ld t2, 88(a0)120 ld s0, 96(a0)121 ld s1, 104(a0)122 ld a1, 120(a0)123 ld a2, 128(a0)124 ld a3, 136(a0)125 ld a4, 144(a0)126 ld a5, 152(a0)127 ld a6, 160(a0)128 ld a7, 168(a0)129 ld s2, 176(a0)130 ld s3, 184(a0)131 ld s4, 192(a0)132 ld s5, 200(a0)133 ld s6, 208(a0)134 ld s7, 216(a0)135 ld s8, 224(a0)136 ld s9, 232(a0)137 ld s10, 240(a0)138 ld s11, 248(a0)139 ld t3, 256(a0)140 ld t4, 264(a0)141 ld t5, 272(a0)142 ld t6, 280(a0)143144 # restore user a0145 ld a0, 112(a0)146 147 # return to user mode and user pc.148 # usertrapret() set up sstatus and sepc.149 sret150