1 /* 2 * Copyright (c) 2006 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sys/platform/vkernel/platform/machintr.c,v 1.17 2008/04/30 16:59:45 dillon Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/machintr.h> 41 #include <sys/errno.h> 42 #include <sys/mman.h> 43 #include <sys/globaldata.h> 44 #include <sys/interrupt.h> 45 #include <stdio.h> 46 #include <signal.h> 47 #include <machine/globaldata.h> 48 #include <machine/md_var.h> 49 #include <sys/thread2.h> 50 51 /* 52 * Interrupt Subsystem ABI 53 */ 54 55 static void dummy_intrdis(int); 56 static void dummy_intren(int); 57 static int dummy_vectorctl(int, int, int); 58 static int dummy_setvar(int, const void *); 59 static int dummy_getvar(int, void *); 60 static void dummy_finalize(void); 61 static void dummy_intrcleanup(void); 62 63 struct machintr_abi MachIntrABI = { 64 MACHINTR_GENERIC, 65 .intrdis = dummy_intrdis, 66 .intren = dummy_intren, 67 .vectorctl = dummy_vectorctl, 68 .setvar = dummy_setvar, 69 .getvar = dummy_getvar, 70 .finalize = dummy_finalize, 71 .cleanup = dummy_intrcleanup 72 }; 73 74 static void 75 dummy_intrdis(int intr) 76 { 77 } 78 79 static void 80 dummy_intren(int intr) 81 { 82 } 83 84 static int 85 dummy_vectorctl(int op, int intr, int flags) 86 { 87 return (0); 88 /* return (EOPNOTSUPP); */ 89 } 90 91 static int 92 dummy_setvar(int varid, const void *buf) 93 { 94 return (ENOENT); 95 } 96 97 static int 98 dummy_getvar(int varid, void *buf) 99 { 100 return (ENOENT); 101 } 102 103 static void 104 dummy_finalize(void) 105 { 106 } 107 108 static void 109 dummy_intrcleanup(void) 110 { 111 } 112 113 /* 114 * Process pending interrupts 115 */ 116 void 117 splz(void) 118 { 119 struct mdglobaldata *gd = mdcpu; 120 thread_t td = gd->mi.gd_curthread; 121 int irq; 122 123 while (gd->mi.gd_reqflags & (RQF_IPIQ|RQF_INTPEND)) { 124 crit_enter_quick(td); 125 #ifdef SMP 126 if (gd->mi.gd_reqflags & RQF_IPIQ) { 127 atomic_clear_int(&gd->mi.gd_reqflags, RQF_IPIQ); 128 lwkt_process_ipiq(); 129 } 130 #endif 131 if (gd->mi.gd_reqflags & RQF_INTPEND) { 132 atomic_clear_int(&gd->mi.gd_reqflags, RQF_INTPEND); 133 while ((irq = ffs(gd->gd_spending)) != 0) { 134 --irq; 135 atomic_clear_int(&gd->gd_spending, 1 << irq); 136 irq += FIRST_SOFTINT; 137 sched_ithd(irq); 138 } 139 while ((irq = ffs(gd->gd_fpending)) != 0) { 140 --irq; 141 atomic_clear_int(&gd->gd_fpending, 1 << irq); 142 sched_ithd(irq); 143 } 144 } 145 crit_exit_noyield(td); 146 } 147 } 148 149 /* 150 * Allows an unprotected signal handler or mailbox to signal an interrupt 151 * 152 * For sched_ithd() to properly preempt via lwkt_schedule() we cannot 153 * enter a critical section here. We use td_nest_count instead. 154 */ 155 void 156 signalintr(int intr) 157 { 158 struct mdglobaldata *gd = mdcpu; 159 thread_t td = gd->mi.gd_curthread; 160 161 if (td->td_critcount || td->td_nest_count) { 162 atomic_set_int_nonlocked(&gd->gd_fpending, 1 << intr); 163 atomic_set_int(&gd->mi.gd_reqflags, RQF_INTPEND); 164 } else { 165 ++td->td_nest_count; 166 atomic_clear_int(&gd->gd_fpending, 1 << intr); 167 sched_ithd(intr); 168 --td->td_nest_count; 169 } 170 } 171 172 void 173 cpu_disable_intr(void) 174 { 175 sigblock(sigmask(SIGALRM)|sigmask(SIGIO)); 176 } 177 178 void 179 cpu_enable_intr(void) 180 { 181 sigsetmask(0); 182 } 183 184 void 185 cpu_mask_all_signals(void) 186 { 187 sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGQUIT)| 188 sigmask(SIGUSR1)|sigmask(SIGTERM)|sigmask(SIGWINCH)| 189 sigmask(SIGUSR2)); 190 } 191 192 void 193 cpu_unmask_all_signals(void) 194 { 195 sigsetmask(0); 196 } 197 198 void 199 cpu_invlpg(void *addr) 200 { 201 madvise(addr, PAGE_SIZE, MADV_INVAL); 202 } 203 204 void 205 cpu_invltlb(void) 206 { 207 madvise((void *)KvaStart, KvaEnd - KvaStart, MADV_INVAL); 208 } 209