1 1.1 cherry /* NetBSD: intr.c,v 1.15 2004/04/10 14:49:55 kochi Exp */ 2 1.1 cherry 3 1.1 cherry /* 4 1.1 cherry * Copyright 2002 (c) Wasabi Systems, Inc. 5 1.1 cherry * All rights reserved. 6 1.1 cherry * 7 1.1 cherry * Written by Frank van der Linden for Wasabi Systems, Inc. 8 1.1 cherry * 9 1.1 cherry * Redistribution and use in source and binary forms, with or without 10 1.1 cherry * modification, are permitted provided that the following conditions 11 1.1 cherry * are met: 12 1.1 cherry * 1. Redistributions of source code must retain the above copyright 13 1.1 cherry * notice, this list of conditions and the following disclaimer. 14 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 cherry * notice, this list of conditions and the following disclaimer in the 16 1.1 cherry * documentation and/or other materials provided with the distribution. 17 1.1 cherry * 3. All advertising materials mentioning features or use of this software 18 1.1 cherry * must display the following acknowledgement: 19 1.1 cherry * This product includes software developed for the NetBSD Project by 20 1.1 cherry * Wasabi Systems, Inc. 21 1.1 cherry * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 cherry * or promote products derived from this software without specific prior 23 1.1 cherry * written permission. 24 1.1 cherry * 25 1.1 cherry * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 cherry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 cherry * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 cherry * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 cherry * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 cherry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 cherry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 cherry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 cherry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 cherry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 cherry * POSSIBILITY OF SUCH DAMAGE. 36 1.1 cherry */ 37 1.1 cherry 38 1.1 cherry /*- 39 1.1 cherry * Copyright (c) 1991 The Regents of the University of California. 40 1.1 cherry * All rights reserved. 41 1.1 cherry * 42 1.1 cherry * This code is derived from software contributed to Berkeley by 43 1.1 cherry * William Jolitz. 44 1.1 cherry * 45 1.1 cherry * Redistribution and use in source and binary forms, with or without 46 1.1 cherry * modification, are permitted provided that the following conditions 47 1.1 cherry * are met: 48 1.1 cherry * 1. Redistributions of source code must retain the above copyright 49 1.1 cherry * notice, this list of conditions and the following disclaimer. 50 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 51 1.1 cherry * notice, this list of conditions and the following disclaimer in the 52 1.1 cherry * documentation and/or other materials provided with the distribution. 53 1.1 cherry * 3. Neither the name of the University nor the names of its contributors 54 1.1 cherry * may be used to endorse or promote products derived from this software 55 1.1 cherry * without specific prior written permission. 56 1.1 cherry * 57 1.1 cherry * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 1.1 cherry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 1.1 cherry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 1.1 cherry * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 1.1 cherry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 1.1 cherry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 1.1 cherry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 1.1 cherry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 1.1 cherry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 1.1 cherry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 1.1 cherry * SUCH DAMAGE. 68 1.1 cherry * 69 1.1 cherry * @(#)isa.c 7.2 (Berkeley) 5/13/91 70 1.1 cherry */ 71 1.1 cherry /*- 72 1.1 cherry * Copyright (c) 1993, 1994 Charles Hannum. 73 1.1 cherry * 74 1.1 cherry * Redistribution and use in source and binary forms, with or without 75 1.1 cherry * modification, are permitted provided that the following conditions 76 1.1 cherry * are met: 77 1.1 cherry * 1. Redistributions of source code must retain the above copyright 78 1.1 cherry * notice, this list of conditions and the following disclaimer. 79 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 80 1.1 cherry * notice, this list of conditions and the following disclaimer in the 81 1.1 cherry * documentation and/or other materials provided with the distribution. 82 1.1 cherry * 3. All advertising materials mentioning features or use of this software 83 1.1 cherry * must display the following acknowledgement: 84 1.1 cherry * This product includes software developed by the University of 85 1.1 cherry * California, Berkeley and its contributors. 86 1.1 cherry * 4. Neither the name of the University nor the names of its contributors 87 1.1 cherry * may be used to endorse or promote products derived from this software 88 1.1 cherry * without specific prior written permission. 89 1.1 cherry * 90 1.1 cherry * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 91 1.1 cherry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 92 1.1 cherry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 93 1.1 cherry * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 94 1.1 cherry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 95 1.1 cherry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 96 1.1 cherry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 97 1.1 cherry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 98 1.1 cherry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 99 1.1 cherry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 100 1.1 cherry * SUCH DAMAGE. 101 1.1 cherry * 102 1.1 cherry * @(#)isa.c 7.2 (Berkeley) 5/13/91 103 1.1 cherry */ 104 1.1 cherry 105 1.1 cherry #include <sys/cdefs.h> 106 1.25 andvar __KERNEL_RCSID(0, "$NetBSD: pintr.c,v 1.25 2025/08/18 20:59:54 andvar Exp $"); 107 1.1 cherry 108 1.1 cherry #include "opt_multiprocessor.h" 109 1.1 cherry #include "opt_xen.h" 110 1.1 cherry #include "isa.h" 111 1.1 cherry #include "pci.h" 112 1.20 jdolecek #include "opt_pci.h" 113 1.1 cherry 114 1.1 cherry #include <sys/param.h> 115 1.1 cherry #include <sys/systm.h> 116 1.1 cherry #include <sys/kernel.h> 117 1.1 cherry #include <sys/syslog.h> 118 1.1 cherry #include <sys/device.h> 119 1.1 cherry #include <sys/proc.h> 120 1.1 cherry #include <sys/errno.h> 121 1.1 cherry #include <sys/cpu.h> 122 1.1 cherry 123 1.1 cherry #include <uvm/uvm_extern.h> 124 1.1 cherry 125 1.1 cherry #include <machine/i8259.h> 126 1.1 cherry #include <machine/pio.h> 127 1.1 cherry #include <xen/evtchn.h> 128 1.1 cherry #include <xen/intr.h> 129 1.1 cherry 130 1.20 jdolecek #include <dev/pci/pcivar.h> 131 1.20 jdolecek 132 1.14 jdolecek #ifdef __HAVE_PCI_MSI_MSIX 133 1.14 jdolecek #include <x86/pci/msipic.h> 134 1.14 jdolecek #endif 135 1.14 jdolecek 136 1.1 cherry #include "acpica.h" 137 1.1 cherry #include "ioapic.h" 138 1.1 cherry #include "opt_mpbios.h" 139 1.1 cherry 140 1.1 cherry #if NIOAPIC > 0 141 1.1 cherry /* XXX: todo - compat with lapic.c and XEN for x2apic */ 142 1.1 cherry bool x2apic_mode __read_mostly = false; 143 1.1 cherry /* for x86/i8259.c */ 144 1.10 cherry struct intrstub legacy_stubs[NUM_LEGACY_IRQS] = {{0,0,0}}; 145 1.1 cherry /* for x86/ioapic.c */ 146 1.10 cherry struct intrstub ioapic_edge_stubs[MAX_INTR_SOURCES] = {{0,0,0}}; 147 1.10 cherry struct intrstub ioapic_level_stubs[MAX_INTR_SOURCES] = {{0,0,0}}; 148 1.10 cherry struct intrstub x2apic_edge_stubs[MAX_INTR_SOURCES] = {{0,0,0}}; 149 1.10 cherry struct intrstub x2apic_level_stubs[MAX_INTR_SOURCES] = {{0,0,0}}; 150 1.1 cherry #include <machine/i82093var.h> 151 1.10 cherry #endif /* NIOAPIC */ 152 1.10 cherry 153 1.14 jdolecek // XXX NR_EVENT_CHANNELS is 2048, use some sparse structure? 154 1.25 andvar short irq2port[NR_EVENT_CHANNELS] = {0}; /* actually port + 1, so that 0 is invalid */ 155 1.10 cherry 156 1.1 cherry #if NACPICA > 0 157 1.1 cherry #include <machine/mpconfig.h> 158 1.1 cherry #include <machine/mpacpi.h> 159 1.1 cherry #endif 160 1.1 cherry #ifdef MPBIOS 161 1.1 cherry #include <machine/mpbiosvar.h> 162 1.1 cherry #endif 163 1.1 cherry 164 1.1 cherry #if NPCI > 0 165 1.1 cherry #include <dev/pci/ppbreg.h> 166 1.1 cherry #endif 167 1.1 cherry 168 1.1 cherry #if defined(DOM0OPS) || NPCI > 0 169 1.18 jdolecek 170 1.19 jdolecek #ifdef __HAVE_PCI_MSI_MSIX 171 1.21 bouyer int 172 1.21 bouyer xen_map_msi_pirq(struct pic *pic, int count) 173 1.18 jdolecek { 174 1.18 jdolecek struct physdev_map_pirq map_irq; 175 1.21 bouyer const struct msipic_pci_info *msi_i = msipic_get_pci_info(pic); 176 1.21 bouyer int i; 177 1.18 jdolecek int ret; 178 1.18 jdolecek 179 1.18 jdolecek if (count == -1) 180 1.21 bouyer count = msi_i->mp_veccnt; 181 1.18 jdolecek KASSERT(count > 0); 182 1.18 jdolecek 183 1.21 bouyer KASSERT(pic->pic_type == PIC_MSI); 184 1.21 bouyer 185 1.18 jdolecek memset(&map_irq, 0, sizeof(map_irq)); 186 1.18 jdolecek map_irq.domid = DOMID_SELF; 187 1.18 jdolecek map_irq.type = MAP_PIRQ_TYPE_MSI_SEG; 188 1.18 jdolecek map_irq.index = -1; 189 1.18 jdolecek map_irq.pirq = -1; 190 1.21 bouyer map_irq.bus = msi_i->mp_bus; 191 1.21 bouyer map_irq.devfn = (msi_i->mp_dev << 3) | msi_i->mp_fun; 192 1.21 bouyer aprint_debug("xen_map_msi_pirq bus %d devfn 0x%x (%d %d) entry_nr %d", 193 1.21 bouyer map_irq.bus, map_irq.devfn, msi_i->mp_dev, msi_i->mp_fun, 194 1.21 bouyer map_irq.entry_nr); 195 1.18 jdolecek map_irq.entry_nr = count; 196 1.21 bouyer if (msi_i->mp_veccnt > 1) { 197 1.18 jdolecek map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI; 198 1.18 jdolecek } 199 1.18 jdolecek 200 1.18 jdolecek ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 201 1.18 jdolecek 202 1.18 jdolecek if (ret == 0) { 203 1.18 jdolecek KASSERT(map_irq.entry_nr == count); 204 1.21 bouyer aprint_debug(" pirq(s)"); 205 1.21 bouyer for (i = 0; i < count; i++) { 206 1.21 bouyer msi_i->mp_xen_pirq[i] = map_irq.pirq + i; 207 1.21 bouyer aprint_debug(" %d", msi_i->mp_xen_pirq[i]); 208 1.21 bouyer } 209 1.21 bouyer aprint_debug("\n"); 210 1.21 bouyer } else { 211 1.24 bouyer aprint_debug(" fail %d\n", ret); 212 1.18 jdolecek } 213 1.18 jdolecek return ret; 214 1.18 jdolecek } 215 1.18 jdolecek 216 1.18 jdolecek int 217 1.21 bouyer xen_map_msix_pirq(struct pic *pic, int count) 218 1.18 jdolecek { 219 1.21 bouyer struct physdev_map_pirq map_irq; 220 1.21 bouyer const struct msipic_pci_info *msi_i = msipic_get_pci_info(pic); 221 1.21 bouyer int i; 222 1.21 bouyer int ret; 223 1.18 jdolecek 224 1.21 bouyer if (count == -1) 225 1.21 bouyer count = msi_i->mp_veccnt; 226 1.21 bouyer KASSERT(count > 0); 227 1.21 bouyer 228 1.21 bouyer KASSERT(pic->pic_type == PIC_MSIX); 229 1.21 bouyer 230 1.21 bouyer memset(&map_irq, 0, sizeof(map_irq)); 231 1.21 bouyer map_irq.domid = DOMID_SELF; 232 1.21 bouyer map_irq.type = MAP_PIRQ_TYPE_MSI_SEG; 233 1.21 bouyer map_irq.index = -1; 234 1.21 bouyer map_irq.pirq = -1; 235 1.21 bouyer map_irq.bus = msi_i->mp_bus; 236 1.21 bouyer map_irq.devfn = (msi_i->mp_dev << 3) | msi_i->mp_fun; 237 1.22 bouyer map_irq.table_base = msi_i->mp_table_base; 238 1.22 bouyer 239 1.23 bouyer aprint_debug("xen_map_msix_pirq bus %d devfn 0x%x (%d %d) count %d", 240 1.21 bouyer map_irq.bus, map_irq.devfn, msi_i->mp_dev, msi_i->mp_fun, 241 1.23 bouyer count); 242 1.21 bouyer 243 1.21 bouyer for (i = 0; i < count; i++) { 244 1.21 bouyer map_irq.entry_nr = i; 245 1.21 bouyer map_irq.pirq = -1; 246 1.21 bouyer aprint_debug(" map %d", i); 247 1.21 bouyer ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 248 1.21 bouyer if (ret) { 249 1.24 bouyer aprint_debug(" fail %d\n", ret); 250 1.21 bouyer goto fail; 251 1.21 bouyer } 252 1.21 bouyer msi_i->mp_xen_pirq[i] = map_irq.pirq; 253 1.21 bouyer aprint_debug("->%d", msi_i->mp_xen_pirq[i]); 254 1.21 bouyer } 255 1.21 bouyer aprint_debug("\n"); 256 1.21 bouyer return 0; 257 1.18 jdolecek 258 1.21 bouyer fail: 259 1.21 bouyer i--; 260 1.21 bouyer while(i >= 0) { 261 1.18 jdolecek struct physdev_unmap_pirq unmap_irq; 262 1.18 jdolecek unmap_irq.domid = DOMID_SELF; 263 1.21 bouyer unmap_irq.pirq = msi_i->mp_xen_pirq[i]; 264 1.18 jdolecek 265 1.18 jdolecek (void)HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); 266 1.21 bouyer msi_i->mp_xen_pirq[i] = 0; 267 1.18 jdolecek } 268 1.21 bouyer return ret; 269 1.21 bouyer } 270 1.18 jdolecek 271 1.21 bouyer void 272 1.21 bouyer xen_pci_msi_release(struct pic *pic, int count) 273 1.21 bouyer { 274 1.21 bouyer const struct msipic_pci_info *msi_i = msipic_get_pci_info(pic); 275 1.21 bouyer KASSERT(count == msi_i->mp_veccnt); 276 1.21 bouyer for (int i = 0; i < count; i++) { 277 1.21 bouyer struct physdev_unmap_pirq unmap_irq; 278 1.21 bouyer unmap_irq.domid = DOMID_SELF; 279 1.21 bouyer unmap_irq.pirq = msi_i->mp_xen_pirq[i]; 280 1.21 bouyer 281 1.21 bouyer (void)HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); 282 1.21 bouyer msi_i->mp_xen_pirq[i] = 0; 283 1.21 bouyer } 284 1.18 jdolecek } 285 1.21 bouyer 286 1.19 jdolecek #endif /* __HAVE_PCI_MSI_MSIX */ 287 1.18 jdolecek 288 1.7 cherry /* 289 1.7 cherry * This function doesn't "allocate" anything. It merely translates our 290 1.7 cherry * understanding of PIC to the XEN 'gsi' namespace. In the case of 291 1.7 cherry * MSIs, pirq == irq. In the case of everything else, the hypervisor 292 1.7 cherry * doesn't really care, so we just use the native conventions that 293 1.7 cherry * have been setup during boot by mpbios.c/mpacpi.c 294 1.7 cherry */ 295 1.7 cherry int 296 1.7 cherry xen_pic_to_gsi(struct pic *pic, int pin) 297 1.7 cherry { 298 1.14 jdolecek int ret; 299 1.7 cherry int gsi; 300 1.7 cherry 301 1.7 cherry KASSERT(pic != NULL); 302 1.5 cherry 303 1.1 cherry /* 304 1.7 cherry * We assume that mpbios/mpacpi have done the right thing. 305 1.7 cherry * If so, legacy_irq should identity map correctly to gsi. 306 1.1 cherry */ 307 1.7 cherry gsi = pic->pic_vecbase + pin; 308 1.14 jdolecek KASSERT(gsi < NR_EVENT_CHANNELS); 309 1.7 cherry 310 1.7 cherry switch (pic->pic_type) { 311 1.7 cherry case PIC_I8259: 312 1.7 cherry KASSERT(gsi < 16); 313 1.14 jdolecek /* FALLTHROUGH */ 314 1.14 jdolecek case PIC_IOAPIC: 315 1.14 jdolecek { 316 1.14 jdolecek KASSERT(gsi < 255); 317 1.14 jdolecek 318 1.15 jdolecek if (irq2port[gsi] != 0) { 319 1.15 jdolecek /* Already mapped the shared interrupt */ 320 1.15 jdolecek break; 321 1.15 jdolecek } 322 1.15 jdolecek 323 1.17 jdolecek struct physdev_irq irq_op; 324 1.17 jdolecek memset(&irq_op, 0, sizeof(irq_op)); 325 1.17 jdolecek irq_op.irq = gsi; 326 1.17 jdolecek ret = HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, 327 1.17 jdolecek &irq_op); 328 1.17 jdolecek if (ret < 0) { 329 1.17 jdolecek panic("physdev_op(PHYSDEVOP_alloc_irq_vector) %d" 330 1.17 jdolecek " fail %d", gsi, ret); 331 1.17 jdolecek } 332 1.21 bouyer aprint_debug("xen_pic_to_gsi %s pin %d gsi %d allocated %d\n", 333 1.21 bouyer (pic->pic_type == PIC_IOAPIC) ? "ioapic" : "i8259", 334 1.21 bouyer pin, gsi, irq_op.vector); 335 1.21 bouyer 336 1.17 jdolecek KASSERT(irq_op.vector == gsi); 337 1.7 cherry break; 338 1.14 jdolecek } 339 1.14 jdolecek case PIC_MSI: 340 1.14 jdolecek case PIC_MSIX: 341 1.14 jdolecek #ifdef __HAVE_PCI_MSI_MSIX 342 1.21 bouyer { 343 1.21 bouyer const struct msipic_pci_info *msi_i = msipic_get_pci_info(pic); 344 1.21 bouyer KASSERT(pin < msi_i->mp_veccnt); 345 1.21 bouyer gsi = msi_i->mp_xen_pirq[pin]; 346 1.21 bouyer aprint_debug("xen_pic_to_gsi %s pin %d gsi %d\n", 347 1.21 bouyer (pic->pic_type == PIC_MSI) ? "MSI" : "MSIX", 348 1.21 bouyer pin, gsi); 349 1.7 cherry break; 350 1.21 bouyer } 351 1.14 jdolecek #endif 352 1.14 jdolecek default: 353 1.14 jdolecek panic("unknown pic_type %d", pic->pic_type); 354 1.7 cherry break; 355 1.1 cherry } 356 1.7 cherry 357 1.7 cherry return gsi; 358 1.1 cherry } 359 1.7 cherry 360 1.7 cherry 361 1.1 cherry #endif /* defined(DOM0OPS) || NPCI > 0 */ 362