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