Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/riscv Split out a bunch of functions from locore.S ...



details:   https://anonhg.NetBSD.org/src/rev/1591afd1cfa4
branches:  trunk
changeset: 371838:1591afd1cfa4
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Oct 14 07:58:30 2022 +0000

description:
Split out a bunch of functions from locore.S into cpu_switch.S

NFC

diffstat:

 sys/arch/riscv/conf/files.riscv   |    3 +-
 sys/arch/riscv/riscv/cpu_switch.S |  438 ++++++++++++++++++++++++++++++++++++++
 sys/arch/riscv/riscv/locore.S     |  392 +---------------------------------
 3 files changed, 441 insertions(+), 392 deletions(-)

diffs (truncated from 865 to 300 lines):

diff -r eb67cbd622ae -r 1591afd1cfa4 sys/arch/riscv/conf/files.riscv
--- a/sys/arch/riscv/conf/files.riscv   Fri Oct 14 07:54:49 2022 +0000
+++ b/sys/arch/riscv/conf/files.riscv   Fri Oct 14 07:58:30 2022 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.riscv,v 1.10 2022/09/27 08:18:21 skrll Exp $
+#      $NetBSD: files.riscv,v 1.11 2022/10/14 07:58:30 skrll Exp $
 #
 
 maxpartitions  16
@@ -21,6 +21,7 @@
 file   arch/riscv/riscv/clock_machdep.c
 file   arch/riscv/riscv/core_machdep.c         coredump
 file   arch/riscv/riscv/cpu_subr.c
+file   arch/riscv/riscv/cpu_switch.S
 file   arch/riscv/riscv/db_interface.c         ddb
 file   arch/riscv/riscv/db_disasm.c            ddb
 file   arch/riscv/riscv/db_machdep.c           ddb | kgdb
