adopt github PR98 (No need to store TRAPFRAME in sscratch register)
This commit is contained in:
parent
ca6fc54934
commit
9fc9f755e1
|
@ -1,3 +1,5 @@
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
// which hart (core) is this?
|
// which hart (core) is this?
|
||||||
static inline uint64
|
static inline uint64
|
||||||
r_mhartid()
|
r_mhartid()
|
||||||
|
@ -331,6 +333,10 @@ sfence_vma()
|
||||||
asm volatile("sfence.vma zero, zero");
|
asm volatile("sfence.vma zero, zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef uint64 pte_t;
|
||||||
|
typedef uint64 *pagetable_t; // 512 PTEs
|
||||||
|
|
||||||
|
#endif // __ASSEMBLER__
|
||||||
|
|
||||||
#define PGSIZE 4096 // bytes per page
|
#define PGSIZE 4096 // bytes per page
|
||||||
#define PGSHIFT 12 // bits of offset within a page
|
#define PGSHIFT 12 // bits of offset within a page
|
||||||
|
@ -361,6 +367,3 @@ sfence_vma()
|
||||||
// Sv39, to avoid having to sign-extend virtual addresses
|
// Sv39, to avoid having to sign-extend virtual addresses
|
||||||
// that have the high bit set.
|
// that have the high bit set.
|
||||||
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
|
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
|
||||||
|
|
||||||
typedef uint64 pte_t;
|
|
||||||
typedef uint64 *pagetable_t; // 512 PTEs
|
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
# kernel.ld causes this to be aligned
|
# kernel.ld causes this to be aligned
|
||||||
# to a page boundary.
|
# to a page boundary.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
#include "riscv.h"
|
||||||
|
#include "memlayout.h"
|
||||||
|
|
||||||
.section trampsec
|
.section trampsec
|
||||||
.globl trampoline
|
.globl trampoline
|
||||||
trampoline:
|
trampoline:
|
||||||
|
@ -20,13 +24,15 @@ uservec:
|
||||||
# in supervisor mode, but with a
|
# in supervisor mode, but with a
|
||||||
# user page table.
|
# user page table.
|
||||||
#
|
#
|
||||||
# sscratch points to where the process's p->trapframe is
|
|
||||||
# mapped into user space, at TRAPFRAME.
|
|
||||||
#
|
|
||||||
|
|
||||||
# swap a0 and sscratch
|
# save user a0 in sscratch so
|
||||||
# so that a0 is TRAPFRAME
|
# a0 can be used to get at TRAPFRAME.
|
||||||
csrrw a0, sscratch, a0
|
csrw sscratch, a0
|
||||||
|
|
||||||
|
# each process has a separate p->trapframe memory area,
|
||||||
|
# but it's mapped to the same virtual address
|
||||||
|
# (TRAPFRAME) in every process.
|
||||||
|
li a0, TRAPFRAME
|
||||||
|
|
||||||
# save the user registers in TRAPFRAME
|
# save the user registers in TRAPFRAME
|
||||||
sd ra, 40(a0)
|
sd ra, 40(a0)
|
||||||
|
@ -86,20 +92,15 @@ uservec:
|
||||||
|
|
||||||
.globl userret
|
.globl userret
|
||||||
userret:
|
userret:
|
||||||
# userret(TRAPFRAME, pagetable)
|
# userret(pagetable)
|
||||||
# switch from kernel to user.
|
# switch from kernel to user.
|
||||||
# usertrapret() calls here.
|
# a0: user page table, for satp.
|
||||||
# a0: TRAPFRAME, in user page table.
|
|
||||||
# a1: user page table, for satp.
|
|
||||||
|
|
||||||
# switch to the user page table.
|
# switch to the user page table.
|
||||||
csrw satp, a1
|
csrw satp, a0
|
||||||
sfence.vma zero, zero
|
sfence.vma zero, zero
|
||||||
|
|
||||||
# put the saved user a0 in sscratch, so we
|
li a0, TRAPFRAME
|
||||||
# can swap it with our a0 (TRAPFRAME) in the last step.
|
|
||||||
ld t0, 112(a0)
|
|
||||||
csrw sscratch, t0
|
|
||||||
|
|
||||||
# restore all but a0 from TRAPFRAME
|
# restore all but a0 from TRAPFRAME
|
||||||
ld ra, 40(a0)
|
ld ra, 40(a0)
|
||||||
|
@ -133,8 +134,8 @@ userret:
|
||||||
ld t5, 272(a0)
|
ld t5, 272(a0)
|
||||||
ld t6, 280(a0)
|
ld t6, 280(a0)
|
||||||
|
|
||||||
# restore user a0, and save TRAPFRAME in sscratch
|
# restore user a0
|
||||||
csrrw a0, sscratch, a0
|
ld a0, 112(a0)
|
||||||
|
|
||||||
# return to user mode and user pc.
|
# return to user mode and user pc.
|
||||||
# usertrapret() set up sstatus and sepc.
|
# usertrapret() set up sstatus and sepc.
|
||||||
|
|
|
@ -96,8 +96,9 @@ usertrapret(void)
|
||||||
// we're back in user space, where usertrap() is correct.
|
// we're back in user space, where usertrap() is correct.
|
||||||
intr_off();
|
intr_off();
|
||||||
|
|
||||||
// send syscalls, interrupts, and exceptions to trampoline.S
|
// send syscalls, interrupts, and exceptions to uservec in trampoline.S
|
||||||
w_stvec(TRAMPOLINE + (uservec - trampoline));
|
uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline);
|
||||||
|
w_stvec(trampoline_uservec);
|
||||||
|
|
||||||
// set up trapframe values that uservec will need when
|
// set up trapframe values that uservec will need when
|
||||||
// the process next re-enters the kernel.
|
// the process next re-enters the kernel.
|
||||||
|
@ -121,11 +122,11 @@ usertrapret(void)
|
||||||
// tell trampoline.S the user page table to switch to.
|
// tell trampoline.S the user page table to switch to.
|
||||||
uint64 satp = MAKE_SATP(p->pagetable);
|
uint64 satp = MAKE_SATP(p->pagetable);
|
||||||
|
|
||||||
// jump to trampoline.S at the top of memory, which
|
// jump to userret in 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.
|
||||||
uint64 fn = TRAMPOLINE + (userret - trampoline);
|
uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline);
|
||||||
((void (*)(uint64,uint64))fn)(TRAPFRAME, satp);
|
((void (*)(uint64))trampoline_userret)(satp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupts and exceptions from kernel code go here via kernelvec,
|
// interrupts and exceptions from kernel code go here via kernelvec,
|
||||||
|
|
Loading…
Reference in a new issue