xref: /netbsd-src/sys/arch/riscv/riscv/spl.S (revision 08c3a075334387243f6f5e37339534c4ab35a0ee)
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