1/* $NetBSD: spl.S,v 1.8 2023/06/12 19:04:14 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2014,2023 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry, and Nick Hudson. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <machine/asm.h> 33#include "assym.h" 34 35__RCSID("$NetBSD: spl.S,v 1.8 2023/06/12 19:04:14 skrll Exp $") 36 37#define SZINT (1 << INT_SCALESHIFT) 38 39 .data 40 .globl _C_LABEL(ipl_sie_map) 41 .type _C_LABEL(ipl_sie_map), @object 42 .p2align INT_SCALESHIFT 43_C_LABEL(ipl_sie_map): 44 .word 0 /* IPL_NONE */ 45 .word 0 /* IPL_SOFTCLOCK */ 46 .word 0 /* IPL_SOFTBIO */ 47 .word 0 /* IPL_SOFTNET */ 48 .word 0 /* IPL_SOFTSERIAL */ 49 .word SIE_SEIE /* IPL_VM */ 50 .word SIE_SEIE | SIE_STIE /* IPL_SCHED */ 51 .word SIE_SEIE | SIE_STIE | SIE_SSIE /* IPL_HIGH */ 52 53 54ENTRY_NP(splx) 55 // a0 = new IPL 56 PTR_L a3, L_CPU(tp) // get curcpu() 57 INT_L t0, CI_CPL(a3) // get current IPL 58 bge a0, t0, 2f 59 60 sll t2, a0, INT_SCALESHIFT 61 PTR_LA a1, _C_LABEL(ipl_sie_map) 62 add a1, a1, t2 63 INT_L a1, 0(a1) 64 65 li t2, (SIE_SEIE | SIE_STIE | SIE_SSIE) 66 xor a1, a1, t2 67 68 // a0 = new ipl 69 INT_S a0, CI_CPL(a3) // change IPL 70 csrs sie, a1 71 72#ifdef __HAVE_FAST_SOFTINTS 73 INT_L t4, CI_SOFTINTS(a3) // get softint mask 74 srl t4, t4, a0 // see what softints are pending. 75 beqz t4, 3f // none, just return 76 // there are softints that need to be delivered, so instead of 77 // returning to the caller, we'll jump to softint_deliver and it 78 // will do a tailcall back to splx and then we can return (if there 79 // are no pending softints). 80 tail _C_LABEL(softint_deliver) 813: 82#endif /* __HAVE_FAST_SOFTINTS */ 832: 84 ret // return (or do softints) 85END(splx) 86 87 88#if IPL_NONE != 0 89#error IPL_NONE is not 0 90#endif 91ENTRY_NP(spl0) 92 PTR_L a3, L_CPU(tp) // get curcpu() 93 INT_S zero, CI_CPL(a3) // set current IPL to IPL_NONE 94 li t2, (SIE_SEIE | SIE_STIE | SIE_SSIE) 95 csrs sie, t2 96 97 csrsi sstatus, SR_SIE // enable interrupts 98#ifdef __HAVE_FAST_SOFTINTS 99 // spl0() is only called rarely so the overhead of always calling 100 // softint_deliver is minimal. 101 tail _C_LABEL(softint_deliver) 102#else /* __HAVE_FAST_SOFTINTS */ 103 ret 104#endif /* __HAVE_FAST_SOFTINTS */ 105END(spl0) 106 107 108ENTRY(splintr) 109 csrr t0, sip 110 111 li t1, IPL_NONE 112 andi t0, t0, (SIP_SEIP | SIP_STIP | SIP_SSIP) 113 beq t0, zero, 1f // If nothing is pending return IPL_NONE 114 115 PTR_LA t3, _C_LABEL(ipl_sie_map) 116 117 li t1, IPL_VM 118 li t2, IPL_HIGH + 1 1192: 120 INT_L t5, IPL_VM * (1 << INT_SCALESHIFT)(t3) 121 PTR_ADDI t3, t3, 1 << INT_SCALESHIFT 122 not t5, t5 123 and t5, t5, t0 124 beq t5, zero, 1f 125 addi t1, t1, 1 126 bne t1, t2, 2b 127 1281: 129 LONG_S t0, 0(a0) 130 mv a0, t1 131 jr ra 132END(splintr) 133 134 135ENTRY_NP(splsoftclock) 136 li t1, IPL_SOFTCLOCK 137 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_SOFTCLOCK 138 j _splraise 139END(splsoftclock) 140 141 142ENTRY_NP(splsoftbio) 143 li t1, IPL_SOFTBIO 144 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_SOFTBIO 145 j _splraise 146END(splsoftbio) 147 148 149ENTRY_NP(splsoftnet) 150 li t1, IPL_SOFTNET 151 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_SOFTNET 152 j _splraise 153END(splsoftnet) 154 155 156ENTRY_NP(splsoftserial) 157 li t1, IPL_SOFTSERIAL 158 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_SOFTSERIAL 159 j _splraise 160END(splsoftserial) 161 162 163ENTRY_NP(splvm) 164 li t1, IPL_VM 165 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_VM 166 j _splraise 167END(splvm) 168 169 170ENTRY_NP(splsched) 171 li t1, IPL_SCHED 172 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_SCHED 173 j _splraise 174END(splsched) 175 176ENTRY_NP(splhigh) 177 li t1, IPL_HIGH 178 INT_L t0, _C_LABEL(ipl_sie_map) + SZINT * IPL_HIGH 179 j _splraise 180END(splhigh) 181 182 183ENTRY_NP(splraise) 184 // a0 = new higher IPL 185 mv t1, a0 186 sll t2, a0, INT_SCALESHIFT 187 PTR_LA a1, _C_LABEL(ipl_sie_map) 188 add a1, a1, t2 189 INT_L t0, 0(a1) 190 191_splraise: 192 PTR_L a3, L_CPU(tp) // get curcpu() 193 INT_L a0, CI_CPL(a3) // get current IPL 194 bge a0, t1, 2f // already at same or higher? 195 csrc sie, t0 // 196 INT_S t1, CI_CPL(a3) // change IPL 1972: 198 ret 199END(splraise) 200