diff -r eb67cbd622ae -r 1591afd1cfa4 sys/arch/riscv/riscv/cpu_switch.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/riscv/riscv/cpu_switch.S Fri Oct 14 07:58:30 2022 +0000
@@ -0,0 +1,438 @@
+/* $NetBSD: cpu_switch.S,v 1.1 2022/10/14 07:58:30 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include "assym.h"
+
+/*
+ * struct lwp *
+ * cpu_switchto(struct lwp *oldl, struct lwp *newl, bool returning);
+ */
+ENTRY_NP(cpu_switchto)
+       addi    sp, sp, -TF_LEN         // allocate trapframe
+
+       REG_S   ra, TF_RA(sp)           // save return address
+       REG_S   s0, TF_S0(sp)           // save callee saved address
+       REG_S   s1, TF_S1(sp)           // save callee saved address
+       REG_S   s2, TF_S2(sp)           // save callee saved address
+       REG_S   s3, TF_S3(sp)           // save callee saved address
+       REG_S   s4, TF_S4(sp)           // save callee saved address
+       REG_S   s5, TF_S5(sp)           // save callee saved address
+       REG_S   s6, TF_S6(sp)           // save callee saved address
+       REG_S   s7, TF_S7(sp)           // save callee saved address
+       REG_S   s8, TF_S8(sp)           // save callee saved address
+       REG_S   s9, TF_S9(sp)           // save callee saved address
+       REG_S   s10, TF_S10(sp)         // save callee saved address
+       REG_S   s11, TF_S11(sp)         // save callee saved address
+       csrr    t4, sstatus             // get status for intr state
+       REG_S   t4, TF_SR(sp)           // save it
+
+       REG_S   sp, L_MD_KTF(a0)        // record trapframe pointer
+
+       csrrci  t0, sstatus, SR_SIE     // # disable interrupts
+
+       mv      tp, a1                  // # put the new lwp in thread pointer
+
+       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 interrupts?)
+
+       REG_L   s0, TF_S0(sp)           // restore callee saved
+       REG_L   s1, TF_S1(sp)           // restore callee saved
+       REG_L   s2, TF_S2(sp)           // restore callee saved
+       REG_L   s3, TF_S3(sp)           // restore callee saved
+       REG_L   s4, TF_S4(sp)           // restore callee saved
+       REG_L   s5, TF_S5(sp)           // restore callee saved
+       REG_L   s6, TF_S6(sp)           // restore callee saved
+       REG_L   s7, TF_S7(sp)           // restore callee saved
+       REG_L   s8, TF_S8(sp)           // restore callee saved
+       REG_L   s9, TF_S9(sp)           // restore callee saved
+       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
+       //      a1 = curcpu()
+       //      tp = newl
+
+       ret
+END(cpu_switchto)
+
+
+ENTRY_NP(cpu_lwp_trampoline)
+       mv      a1, tp                  // get new lwp
+       call    _C_LABEL(lwp_startup)   // call lwp startup
+
+       mv      a0, s1                  // get saved arg
+       jalr    s0                      // call saved func
+
+       // If the saved func returns, we are returning to user land.
+       j       _C_LABEL(exception_userexit)
+END(cpu_lwp_trampoline)
+
+
+ENTRY_NP(cpu_fast_switchto_cleanup)
+//     PTR_L   t0, L_CPU(tp)           // Get curcpu()
+//     INT_L   t1, CI_MTX_COUNT(t0)    // get mutex count
+//     addi    t1, t1, 1               // increment mutex count
+//     INT_S   t1, CI_MTX_COUNT(t0)    // save it
+       mv      ra, a1                  // Restore real RA
+#if IPL_SCHED != IPL_HIGH
+       tail    _C_LABEL(splhigh)       // go back to IPL HIGH
+#else
+       ret                             // just return
+#endif
+END(cpu_fast_switchto_cleanup)
+
+
+/*
+ * void
+ * cpu_fast_switchto(struct lwp *, int s);
+ */
+ENTRY_NP(cpu_fast_switchto)
+       addi    sp, sp, -(TF_LEN + CALLFRAME_SIZ)
+       REG_S   a0, (TF_LEN + CALLFRAME_S0)(sp)
+       REG_S   ra, (TF_LEN + CALLFRAME_RA)(sp)
+
+       PTR_LA  t2, _C_LABEL(cpu_fast_switchto_cleanup)
+
+       REG_S   t2, TF_RA(sp)           // return to someplace else
+       REG_S   s0, TF_S0(sp)           // save callee saved register
+       REG_S   s1, TF_S1(sp)           // save callee saved register
+       REG_S   s2, TF_S2(sp)           // save callee saved register
+       REG_S   s3, TF_S3(sp)           // save callee saved register
+       REG_S   s4, TF_S4(sp)           // save callee saved register
+       REG_S   s5, TF_S5(sp)           // save callee saved register
+       REG_S   s6, TF_S6(sp)           // save callee saved register
+       REG_S   s7, TF_S7(sp)           // save callee saved register
+       REG_S   s8, TF_S8(sp)           // save callee saved register
+       REG_S   s9, TF_S9(sp)           // save callee saved register
+       REG_S   s10, TF_S10(sp)         // save callee saved register
+       REG_S   s11, TF_S11(sp)         // save callee saved register
+       csrr    t4, sstatus             // get status register (for intr state)
+       REG_S   t4, TF_SR(sp)           // save it
+
+       mv      s0, tp                  // remember curlwp
+       mv      s1, sp                  // remember kernel stack
+
+       csrrci  t0, sstatus, SR_SIE     // disable interrupts
+       PTR_L   t1, L_CPU(tp)           // get curcpu()
+
+       PTR_S   sp, L_MD_KTF(tp)        // save trapframe ptr in oldlwp
+       mv      tp, a0                  // set thread pointer to newlwp
+       PTR_S   tp, CI_CURLWP(t1)       // update curlwp
+       PTR_L   sp, L_MD_KTF(tp)        // switch to its stack
+       csrw    sstatus, t0             // reenable interrupts
+       call    _C_LABEL(softint_dispatch)
+       csrrci  t0, sstatus, SR_SIE     // disable interrupts
+       PTR_L   t1, L_CPU(tp)           // get curcpu() again
+       mv      tp, s0                  // return to pinned lwp
+       PTR_S   tp, CI_CURLWP(t1)       // restore curlwp
+       csrw    sstatus, t0             // reenable interrupts
+       mv      sp, s1                  // restore stack pointer
+
+       REG_L   ra, TF_RA(sp)           // get return address
+       REG_L   s0, TF_S0(sp)           // restore register we used
+       REG_L   s1, TF_S1(sp)           // restore register we used
+
+       REG_L   a0, (TF_LEN + CALLFRAME_S0)(sp) // Pass the softlwp
+       REG_L   a1, (TF_LEN + CALLFRAME_RA)(sp) // Pass the real RA
+
+       addi    sp, sp, TF_LEN+CALLFRAME_SIZ    // drop trapframe/callframe
+       ret                             // return
+END(cpu_fast_switchto)
+
+
+/*
+ * RISC-V only has a simple exception handler handles both synchronous traps
+ * and interrupts.
+ */
+ENTRY_NP(cpu_exception_handler)
+       csrrw   tp, sscratch, tp        // swap scratch and thread pointer
+       beqz    tp, .Lexception_kernel  //   tp == 0, already on kernel stack
+       //
+       // The exception 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.
+       //
+       REG_S   sp, L_MD_USP(tp)        // save user stack pointer temporarily
+       PTR_L   sp, L_MD_UTF(sp)        // trapframe pointer loaded
+       REG_S   t1, TF_T1(sp)           // save t1
+       REG_L   t1, L_MD_USP(tp)        // get user stack pointer
+       REG_S   t1, TF_SP(sp)           // save thread pointer in trapframe
+       csrrw   t1, sscratch, zero      // swap saved thread pointer with 0
+       REG_L   t1, TF_TP(sp)           // save thread pointer in trapframe
+       li      t1, 0                   // indicate user exception
+       j       .Lexception_common
+
+       //
+       // The exception happened while we were already in the kernel.  That
+       // means tp already has curlwp and sp has the kernel stack pointer so
+       // just need to restore it and then adjust it down for space for the
+       // trap frame.  We save t1 so we can use it the original sp into the
+       // trapframe for use by the exception exiting code.
+       //
+.Lexception_kernel:
+       csrrw   tp, sscratch, zero      // get back our thread 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
+       li      t1, 1                   // indicate kernel exception
+
+.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
+       REG_S   gp, TF_GP(sp)           // save gp
+       REG_S   a0, TF_A0(sp)           // save a0
+       REG_S   a1, TF_A1(sp)           // save a1
+       REG_S   a2, TF_A2(sp)           // save a2
+       REG_S   a3, TF_A3(sp)           // save a3
+       REG_S   a4, TF_A4(sp)           // save a4
+       REG_S   a5, TF_A5(sp)           // save a5
+       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
+       REG_S   t5, TF_T5(sp)           // save t5
+       REG_S   t6, TF_T6(sp)           // save t6
+
+       // Now we get the
+       mv      a0, sp                  // trapframe pointer
+       csrr    a1, sepc                // get exception pc
+       csrr    a2, sstatus             // get status
+       csrr    a3, scause              // get cause
+
+       REG_S   a1, TF_PC(sp)
+       REG_S   a2, TF_SR(sp)
+       REG_S   a3, TF_CAUSE(sp)        // save cause
+
+       // Now we've saved the trapfame, the cause is still in a3.
+
+       bltz    a3, intr_handler        // MSB is set if interrupt
+
+       // stval is only relevant for non-interrupts
+       csrr    a4, stval               // get stval
+       REG_S   a4, TF_TVAL(sp)
+
+       beqz    t1, trap_user           // this was a user trap
+       // This was a kernel exception
+       call    _C_LABEL(cpu_trap)      // just call trap to handle it
+exception_kernexit:
+       // If we got here, we are returning from a kernel exception (either a
+       // 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_SIE   // 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
+       REG_L   a1, TF_A1(sp)           // restore a1
+       REG_L   a2, TF_A2(sp)           // restore a2
+       REG_L   a3, TF_A3(sp)           // restore a3
+       REG_L   a4, TF_A4(sp)           // restore a4
+       REG_L   a5, TF_A5(sp)           // restore a5
+       REG_L   a6, TF_A6(sp)           // restore a6
+       REG_L   a7, TF_A7(sp)           // restore a7
+       REG_L   t2, TF_T2(sp)           // restore t2
+       REG_L   t3, TF_T3(sp)           // restore t3



Home | Main Index | Thread Index | Old Index