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 35 #include <sys/types.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/machintr.h> 39 #include <sys/errno.h> 40 #include <sys/mman.h> 41 #include <sys/globaldata.h> 42 #include <sys/interrupt.h> 43 #include <stdio.h> 44 #include <signal.h> 45 #include <machine/globaldata.h> 46 #include <machine/md_var.h> 47 #include <sys/thread2.h> 48 49 /* 50 * Interrupt Subsystem ABI 51 */ 52 53 static void dummy_intr_disable(int); 54 static void dummy_intr_enable(int); 55 static void dummy_intr_setup(int, int); 56 static void dummy_intr_teardown(int); 57 static int dummy_legacy_intr_cpuid(int); 58 static void dummy_finalize(void); 59 static void dummy_intrcleanup(void); 60 static void dummy_stabilize(void); 61 62 struct machintr_abi MachIntrABI = { 63 MACHINTR_GENERIC, 64 .intr_disable = dummy_intr_disable, 65 .intr_enable = dummy_intr_enable, 66 .intr_setup = dummy_intr_setup, 67 .intr_teardown = dummy_intr_teardown, 68 .legacy_intr_cpuid = dummy_legacy_intr_cpuid, 69 70 .finalize = dummy_finalize, 71 .cleanup = dummy_intrcleanup, 72 .stabilize = dummy_stabilize 73 }; 74 75 static void 76 dummy_intr_disable(int intr) 77 { 78 } 79 80 static void 81 dummy_intr_enable(int intr) 82 { 83 } 84 85 static void 86 dummy_intr_setup(int intr, int flags) 87 { 88 } 89 90 static void 91 dummy_intr_teardown(int intr) 92 { 93 } 94 95 static void 96 dummy_finalize(void) 97 { 98 } 99 100 static void 101 dummy_intrcleanup(void) 102 { 103 } 104 105 static void 106 dummy_stabilize(void) 107 { 108 } 109 110 static int 111 dummy_legacy_intr_cpuid(int irq __unused) 112 { 113 return 0; 114 } 115 116 /* 117 * Process pending interrupts 118 */ 119 void 120 splz(void) 121 { 122 struct mdglobaldata *gd = mdcpu; 123 thread_t td = gd->mi.gd_curthread; 124 int irq; 125 126 while (gd->mi.gd_reqflags & (RQF_IPIQ|RQF_INTPEND)) { 127 crit_enter_quick(td); 128 if (gd->mi.gd_reqflags & RQF_IPIQ) { 129 atomic_clear_int(&gd->mi.gd_reqflags, RQF_IPIQ); 130 lwkt_process_ipiq(); 131 } 132 if (gd->mi.gd_reqflags & RQF_INTPEND) { 133 atomic_clear_int(&gd->mi.gd_reqflags, RQF_INTPEND); 134 while ((irq = ffs(gd->gd_spending)) != 0) { 135 --irq; 136 atomic_clear_int(&gd->gd_spending, 1 << irq); 137 irq += FIRST_SOFTINT; 138 sched_ithd_soft(irq); 139 } 140 while ((irq = ffs(gd->gd_fpending)) != 0) { 141 --irq; 142 atomic_clear_int(&gd->gd_fpending, 1 << irq); 143 sched_ithd_hard_virtual(irq); 144 } 145 } 146 crit_exit_noyield(td); 147 } 148 } 149 150 /* 151 * Allows an unprotected signal handler or mailbox to signal an interrupt 152 * 153 * For sched_ithd_hard_virtual() to properly preempt via lwkt_schedule() we 154 * cannot enter a critical section here. We use td_nest_count instead. 155 */ 156 void 157 signalintr(int intr) 158 { 159 struct mdglobaldata *gd = mdcpu; 160 thread_t td = gd->mi.gd_curthread; 161 162 if (td->td_critcount || td->td_nest_count) { 163 atomic_set_int_nonlocked(&gd->gd_fpending, 1 << intr); 164 atomic_set_int(&gd->mi.gd_reqflags, RQF_INTPEND); 165 } else { 166 ++td->td_nest_count; 167 atomic_clear_int(&gd->gd_fpending, 1 << intr); 168 sched_ithd_hard_virtual(intr); 169 --td->td_nest_count; 170 } 171 } 172 173 /* 174 * Must block any signal normally handled as maskable interrupt. 175 */ 176 void 177 cpu_disable_intr(void) 178 { 179 sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGUSR1)); 180 } 181 182 void 183 cpu_enable_intr(void) 184 { 185 sigsetmask(0); 186 } 187 188 void 189 cpu_mask_all_signals(void) 190 { 191 sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGQUIT)| 192 sigmask(SIGUSR1)|sigmask(SIGTERM)|sigmask(SIGWINCH)| 193 sigmask(SIGUSR2)); 194 } 195 196 void 197 cpu_unmask_all_signals(void) 198 { 199 sigsetmask(0); 200 } 201 202 void 203 cpu_invlpg(void *addr) 204 { 205 madvise(addr, PAGE_SIZE, MADV_INVAL); 206 } 207 208 void 209 cpu_invltlb(void) 210 { 211 madvise((void *)KvaStart, KvaEnd - KvaStart, MADV_INVAL); 212 } 213