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