root/kernel/trampoline.S

/* [<][>][^][v][top][bottom][index][help] */
   1         #
   2         # low-level code to handle traps from user space into
   3         # the kernel, and returns from kernel to user.
   4         #
   5         # the kernel maps the page holding this code
   6         # at the same virtual address (TRAMPOLINE)
   7         # in user and kernel space so that it continues
   8         # to work when it switches page tables.
   9         # kernel.ld causes this code to start at 
  10         # a page boundary.
  11         #
  12 
  13 #include "riscv.h"
  14 #include "memlayout.h"
  15 
  16 .section trampsec
  17 .globl trampoline
  18 .globl usertrap
  19 trampoline:
  20 .align 4
  21 .globl uservec
  22 uservec:    
  23     #
  24         # trap.c sets stvec to point here, so
  25         # traps from user space start here,
  26         # in supervisor mode, but with a
  27         # user page table.
  28         #
  29 
  30         # save user a0 in sscratch so
  31         # a0 can be used to get at TRAPFRAME.
  32         csrw sscratch, a0
  33 
  34         # each process has a separate p->trapframe memory area,
  35         # but it's mapped to the same virtual address
  36         # (TRAPFRAME) in every process's user page table.
  37         li a0, TRAPFRAME
  38         
  39         # save the user registers in TRAPFRAME
  40         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)
  70 
  71     # save the user a0 in p->trapframe->a0
  72         csrr t0, sscratch
  73         sd t0, 112(a0)
  74 
  75         # initialize kernel stack pointer, from p->trapframe->kernel_sp
  76         ld sp, 8(a0)
  77 
  78         # make tp hold the current hartid, from p->trapframe->kernel_hartid
  79         ld tp, 32(a0)
  80 
  81         # load the address of usertrap(), from p->trapframe->kernel_trap
  82         ld t0, 16(a0)
  83 
  84         # fetch the kernel page table address, from p->trapframe->kernel_satp.
  85         ld t1, 0(a0)
  86 
  87         # wait for any previous memory operations to complete, so that
  88         # they use the user page table.
  89         sfence.vma zero, zero
  90 
  91         # install the kernel page table.
  92         csrw satp, t1
  93 
  94         # flush now-stale user entries from the TLB.
  95         sfence.vma zero, zero
  96 
  97         # call usertrap()
  98         jalr t0
  99 
 100 .globl userret
 101 userret:
 102         # usertrap() returns here, with user satp in a0.
 103         # return from kernel to user.
 104 
 105         # flush icache, in case this is the first time
 106         # we're running this proc on this hart.
 107         fence.i
 108 
 109         # switch to the user page table.
 110         sfence.vma zero, zero
 111         csrw satp, a0
 112         sfence.vma zero, zero
 113 
 114         li a0, TRAPFRAME
 115 
 116         # restore all but a0 from TRAPFRAME
 117         ld ra, 40(a0)
 118         ld sp, 48(a0)
 119         ld gp, 56(a0)
 120         ld tp, 64(a0)
 121         ld t0, 72(a0)
 122         ld t1, 80(a0)
 123         ld t2, 88(a0)
 124         ld s0, 96(a0)
 125         ld s1, 104(a0)
 126         ld a1, 120(a0)
 127         ld a2, 128(a0)
 128         ld a3, 136(a0)
 129         ld a4, 144(a0)
 130         ld a5, 152(a0)
 131         ld a6, 160(a0)
 132         ld a7, 168(a0)
 133         ld s2, 176(a0)
 134         ld s3, 184(a0)
 135         ld s4, 192(a0)
 136         ld s5, 200(a0)
 137         ld s6, 208(a0)
 138         ld s7, 216(a0)
 139         ld s8, 224(a0)
 140         ld s9, 232(a0)
 141         ld s10, 240(a0)
 142         ld s11, 248(a0)
 143         ld t3, 256(a0)
 144         ld t4, 264(a0)
 145         ld t5, 272(a0)
 146         ld t6, 280(a0)
 147 
 148     # restore user a0
 149         ld a0, 112(a0)
 150         
 151         # return to user mode and user pc.
 152         # prepare_return() sets up sstatus and sepc.
 153         sret

/* [<][>][^][v][top][bottom][index][help] */