uservec before userret in trampoline, to match book and kernelvec

This commit is contained in:
Robert Morris 2019-07-26 09:38:22 -04:00
parent 8d30e21b59
commit fa2e2e3c81
3 changed files with 69 additions and 63 deletions

View file

@ -8,8 +8,10 @@
.globl kernelvec .globl kernelvec
.align 4 .align 4
kernelvec: kernelvec:
// make room to save registers.
addi sp, sp, -256 addi sp, sp, -256
// save the registers.
sd ra, 0(sp) sd ra, 0(sp)
sd sp, 8(sp) sd sp, 8(sp)
sd gp, 16(sp) sd gp, 16(sp)
@ -42,8 +44,10 @@ kernelvec:
sd t5, 232(sp) sd t5, 232(sp)
sd t6, 240(sp) sd t6, 240(sp)
// call the C trap handler in trap.c
call kerneltrap call kerneltrap
// restore registers.
ld ra, 0(sp) ld ra, 0(sp)
ld sp, 8(sp) ld sp, 8(sp)
ld gp, 16(sp) ld gp, 16(sp)
@ -78,6 +82,7 @@ kernelvec:
addi sp, sp, 256 addi sp, sp, 256
// return to whatever we were doing in the kernel.
sret sret
# #

View file

@ -2,77 +2,21 @@
# code to switch between user and kernel space. # code to switch between user and kernel space.
# #
# this code is mapped at the same virtual address # this code is mapped at the same virtual address
# in user and kernel space so that it continues # (TRAMPOLINE) in user and kernel space so that
# to work when it switches page tables. # it continues to work when it switches page tables.
# #
# kernel.ld causes userret to be aligned # kernel.ld causes this to be aligned
# to a page boundary. # to a page boundary.
# #
.section trampsec .section trampsec
.globl trampoline .globl trampoline
trampoline: trampoline:
.globl userret
userret:
# userret(trapframe, pagetable)
# 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 the 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 in sscratch
csrrw a0, sscratch, a0
# return to user mode and user pc.
# usertrapret() set up sstatus and sepc.
sret
.align 4 .align 4
.globl uservec .globl uservec
uservec: uservec:
# #
# trap.c set stvec to point here, so # trap.c sets stvec to point here, so
# user interrupts and exceptions start here, # traps from user space start here,
# in supervisor mode, but with a # in supervisor mode, but with a
# user page table. # user page table.
# #
@ -139,3 +83,59 @@ uservec:
# jump to usertrap(), which does not return # jump to usertrap(), which does not return
jr t0 jr t0
.globl userret
userret:
# userret(trapframe, pagetable)
# 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 the 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 in sscratch
csrrw a0, sscratch, a0
# return to user mode and user pc.
# usertrapret() set up sstatus and sepc.
sret

View file

@ -9,7 +9,7 @@
struct spinlock tickslock; struct spinlock tickslock;
uint ticks; uint ticks;
extern char trampoline[], uservec[]; extern char trampoline[], uservec[], userret[];
// in kernelvec.S, calls kerneltrap(). // in kernelvec.S, calls kerneltrap().
void kernelvec(); void kernelvec();
@ -123,7 +123,8 @@ usertrapret(void)
// jump to trampoline.S at the top of memory, which // jump to trampoline.S at the top of memory, which
// switches to the user page table, restores user registers, // switches to the user page table, restores user registers,
// and switches to user mode with sret. // and switches to user mode with sret.
((void (*)(uint64,uint64))TRAMPOLINE)(TRAPFRAME, satp); uint64 fn = TRAMPOLINE + (userret - trampoline);
((void (*)(uint64,uint64))fn)(TRAPFRAME, satp);
} }
// interrupts and exceptions from kernel code go here via kernelvec, // interrupts and exceptions from kernel code go here via kernelvec,