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 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 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 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 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