xref: /openbsd/sys/arch/arm64/arm64/softintr.c (revision 311b6aa8)
1*311b6aa8Smpi /*	$OpenBSD: softintr.c,v 1.2 2020/09/11 09:27:10 mpi Exp $	*/
2f24071e5Spatrick /*	$NetBSD: softintr.c,v 1.1 2003/02/26 21:26:12 fvdl Exp $	*/
3f24071e5Spatrick 
4f24071e5Spatrick /*-
5f24071e5Spatrick  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
6f24071e5Spatrick  * All rights reserved.
7f24071e5Spatrick  *
8f24071e5Spatrick  * This code is derived from software contributed to The NetBSD Foundation
9f24071e5Spatrick  * by Jason R. Thorpe.
10f24071e5Spatrick  *
11f24071e5Spatrick  * Redistribution and use in source and binary forms, with or without
12f24071e5Spatrick  * modification, are permitted provided that the following conditions
13f24071e5Spatrick  * are met:
14f24071e5Spatrick  * 1. Redistributions of source code must retain the above copyright
15f24071e5Spatrick  *    notice, this list of conditions and the following disclaimer.
16f24071e5Spatrick  * 2. Redistributions in binary form must reproduce the above copyright
17f24071e5Spatrick  *    notice, this list of conditions and the following disclaimer in the
18f24071e5Spatrick  *    documentation and/or other materials provided with the distribution.
19f24071e5Spatrick  *
20f24071e5Spatrick  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21f24071e5Spatrick  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22f24071e5Spatrick  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23f24071e5Spatrick  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24f24071e5Spatrick  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25f24071e5Spatrick  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26f24071e5Spatrick  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27f24071e5Spatrick  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28f24071e5Spatrick  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29f24071e5Spatrick  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30f24071e5Spatrick  * POSSIBILITY OF SUCH DAMAGE.
31f24071e5Spatrick  */
32f24071e5Spatrick 
33f24071e5Spatrick /*
34f24071e5Spatrick  * Generic soft interrupt implementation
35f24071e5Spatrick  */
36f24071e5Spatrick 
37f24071e5Spatrick #include <sys/param.h>
38*311b6aa8Smpi #include <sys/systm.h>
39f24071e5Spatrick #include <sys/malloc.h>
40f24071e5Spatrick 
41f24071e5Spatrick #include <machine/intr.h>
42f24071e5Spatrick 
43f24071e5Spatrick #include <uvm/uvm_extern.h>
44f24071e5Spatrick 
45f24071e5Spatrick struct soft_intr soft_intrs[SI_NSOFTINTR];
46f24071e5Spatrick 
47f24071e5Spatrick const int soft_intr_to_ssir[SI_NSOFTINTR] = {
48f24071e5Spatrick 	SIR_SOFT,
49f24071e5Spatrick 	SIR_CLOCK,
50f24071e5Spatrick 	SIR_NET,
51f24071e5Spatrick 	SIR_TTY,
52f24071e5Spatrick };
53f24071e5Spatrick 
54f24071e5Spatrick void	softintr_biglock_wrap(void *);
55f24071e5Spatrick 
56f24071e5Spatrick /*
57f24071e5Spatrick  * softintr_init:
58f24071e5Spatrick  *
59f24071e5Spatrick  *	Initialize the software interrupt system.
60f24071e5Spatrick  */
61f24071e5Spatrick void
softintr_init(void)62f24071e5Spatrick softintr_init(void)
63f24071e5Spatrick {
64f24071e5Spatrick 	struct soft_intr *si;
65f24071e5Spatrick 	int i;
66f24071e5Spatrick 
67f24071e5Spatrick 	for (i = 0; i < SI_NSOFTINTR; i++) {
68f24071e5Spatrick 		si = &soft_intrs[i];
69f24071e5Spatrick 		TAILQ_INIT(&si->softintr_q);
70f24071e5Spatrick 		mtx_init(&si->softintr_lock, IPL_HIGH);
71f24071e5Spatrick 		si->softintr_ssir = soft_intr_to_ssir[i];
72f24071e5Spatrick 	}
73f24071e5Spatrick }
74f24071e5Spatrick 
75f24071e5Spatrick /*
76f24071e5Spatrick  * softintr_dispatch:
77f24071e5Spatrick  *
78f24071e5Spatrick  *	Process pending software interrupts.
79f24071e5Spatrick  */
80f24071e5Spatrick void
softintr_dispatch(int which)81f24071e5Spatrick softintr_dispatch(int which)
82f24071e5Spatrick {
83f24071e5Spatrick 	struct soft_intr		*si = &soft_intrs[which];
84f24071e5Spatrick 	struct soft_intrhand	*sih;
85f24071e5Spatrick 	void				*arg;
86f24071e5Spatrick 	void				(*fn)(void *);
87f24071e5Spatrick 
88f24071e5Spatrick 	for (;;) {
89f24071e5Spatrick 		mtx_enter(&si->softintr_lock);
90f24071e5Spatrick 		sih = TAILQ_FIRST(&si->softintr_q);
91f24071e5Spatrick 		if (sih == NULL) {
92f24071e5Spatrick 			mtx_leave(&si->softintr_lock);
93f24071e5Spatrick 			break;
94f24071e5Spatrick 		}
95f24071e5Spatrick 		TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
96f24071e5Spatrick 		sih->sih_pending = 0;
97f24071e5Spatrick 
98f24071e5Spatrick 		uvmexp.softs++;
99f24071e5Spatrick 		arg = sih->sih_arg;
100f24071e5Spatrick 		fn = sih->sih_fn;
101f24071e5Spatrick 		mtx_leave(&si->softintr_lock);
102f24071e5Spatrick 
103f24071e5Spatrick 		(*fn)(arg);
104f24071e5Spatrick 	}
105f24071e5Spatrick }
106f24071e5Spatrick 
107f24071e5Spatrick #ifdef MULTIPROCESSOR
108f24071e5Spatrick void
softintr_biglock_wrap(void * arg)109f24071e5Spatrick softintr_biglock_wrap(void *arg)
110f24071e5Spatrick {
111f24071e5Spatrick 	struct soft_intrhand	*sih = arg;
112f24071e5Spatrick 
113f24071e5Spatrick 	KERNEL_LOCK();
114f24071e5Spatrick 	sih->sih_fnwrap(sih->sih_argwrap);
115f24071e5Spatrick 	KERNEL_UNLOCK();
116f24071e5Spatrick }
117f24071e5Spatrick #endif
118f24071e5Spatrick 
119f24071e5Spatrick /*
120f24071e5Spatrick  * softintr_establish:		[interface]
121f24071e5Spatrick  *
122f24071e5Spatrick  *	Register a software interrupt handler.
123f24071e5Spatrick  */
124f24071e5Spatrick void *
softintr_establish_flags(int ipl,void (* func)(void *),void * arg,int flags)125f24071e5Spatrick softintr_establish_flags(int ipl, void (*func)(void *), void *arg, int flags)
126f24071e5Spatrick {
127f24071e5Spatrick 	struct soft_intr *si;
128f24071e5Spatrick 	struct soft_intrhand *sih;
129f24071e5Spatrick 	int which;
130f24071e5Spatrick 
131f24071e5Spatrick 	switch (ipl) {
132f24071e5Spatrick 	case IPL_SOFTCLOCK:
133f24071e5Spatrick 		which = SIR_CLOCK;
134f24071e5Spatrick 		break;
135f24071e5Spatrick 
136f24071e5Spatrick 	case IPL_SOFTNET:
137f24071e5Spatrick 		which = SIR_NET;
138f24071e5Spatrick 		break;
139f24071e5Spatrick 
140f24071e5Spatrick 	case IPL_TTY:
141f24071e5Spatrick 	case IPL_SOFTTTY:
142f24071e5Spatrick 		which = SIR_TTY;
143f24071e5Spatrick 		break;
144f24071e5Spatrick 
145f24071e5Spatrick 	default:
146f24071e5Spatrick 		panic("softintr_establish");
147f24071e5Spatrick 	}
148f24071e5Spatrick 
149f24071e5Spatrick 	si = &soft_intrs[which];
150f24071e5Spatrick 
151f24071e5Spatrick 	sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT | M_ZERO);
152f24071e5Spatrick 	if (__predict_true(sih != NULL)) {
153f24071e5Spatrick 		sih->sih_intrhead = si;
154f24071e5Spatrick #ifdef MULTIPROCESSOR
155f24071e5Spatrick 		if (flags & SOFTINTR_ESTABLISH_MPSAFE) {
156f24071e5Spatrick #endif
157f24071e5Spatrick 			sih->sih_fn = func;
158f24071e5Spatrick 			sih->sih_arg = arg;
159f24071e5Spatrick #ifdef MULTIPROCESSOR
160f24071e5Spatrick 		} else {
161f24071e5Spatrick 			sih->sih_fnwrap = func;
162f24071e5Spatrick 			sih->sih_argwrap = arg;
163f24071e5Spatrick 			sih->sih_fn = softintr_biglock_wrap;
164f24071e5Spatrick 			sih->sih_arg = sih;
165f24071e5Spatrick 		}
166f24071e5Spatrick #endif
167f24071e5Spatrick 	}
168f24071e5Spatrick 	return (sih);
169f24071e5Spatrick }
170f24071e5Spatrick 
171f24071e5Spatrick /*
172f24071e5Spatrick  * softintr_disestablish:	[interface]
173f24071e5Spatrick  *
174f24071e5Spatrick  *	Unregister a software interrupt handler.
175f24071e5Spatrick  */
176f24071e5Spatrick void
softintr_disestablish(void * arg)177f24071e5Spatrick softintr_disestablish(void *arg)
178f24071e5Spatrick {
179f24071e5Spatrick 	struct soft_intrhand *sih = arg;
180f24071e5Spatrick 	struct soft_intr *si = sih->sih_intrhead;
181f24071e5Spatrick 
182f24071e5Spatrick 	mtx_enter(&si->softintr_lock);
183f24071e5Spatrick 	if (sih->sih_pending) {
184f24071e5Spatrick 		TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
185f24071e5Spatrick 		sih->sih_pending = 0;
186f24071e5Spatrick 	}
187f24071e5Spatrick 	mtx_leave(&si->softintr_lock);
188f24071e5Spatrick 
189f24071e5Spatrick 	free(sih, M_DEVBUF, 0);
190f24071e5Spatrick }
191f24071e5Spatrick 
192f24071e5Spatrick void
softintr(int intrq)193f24071e5Spatrick softintr(int intrq)
194f24071e5Spatrick {
195f24071e5Spatrick 	// protected by mutex in caller
196f24071e5Spatrick 	curcpu()->ci_ipending |= (1 << intrq);
197f24071e5Spatrick }
198