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