1 /* $NetBSD: softint_machdep.c,v 1.4 2020/01/08 17:38:42 ad Exp $ */
2 /*-
3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 *
10 * This material is based upon work supported by the Defense Advanced Research
11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 * Contract No. N66001-09-C-2073.
13 * Approved for Public Release, Distribution Unlimited
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #define __INTR_PRIVATE
38
39 #include <sys/param.h>
40 #include <sys/intr.h>
41 #include <sys/cpu.h>
42 #include <sys/atomic.h>
43
44 #ifdef __HAVE_FAST_SOFTINTS
45 #include <powerpc/softint.h>
46
47 __CTASSERT(IPL_NONE < IPL_SOFTCLOCK);
48 __CTASSERT(IPL_SOFTCLOCK < IPL_SOFTBIO);
49 __CTASSERT(IPL_SOFTBIO < IPL_SOFTNET);
50 __CTASSERT(IPL_SOFTNET < IPL_SOFTSERIAL);
51 __CTASSERT(IPL_SOFTSERIAL < IPL_VM);
52 __CTASSERT(IPL_SOFTSERIAL < sizeof(uint32_t)*2);
53
54 static inline void
softint_deliver(struct cpu_info * ci,int ipl)55 softint_deliver(struct cpu_info *ci, int ipl)
56 {
57 const int si_level = IPL2SOFTINT(ipl);
58 KASSERT(ci->ci_data.cpu_softints & (1 << ipl));
59 ci->ci_data.cpu_softints ^= 1 << ipl;
60 softint_fast_dispatch(ci->ci_softlwps[si_level], ipl);
61 KASSERTMSG(ci->ci_cpl == IPL_HIGH,
62 "%s: cpl (%d) != HIGH", __func__, ci->ci_cpl);
63 }
64
65 void
powerpc_softint(struct cpu_info * ci,int old_ipl,vaddr_t pc)66 powerpc_softint(struct cpu_info *ci, int old_ipl, vaddr_t pc)
67 {
68 const u_int softint_mask = (IPL_SOFTMASK << old_ipl) & IPL_SOFTMASK;
69 u_int softints;
70
71 KASSERTMSG(ci->ci_idepth == -1,
72 "%s: cpu%u: idepth (%d) != -1", __func__,
73 cpu_index(ci), ci->ci_idepth);
74 KASSERT(ci->ci_mtx_count == 0);
75 KASSERT(ci->ci_cpl == IPL_HIGH);
76 while ((softints = (ci->ci_data.cpu_softints & softint_mask)) != 0) {
77 KASSERT(old_ipl < IPL_SOFTSERIAL);
78 if (softints & (1 << IPL_SOFTSERIAL)) {
79 softint_deliver(ci, IPL_SOFTSERIAL);
80 continue;
81 }
82 KASSERT(old_ipl < IPL_SOFTNET);
83 if (softints & (1 << IPL_SOFTNET)) {
84 softint_deliver(ci, IPL_SOFTNET);
85 continue;
86 }
87 KASSERT(old_ipl < IPL_SOFTBIO);
88 if (softints & (1 << IPL_SOFTBIO)) {
89 softint_deliver(ci, IPL_SOFTBIO);
90 continue;
91 }
92 KASSERT(old_ipl < IPL_SOFTCLOCK);
93 if (softints & (1 << IPL_SOFTCLOCK)) {
94 softint_deliver(ci, IPL_SOFTCLOCK);
95 continue;
96 }
97 #ifdef __HAVE_PREEMPTION
98 KASSERT(old_ipl == IPL_NONE);
99 KASSERT(softints == (1 << IPL_NONE));
100 ci->ci_data.cpu_softints ^= (1 << IPL_NONE);
101 kpreempt(pc);
102 #endif
103 }
104 }
105
106 void
powerpc_softint_init_md(lwp_t * l,u_int si_level,uintptr_t * machdep_p)107 powerpc_softint_init_md(lwp_t *l, u_int si_level, uintptr_t *machdep_p)
108 {
109 struct cpu_info * const ci = l->l_cpu;
110
111 *machdep_p = 1 << SOFTINT2IPL(si_level);
112 KASSERT(*machdep_p & IPL_SOFTMASK);
113 ci->ci_softlwps[si_level] = l;
114 }
115
116 void
powerpc_softint_trigger(uintptr_t machdep)117 powerpc_softint_trigger(uintptr_t machdep)
118 {
119 struct cpu_info * const ci = curcpu();
120
121 atomic_or_uint(&ci->ci_data.cpu_softints, machdep);
122 }
123
124 #endif /* __HAVE_FAST_SOFTINTS */
125