Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/riscv/riscv Since there is only "scratch" system re...
details: https://anonhg.NetBSD.org/src/rev/5cce52219ed0
branches: trunk
changeset: 337044:5cce52219ed0
user: matt <matt%NetBSD.org@localhost>
date: Tue Mar 31 01:30:50 2015 +0000
description:
Since there is only "scratch" system register for use on exception, come
up with a new scheme for its use. Use PTR_LA, INT_S/INT_L, etc. Disable
interrupts when returning from exceptions. Use L_CPU(tp) to get the curcpu
pointer.
When the cpu gets an exception from kernel mode, the sscratch register will be
0 and curlwp will be in the "tp" register. When the cpu gets an exception from
user mode, the sscratch register will be a pointer to the current lwp.
When an exception happends, the sp is atomically swapped with the sscratch
register.
If the sp is zero, the exception was a kernel exception and the
kernel exception path is taken: sp and sscratch are swapped again
so sscratch is zero again and then a trapframe is allocated from
the kernel stack. The t1 register is saved and then the pre-trapframe
sp is written to the trapframe.
If sp was non-zero, the exception was from user mode. The tp register
is temporarily saved in L_MD_TP(sp) and sp is moved tp. tp now
contains a pointer to the current lwp. A pointer to the user
trapframe is loaded from L_MD_UTF(tp). Then t1 is saved in the
trapframe so it can be used. The old sp is fetched from sscratch
while sscratch is zeroed (indicated kernel mode). The old sp is
saved in the trapframe.
Upon exiting the exception, if the exception is returning to user
mode, the contents of tp is written to sscratch.
diffstat:
sys/arch/riscv/riscv/locore.S | 92 +++++++++++++++++++++---------------------
1 files changed, 47 insertions(+), 45 deletions(-)
diffs (255 lines):
diff -r 101790fe635a -r 5cce52219ed0 sys/arch/riscv/riscv/locore.S
--- a/sys/arch/riscv/riscv/locore.S Tue Mar 31 01:15:26 2015 +0000
+++ b/sys/arch/riscv/riscv/locore.S Tue Mar 31 01:30:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.1 2015/03/28 16:13:56 matt Exp $ */
+/* $NetBSD: locore.S,v 1.2 2015/03/31 01:30:50 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -78,10 +78,10 @@
call memset // zero through kernel_end
// As a temporary hack, word 0 contains the amount of memory in MB
- lw a7, (zero) // load memory size
+ INT_L a7, (zero) // load memory size
slli a7, a7, (20-PGSHIFT) // convert MB to pages
- auipc t0, %pcrel_hi(physmem)
- sw a7, %pcrel_lo(physmem)(t0) // store it in physmem
+.L01: auipc t0, %pcrel_hi(physmem)
+ INT_S a7, %pcrel_lo(.L01)(t0) // store it in physmem
li t4, PTE_V | PTE_SX | PTE_SW | PTE_SR | PTE_G
#ifdef _LP64
@@ -115,11 +115,11 @@
//
// Fill in the PDEs to direct map memory.
//
-1: REG_S t4, 0(s3) // store PDE
+.Lfill: REG_S t4, 0(s3) // store PDE
add t4, t4, t3 // advance PA in PDE to next segment
add s3, s3, SZREG // advance to next PDE slot
addi a7, a7, -1 // count down segment
- bgtz a6, 1b // loop if more
+ bgtz a6, .Lfill // loop if more
csrw sptbr, s1 // set the page table base
li t0, SR_VM
@@ -131,8 +131,7 @@
.Lmmu_on:
// MMU is on!
- PTR_LA a0, _C_LABEL(cpu_info_store)
- csrw sscratch, a0 // curcpu() in sscratch
+ csrw sscratch, zero // zero in sscratch to mark kernel
PTR_LA tp, _C_LABEL(lwp0) // put curlwp in tp
@@ -151,8 +150,8 @@
// Now we should ready to start initializing the kernel.
PTR_LA a0, _C_LABEL(start) // kernel_start
add a1, s5, s11 // kernel_end
- PTR_LA ra, _C_LABEL(main) // return to main
- tail _C_LABEL(init_riscv) // do MD startup
+ call _C_LABEL(init_riscv) // do MD startup
+ tail _C_LABEL(main) // and transfer to main
// not reached
END(start)
@@ -162,7 +161,7 @@
ENTRY_NP(cpu_switchto)
addi sp, sp, -TF_LEN // allocate trapframe
- beqz a0, 1f // can skip saving oldl state?
+ beqz a0, .Lswitchto_newlwp // can skip saving oldl state?
REG_S ra, TF_RA(sp) // save return address
REG_S s0, TF_S0(sp) // save callee saved address
@@ -181,17 +180,17 @@
REG_S t4, TF_SR(sp) // save it
REG_S sp, L_MD_KTF(a0) // record trapframe pointer
-1:
- csrrci t0, sstatus, SR_EI // disable interrupts
+.Lswitchto_newlwp:
+ csrrci t0, sstatus, SR_EI // # disable interrupts
- move tp, a1 // put the new lwp in thread pointer
+ move tp, a1 // # put the new lwp in thread pointer
- csrr t1, sscratch // get curcpu
- PTR_S tp, CI_CURLWP(t1) // update curcpu with the new curlwp
+ PTR_L t1, L_CPU(tp) // # get curcpu
+ PTR_S tp, CI_CURLWP(t1) // # update curcpu with the new curlwp
- REG_L sp, L_MD_KTF(tp) // load its kernel stack pointer
- REG_L t4, TF_SR(sp) // fetch status register
- csrw sstatus, t4 // restore it (and interrutps?)
+ REG_L sp, L_MD_KTF(tp) // # load its kernel stack pointer
+ REG_L t4, TF_SR(sp) // # fetch status register
+ csrw sstatus, t4 // # restore it (and interrutps?)
REG_L s0, TF_S0(sp) // restore callee saved
REG_L s1, TF_S1(sp) // restore callee saved
@@ -206,6 +205,8 @@
REG_L s10, TF_S10(sp) // restore callee saved
REG_L s11, TF_S11(sp) // restore callee saved
+ REG_L ra, TF_RA(sp) // restore return address
+
addi sp, sp, TF_LEN // remove trapframe
// a0 = oldl
@@ -227,11 +228,11 @@
END(cpu_lwp_trampoline)
ENTRY_NP(cpu_fast_switchto_cleanup)
- lw t0, CI_MTX_COUNT(a1) // get mutex count
+ INT_L t0, CI_MTX_COUNT(a1) // get mutex count
REG_L ra, CALLFRAME_RA(sp) // get return address
REG_L a0, CALLFRAME_S0(sp) // get pinned LWP
addi t0, t0, 1 // increment mutex count
- sw t0, CI_MTX_COUNT(a1) // save it
+ INT_S t0, CI_MTX_COUNT(a1) // save it
PTR_S zero, L_CTXSWTCH(a0) // clear l_ctxswitch
addi sp, sp, CALLFRAME_SIZ // remove callframe
#if IPL_SCHED != IPL_HIGH
@@ -273,7 +274,7 @@
#if 0
csrrci t0, sstatus, SR_EI // disable interrupts
#endif
- csrr t1, sscratch // get curcpu()
+ PTR_L t1, L_CPU(tp) // get curcpu()
PTR_S sp, L_MD_KTF(tp) // save trapframe ptr in oldlwp
move tp, a0 // set thread pointer to newlwp
@@ -286,7 +287,7 @@
#if 0
csrrci t0, sstatus, SR_EI // disable interrupts
#endif
- csrr t1, sscratch // get curcpu() again
+ PTR_L t1, L_CPU(tp) // get curcpu() again
move tp, s0 // return to pinned lwp
PTR_S tp, CI_CURLWP(t1) // restore curlwp
#if 0
@@ -305,26 +306,24 @@
// RISCV only has a simple exception handler handles both synchronous traps
// and interrupts.
ENTRY_NP(cpu_exception_handler)
- csrw uarch0, sp // save stack pointer
- csrr sp, sstatus // get status
- andi sp, sp, SR_PS // user fault?
- bnez sp, 1f // no, already on kernel stack
+ csrrw sp, sscratch, sp // swap scratch and stack pointer
+ beqz sp, .Lexception_kernel // sp == 0, already on kernel stack
//
// The execption happened while user code was executing. We need to
// get the pointer to the user trapframe from the LWP md area. Then we
// save t1 and tp so we have a register to work with and to get curlwp
// into tp. We also save the saved SP into the trapframe.
+ // Upon entry on an exception from user, sscratch will contain curlwp.
//
- csrr sp, sscratch // get curcpu()
- PTR_L sp, CI_CURLWP(sp) // get curlwp
+ REG_S tp, L_MD_TP(sp) // save thread pointer temporarily
+ mv tp, sp // put curlwp in thread pointer
PTR_L sp, L_MD_UTF(sp) // trapframe pointer loaded
- REG_S tp, TF_TP(sp) // save thread pointer
REG_S t1, TF_T1(sp) // save t1
- csrr t1, uarch0 // get saved SP
+ csrrw t1, sscratch, zero // save saved stack pointer with 0
REG_S t1, TF_SP(sp) // save stack pointer
- csrr t1, sscratch // get curcpu()
- PTR_L tp, CI_CURLWP(t1) // put curlwp in thread pointer
- j 2f
+ REG_S t1, L_MD_TP(tp) // get thread pointer from temp store
+ REG_L t1, TF_SP(sp) // save thread pointer in trapframe
+ j .Lexception_common
//
// The exception happened while we were already in the kernel. That
@@ -333,12 +332,13 @@
// trap frame. We save t1 so we can use it the original sp into the
// trapframe for use by the exception exiting code.
//
-1: csrr sp, uarch0 // get back our stack pointer
+.Lexception_kernel:
+ csrrw sp, sscratch, zero // get back our stack pointer
addi sp, sp, -TF_LEN // allocate stack frame
REG_S t1, TF_T1(sp) // save t1
addi t1, sp, TF_LEN
REG_S t1, TF_SP(sp) // save SP
-2:
+.Lexception_common:
// Now we save all the temporary registers into the trapframe since
// they will most certainly be changed.
REG_S ra, TF_RA(sp) // save return address
@@ -352,6 +352,7 @@
REG_S a6, TF_A6(sp) // save a6
REG_S a7, TF_A7(sp) // save a7
REG_S t0, TF_T0(sp) // save t0
+ // t1 is already saved
REG_S t2, TF_T2(sp) // save t2
REG_S t3, TF_T3(sp) // save t3
REG_S t4, TF_T4(sp) // save t4
@@ -366,8 +367,8 @@
csrr a4, sbadaddr // get badaddr
REG_S a1, TF_PC(sp)
- sw a2, TF_SR(sp)
- sw a3, TF_CAUSE(sp) // save cause
+ INT_S a2, TF_SR(sp)
+ INT_S a3, TF_CAUSE(sp) // save cause
REG_S a4, TF_BADADDR(sp)
// Now we've saved the trapfame, the cause is still in a3.
@@ -383,6 +384,8 @@
// trap or interrupt). Simply return the volatile registers and the
// exception PC and status, load the saved SP from the trapframe, and
// return from the exception
+ csrrci zero, sstatus, SR_EI // disable interrupts
+
REG_L ra, TF_RA(sp) // restore return address
REG_L gp, TF_GP(sp) // restore gp
REG_L a0, TF_A0(sp) // restore a0
@@ -431,8 +434,10 @@
call _C_LABEL(cpu_trap) // nope, just a regular trap
_C_LABEL(exception_userexit):
- lw t0, L_MD_ASTPENDING(tp) // ast pending?
+ INT_L t0, L_MD_ASTPENDING(tp) // ast pending?
bnez t0, trap_doast // yes, handle it.
+ csrrci zero, sstatus, SR_EI // disable interrupts
+ csrw sscratch, tp // show we are coming from userland
REG_L s0, TF_S0(sp) // only restore from userland
REG_L s1, TF_S1(sp) // only restore from userland
REG_L s2, TF_S2(sp) // only restore from userland
@@ -449,9 +454,7 @@
j exception_kernexit
trap_syscall:
-.L0: auipc ra, %pcrel_hi(exception_userexit)
- addi ra, ra, %pcrel_lo(.L0)
-
+.L0: PTR_L ra, exception_userexit
PTR_L t0, L_PROC(tp) // get proc struct
PTR_L t0, P_MD_SYSCALL(t0) // get syscall address from proc
jr t0 // and jump to it
@@ -469,15 +472,14 @@
REG_S s9, TF_S9(sp) // only save from userland
REG_S s10, TF_S10(sp) // only save from userland
REG_S s11, TF_S11(sp) // only save from userland
- auipc ra, %pcrel_hi(exception_userexit)
- addi ra, ra, %pcrel_lo(exception_userexit)
+ PTR_LA ra, exception_userexit
trap_doast:
move a0, sp // only argument is trapframe
tail _C_LABEL(cpu_ast)
intr_user:
call _C_LABEL(cpu_intr) // handle interrupt
- lw t0, L_MD_ASTPENDING(tp) // get astpending
+ INT_L t0, L_MD_ASTPENDING(tp) // get astpending
bnez t0, intr_usersave // if one is pending, deal with in
REG_L tp, TF_TP(sp) // restore thread pointer
Home |
Main Index |
Thread Index |
Old Index