1 1.31 riastrad /* $NetBSD: xen_intr.c,v 1.31 2023/02/25 00:32:13 riastradh Exp $ */ 2 1.2 bouyer 3 1.2 bouyer /*- 4 1.2 bouyer * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 1.2 bouyer * All rights reserved. 6 1.2 bouyer * 7 1.2 bouyer * This code is derived from software contributed to The NetBSD Foundation 8 1.2 bouyer * by Charles M. Hannum, and by Jason R. Thorpe. 9 1.2 bouyer * 10 1.2 bouyer * Redistribution and use in source and binary forms, with or without 11 1.2 bouyer * modification, are permitted provided that the following conditions 12 1.2 bouyer * are met: 13 1.2 bouyer * 1. Redistributions of source code must retain the above copyright 14 1.2 bouyer * notice, this list of conditions and the following disclaimer. 15 1.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 bouyer * notice, this list of conditions and the following disclaimer in the 17 1.2 bouyer * documentation and/or other materials provided with the distribution. 18 1.2 bouyer * 19 1.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 bouyer * POSSIBILITY OF SUCH DAMAGE. 30 1.2 bouyer */ 31 1.2 bouyer 32 1.2 bouyer #include <sys/cdefs.h> 33 1.31 riastrad __KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.31 2023/02/25 00:32:13 riastradh Exp $"); 34 1.19 ad 35 1.19 ad #include "opt_multiprocessor.h" 36 1.28 jdolecek #include "opt_pci.h" 37 1.2 bouyer 38 1.2 bouyer #include <sys/param.h> 39 1.10 cherry #include <sys/kernel.h> 40 1.10 cherry #include <sys/kmem.h> 41 1.11 cherry #include <sys/cpu.h> 42 1.19 ad #include <sys/device.h> 43 1.11 cherry 44 1.24 bouyer #include <xen/intr.h> 45 1.10 cherry #include <xen/evtchn.h> 46 1.15 cherry #include <xen/xenfunc.h> 47 1.2 bouyer 48 1.12 cherry #include <uvm/uvm.h> 49 1.12 cherry 50 1.2 bouyer #include <machine/cpu.h> 51 1.2 bouyer #include <machine/intr.h> 52 1.2 bouyer 53 1.11 cherry #include "acpica.h" 54 1.11 cherry #include "ioapic.h" 55 1.11 cherry #include "lapic.h" 56 1.11 cherry #include "pci.h" 57 1.11 cherry 58 1.11 cherry #if NACPICA > 0 59 1.11 cherry #include <dev/acpi/acpivar.h> 60 1.11 cherry #endif 61 1.11 cherry 62 1.11 cherry #if NIOAPIC > 0 || NACPICA > 0 63 1.11 cherry #include <machine/i82093var.h> 64 1.11 cherry #endif 65 1.11 cherry 66 1.11 cherry #if NLAPIC > 0 67 1.11 cherry #include <machine/i82489var.h> 68 1.11 cherry #endif 69 1.11 cherry 70 1.11 cherry #if NPCI > 0 71 1.11 cherry #include <dev/pci/ppbreg.h> 72 1.23 jdolecek #ifdef __HAVE_PCI_MSI_MSIX 73 1.23 jdolecek #include <x86/pci/msipic.h> 74 1.23 jdolecek #include <x86/pci/pci_msi_machdep.h> 75 1.23 jdolecek #endif 76 1.11 cherry #endif 77 1.11 cherry 78 1.19 ad #if defined(MULTIPROCESSOR) 79 1.19 ad static const char *xen_ipi_names[XEN_NIPIS] = XEN_IPI_NAMES; 80 1.19 ad #endif 81 1.19 ad 82 1.17 cherry #if !defined(XENPVHVM) 83 1.2 bouyer void 84 1.16 bouyer x86_disable_intr(void) 85 1.2 bouyer { 86 1.31 riastrad 87 1.31 riastrad kpreempt_disable(); 88 1.16 bouyer curcpu()->ci_vcpu->evtchn_upcall_mask = 1; 89 1.31 riastrad kpreempt_enable(); 90 1.31 riastrad 91 1.31 riastrad __insn_barrier(); 92 1.2 bouyer } 93 1.2 bouyer 94 1.2 bouyer void 95 1.16 bouyer x86_enable_intr(void) 96 1.2 bouyer { 97 1.31 riastrad struct cpu_info *ci; 98 1.31 riastrad 99 1.16 bouyer __insn_barrier(); 100 1.31 riastrad 101 1.31 riastrad kpreempt_disable(); 102 1.31 riastrad ci = curcpu(); 103 1.31 riastrad ci->ci_vcpu->evtchn_upcall_mask = 0; 104 1.31 riastrad __insn_barrier(); 105 1.31 riastrad if (__predict_false(ci->ci_vcpu->evtchn_upcall_pending)) 106 1.16 bouyer hypervisor_force_callback(); 107 1.31 riastrad kpreempt_enable(); 108 1.2 bouyer } 109 1.2 bouyer 110 1.17 cherry #endif /* !XENPVHVM */ 111 1.17 cherry 112 1.2 bouyer u_long 113 1.11 cherry xen_read_psl(void) 114 1.2 bouyer { 115 1.31 riastrad u_long psl; 116 1.31 riastrad 117 1.31 riastrad kpreempt_disable(); 118 1.31 riastrad psl = curcpu()->ci_vcpu->evtchn_upcall_mask; 119 1.31 riastrad kpreempt_enable(); 120 1.2 bouyer 121 1.31 riastrad return psl; 122 1.2 bouyer } 123 1.2 bouyer 124 1.2 bouyer void 125 1.11 cherry xen_write_psl(u_long psl) 126 1.2 bouyer { 127 1.31 riastrad struct cpu_info *ci; 128 1.2 bouyer 129 1.31 riastrad kpreempt_disable(); 130 1.31 riastrad ci = curcpu(); 131 1.4 cegger ci->ci_vcpu->evtchn_upcall_mask = psl; 132 1.31 riastrad __insn_barrier(); 133 1.31 riastrad if (__predict_false(ci->ci_vcpu->evtchn_upcall_pending) && psl == 0) 134 1.2 bouyer hypervisor_force_callback(); 135 1.31 riastrad kpreempt_enable(); 136 1.2 bouyer } 137 1.10 cherry 138 1.10 cherry void * 139 1.10 cherry xen_intr_establish(int legacy_irq, struct pic *pic, int pin, 140 1.10 cherry int type, int level, int (*handler)(void *), void *arg, 141 1.10 cherry bool known_mpsafe) 142 1.10 cherry { 143 1.10 cherry 144 1.10 cherry return xen_intr_establish_xname(legacy_irq, pic, pin, type, level, 145 1.10 cherry handler, arg, known_mpsafe, "XEN"); 146 1.10 cherry } 147 1.10 cherry 148 1.10 cherry void * 149 1.10 cherry xen_intr_establish_xname(int legacy_irq, struct pic *pic, int pin, 150 1.10 cherry int type, int level, int (*handler)(void *), void *arg, 151 1.10 cherry bool known_mpsafe, const char *xname) 152 1.10 cherry { 153 1.10 cherry const char *intrstr; 154 1.10 cherry char intrstr_buf[INTRIDBUF]; 155 1.10 cherry 156 1.10 cherry if (pic->pic_type == PIC_XEN) { 157 1.10 cherry struct intrhand *rih; 158 1.10 cherry 159 1.10 cherry intrstr = intr_create_intrid(legacy_irq, pic, pin, intrstr_buf, 160 1.10 cherry sizeof(intrstr_buf)); 161 1.10 cherry 162 1.24 bouyer rih = event_set_handler(pin, handler, arg, level, 163 1.27 bouyer intrstr, xname, known_mpsafe, NULL); 164 1.10 cherry 165 1.10 cherry if (rih == NULL) { 166 1.24 bouyer printf("%s: can't establish interrupt\n", __func__); 167 1.10 cherry return NULL; 168 1.10 cherry } 169 1.10 cherry 170 1.10 cherry return rih; 171 1.10 cherry } /* Else we assume pintr */ 172 1.10 cherry 173 1.14 cherry #if (NPCI > 0 || NISA > 0) && defined(XENPV) /* XXX: support PVHVM pirq */ 174 1.10 cherry struct pintrhand *pih; 175 1.10 cherry int gsi; 176 1.25 jdolecek int evtchn; 177 1.27 bouyer /* the hack below is from x86's intr_establish_xname() */ 178 1.27 bouyer bool mpsafe = (known_mpsafe || level != IPL_VM); 179 1.10 cherry 180 1.10 cherry KASSERTMSG(legacy_irq == -1 || (0 <= legacy_irq && legacy_irq < NUM_XEN_IRQS), 181 1.10 cherry "bad legacy IRQ value: %d", legacy_irq); 182 1.10 cherry KASSERTMSG(!(legacy_irq == -1 && pic == &i8259_pic), 183 1.10 cherry "non-legacy IRQon i8259 "); 184 1.10 cherry 185 1.10 cherry gsi = xen_pic_to_gsi(pic, pin); 186 1.30 bouyer if (gsi < 0) 187 1.30 bouyer return NULL; 188 1.25 jdolecek KASSERTMSG(gsi < NR_EVENT_CHANNELS, "gsi %d >= NR_EVENT_CHANNELS %u", 189 1.25 jdolecek gsi, (int)NR_EVENT_CHANNELS); 190 1.10 cherry 191 1.10 cherry intrstr = intr_create_intrid(gsi, pic, pin, intrstr_buf, 192 1.10 cherry sizeof(intrstr_buf)); 193 1.10 cherry 194 1.10 cherry if (irq2port[gsi] == 0) { 195 1.10 cherry extern struct cpu_info phycpu_info_primary; /* XXX */ 196 1.10 cherry struct cpu_info *ci = &phycpu_info_primary; 197 1.10 cherry 198 1.25 jdolecek pic->pic_addroute(pic, ci, pin, gsi, type); 199 1.10 cherry 200 1.10 cherry evtchn = bind_pirq_to_evtch(gsi); 201 1.10 cherry KASSERT(evtchn > 0); 202 1.10 cherry KASSERT(evtchn < NR_EVENT_CHANNELS); 203 1.10 cherry irq2port[gsi] = evtchn + 1; 204 1.10 cherry xen_atomic_set_bit(&ci->ci_evtmask[0], evtchn); 205 1.10 cherry } else { 206 1.10 cherry /* 207 1.10 cherry * Shared interrupt - we can't rebind. 208 1.10 cherry * The port is shared instead. 209 1.10 cherry */ 210 1.10 cherry evtchn = irq2port[gsi] - 1; 211 1.10 cherry } 212 1.10 cherry 213 1.10 cherry pih = pirq_establish(gsi, evtchn, handler, arg, level, 214 1.27 bouyer intrstr, xname, mpsafe); 215 1.24 bouyer pih->pic = pic; 216 1.30 bouyer if (msipic_is_msi_pic(pic)) 217 1.30 bouyer pic->pic_hwunmask(pic, pin); 218 1.10 cherry return pih; 219 1.10 cherry #endif /* NPCI > 0 || NISA > 0 */ 220 1.10 cherry 221 1.10 cherry /* FALLTHROUGH */ 222 1.10 cherry return NULL; 223 1.10 cherry } 224 1.10 cherry 225 1.10 cherry /* 226 1.18 thorpej * Mask an interrupt source. 227 1.18 thorpej */ 228 1.18 thorpej void 229 1.18 thorpej xen_intr_mask(struct intrhand *ih) 230 1.18 thorpej { 231 1.18 thorpej /* XXX */ 232 1.18 thorpej panic("xen_intr_mask: not yet implemented."); 233 1.18 thorpej } 234 1.18 thorpej 235 1.18 thorpej /* 236 1.18 thorpej * Unmask an interrupt source. 237 1.18 thorpej */ 238 1.18 thorpej void 239 1.18 thorpej xen_intr_unmask(struct intrhand *ih) 240 1.18 thorpej { 241 1.18 thorpej /* XXX */ 242 1.18 thorpej panic("xen_intr_unmask: not yet implemented."); 243 1.18 thorpej } 244 1.18 thorpej 245 1.18 thorpej /* 246 1.10 cherry * Deregister an interrupt handler. 247 1.10 cherry */ 248 1.10 cherry void 249 1.10 cherry xen_intr_disestablish(struct intrhand *ih) 250 1.10 cherry { 251 1.10 cherry 252 1.24 bouyer if (ih->ih_pic->pic_type == PIC_XEN) { 253 1.10 cherry event_remove_handler(ih->ih_pin, ih->ih_realfun, 254 1.10 cherry ih->ih_realarg); 255 1.24 bouyer /* event_remove_handler frees ih */ 256 1.10 cherry return; 257 1.10 cherry } 258 1.26 bouyer #if defined(DOM0OPS) && defined(XENPV) 259 1.10 cherry /* 260 1.10 cherry * Cache state, to prevent a use after free situation with 261 1.10 cherry * ih. 262 1.10 cherry */ 263 1.10 cherry 264 1.10 cherry struct pintrhand *pih = (struct pintrhand *)ih; 265 1.10 cherry 266 1.10 cherry int pirq = pih->pirq; 267 1.10 cherry int port = pih->evtch; 268 1.10 cherry KASSERT(irq2port[pirq] != 0); 269 1.10 cherry 270 1.10 cherry pirq_disestablish(pih); 271 1.10 cherry 272 1.10 cherry if (evtsource[port] == NULL) { 273 1.10 cherry /* 274 1.10 cherry * Last handler was removed by 275 1.10 cherry * event_remove_handler(). 276 1.10 cherry * 277 1.10 cherry * We can safely unbind the pirq now. 278 1.10 cherry */ 279 1.10 cherry 280 1.10 cherry port = unbind_pirq_from_evtch(pirq); 281 1.10 cherry KASSERT(port == pih->evtch); 282 1.10 cherry irq2port[pirq] = 0; 283 1.10 cherry } 284 1.10 cherry #endif 285 1.10 cherry return; 286 1.10 cherry } 287 1.10 cherry 288 1.11 cherry /* MI interface for kern_cpu.c */ 289 1.11 cherry void xen_cpu_intr_redistribute(void); 290 1.11 cherry 291 1.11 cherry void 292 1.11 cherry xen_cpu_intr_redistribute(void) 293 1.11 cherry { 294 1.11 cherry KASSERT(mutex_owned(&cpu_lock)); 295 1.11 cherry KASSERT(mp_online); 296 1.11 cherry 297 1.11 cherry return; 298 1.11 cherry } 299 1.11 cherry 300 1.11 cherry /* MD - called by x86/cpu.c */ 301 1.12 cherry #if defined(INTRSTACKSIZE) 302 1.12 cherry static inline bool 303 1.12 cherry redzone_const_or_false(bool x) 304 1.12 cherry { 305 1.12 cherry #ifdef DIAGNOSTIC 306 1.12 cherry return x; 307 1.12 cherry #else 308 1.12 cherry return false; 309 1.12 cherry #endif /* !DIAGNOSTIC */ 310 1.12 cherry } 311 1.12 cherry 312 1.12 cherry static inline int 313 1.12 cherry redzone_const_or_zero(int x) 314 1.12 cherry { 315 1.12 cherry return redzone_const_or_false(true) ? x : 0; 316 1.12 cherry } 317 1.12 cherry #endif 318 1.12 cherry 319 1.14 cherry void xen_cpu_intr_init(struct cpu_info *); 320 1.11 cherry void 321 1.14 cherry xen_cpu_intr_init(struct cpu_info *ci) 322 1.11 cherry { 323 1.24 bouyer #if defined(__HAVE_PREEMPTION) 324 1.24 bouyer x86_init_preempt(ci); 325 1.24 bouyer #endif 326 1.24 bouyer x86_intr_calculatemasks(ci); 327 1.11 cherry 328 1.11 cherry #if defined(INTRSTACKSIZE) 329 1.11 cherry vaddr_t istack; 330 1.11 cherry 331 1.11 cherry /* 332 1.11 cherry * If the red zone is activated, protect both the top and 333 1.11 cherry * the bottom of the stack with an unmapped page. 334 1.11 cherry */ 335 1.11 cherry istack = uvm_km_alloc(kernel_map, 336 1.11 cherry INTRSTACKSIZE + redzone_const_or_zero(2 * PAGE_SIZE), 0, 337 1.11 cherry UVM_KMF_WIRED|UVM_KMF_ZERO); 338 1.11 cherry if (redzone_const_or_false(true)) { 339 1.11 cherry pmap_kremove(istack, PAGE_SIZE); 340 1.11 cherry pmap_kremove(istack + INTRSTACKSIZE + PAGE_SIZE, PAGE_SIZE); 341 1.11 cherry pmap_update(pmap_kernel()); 342 1.11 cherry } 343 1.11 cherry 344 1.11 cherry /* 345 1.11 cherry * 33 used to be 1. Arbitrarily reserve 32 more register_t's 346 1.11 cherry * of space for ddb(4) to examine some subroutine arguments 347 1.11 cherry * and to hunt for the next stack frame. 348 1.11 cherry */ 349 1.11 cherry ci->ci_intrstack = (char *)istack + redzone_const_or_zero(PAGE_SIZE) + 350 1.11 cherry INTRSTACKSIZE - 33 * sizeof(register_t); 351 1.11 cherry #endif 352 1.11 cherry 353 1.19 ad #ifdef MULTIPROCESSOR 354 1.24 bouyer for (int i = 0; i < XEN_NIPIS; i++) 355 1.19 ad evcnt_attach_dynamic(&ci->ci_ipi_events[i], EVCNT_TYPE_MISC, 356 1.19 ad NULL, device_xname(ci->ci_dev), xen_ipi_names[i]); 357 1.19 ad #endif 358 1.19 ad 359 1.11 cherry ci->ci_idepth = -1; 360 1.11 cherry } 361 1.11 cherry 362 1.11 cherry /* 363 1.11 cherry * Everything below from here is duplicated from x86/intr.c 364 1.11 cherry * When intr.c and xen_intr.c are unified, these will need to be 365 1.11 cherry * merged. 366 1.11 cherry */ 367 1.11 cherry 368 1.11 cherry u_int xen_cpu_intr_count(struct cpu_info *ci); 369 1.11 cherry 370 1.11 cherry u_int 371 1.11 cherry xen_cpu_intr_count(struct cpu_info *ci) 372 1.11 cherry { 373 1.11 cherry 374 1.11 cherry KASSERT(ci->ci_nintrhand >= 0); 375 1.11 cherry 376 1.11 cherry return ci->ci_nintrhand; 377 1.11 cherry } 378 1.11 cherry 379 1.11 cherry static const char * 380 1.11 cherry xen_intr_string(int port, char *buf, size_t len, struct pic *pic) 381 1.11 cherry { 382 1.11 cherry KASSERT(pic->pic_type == PIC_XEN); 383 1.11 cherry 384 1.11 cherry KASSERT(port >= 0); 385 1.11 cherry KASSERT(port < NR_EVENT_CHANNELS); 386 1.11 cherry 387 1.24 bouyer snprintf(buf, len, "%s chan %d", pic->pic_name, port); 388 1.11 cherry 389 1.11 cherry return buf; 390 1.11 cherry } 391 1.11 cherry 392 1.11 cherry static const char * 393 1.11 cherry legacy_intr_string(int ih, char *buf, size_t len, struct pic *pic) 394 1.11 cherry { 395 1.11 cherry int legacy_irq; 396 1.11 cherry 397 1.11 cherry KASSERT(pic->pic_type == PIC_I8259); 398 1.11 cherry #if NLAPIC > 0 399 1.11 cherry KASSERT(APIC_IRQ_ISLEGACY(ih)); 400 1.11 cherry 401 1.11 cherry legacy_irq = APIC_IRQ_LEGACY_IRQ(ih); 402 1.11 cherry #else 403 1.11 cherry legacy_irq = ih; 404 1.11 cherry #endif 405 1.11 cherry KASSERT(legacy_irq >= 0 && legacy_irq < 16); 406 1.11 cherry 407 1.11 cherry snprintf(buf, len, "%s pin %d", pic->pic_name, legacy_irq); 408 1.11 cherry 409 1.11 cherry return buf; 410 1.11 cherry } 411 1.11 cherry 412 1.14 cherry const char * xintr_string(intr_handle_t ih, char *buf, size_t len); 413 1.14 cherry 414 1.11 cherry const char * 415 1.14 cherry xintr_string(intr_handle_t ih, char *buf, size_t len) 416 1.11 cherry { 417 1.11 cherry #if NIOAPIC > 0 418 1.11 cherry struct ioapic_softc *pic; 419 1.11 cherry #endif 420 1.11 cherry 421 1.11 cherry if (ih == 0) 422 1.11 cherry panic("%s: bogus handle 0x%" PRIx64, __func__, ih); 423 1.11 cherry 424 1.11 cherry #if NIOAPIC > 0 425 1.11 cherry if (ih & APIC_INT_VIA_APIC) { 426 1.11 cherry pic = ioapic_find(APIC_IRQ_APIC(ih)); 427 1.11 cherry if (pic != NULL) { 428 1.11 cherry snprintf(buf, len, "%s pin %d", 429 1.11 cherry device_xname(pic->sc_dev), APIC_IRQ_PIN(ih)); 430 1.11 cherry } else { 431 1.11 cherry snprintf(buf, len, 432 1.11 cherry "apic %d int %d (irq %d)", 433 1.11 cherry APIC_IRQ_APIC(ih), 434 1.11 cherry APIC_IRQ_PIN(ih), 435 1.11 cherry APIC_IRQ_LEGACY_IRQ(ih)); 436 1.11 cherry } 437 1.11 cherry } else 438 1.11 cherry snprintf(buf, len, "irq %d", APIC_IRQ_LEGACY_IRQ(ih)); 439 1.11 cherry 440 1.11 cherry #elif NLAPIC > 0 441 1.14 cherry snprintf(buf, len, "irq %d", APIC_IRQ_LEGACY_IRQ(ih)); 442 1.11 cherry #else 443 1.11 cherry snprintf(buf, len, "irq %d", (int) ih); 444 1.11 cherry #endif 445 1.11 cherry return buf; 446 1.11 cherry 447 1.11 cherry } 448 1.11 cherry 449 1.11 cherry /* 450 1.11 cherry * Create an interrupt id such as "ioapic0 pin 9". This interrupt id is used 451 1.11 cherry * by MI code and intrctl(8). 452 1.11 cherry */ 453 1.14 cherry const char * xen_intr_create_intrid(int legacy_irq, struct pic *pic, 454 1.14 cherry int pin, char *buf, size_t len); 455 1.14 cherry 456 1.11 cherry const char * 457 1.14 cherry xen_intr_create_intrid(int legacy_irq, struct pic *pic, int pin, char *buf, size_t len) 458 1.11 cherry { 459 1.11 cherry int ih = 0; 460 1.11 cherry 461 1.24 bouyer #if NPCI > 0 && defined(XENPV) 462 1.11 cherry #if defined(__HAVE_PCI_MSI_MSIX) 463 1.11 cherry if ((pic->pic_type == PIC_MSI) || (pic->pic_type == PIC_MSIX)) { 464 1.11 cherry uint64_t pih; 465 1.11 cherry int dev, vec; 466 1.11 cherry 467 1.11 cherry dev = msipic_get_devid(pic); 468 1.11 cherry vec = pin; 469 1.11 cherry pih = __SHIFTIN((uint64_t)dev, MSI_INT_DEV_MASK) 470 1.11 cherry | __SHIFTIN((uint64_t)vec, MSI_INT_VEC_MASK) 471 1.11 cherry | APIC_INT_VIA_MSI; 472 1.11 cherry if (pic->pic_type == PIC_MSI) 473 1.11 cherry MSI_INT_MAKE_MSI(pih); 474 1.11 cherry else if (pic->pic_type == PIC_MSIX) 475 1.11 cherry MSI_INT_MAKE_MSIX(pih); 476 1.11 cherry 477 1.11 cherry return x86_pci_msi_string(NULL, pih, buf, len); 478 1.11 cherry } 479 1.11 cherry #endif /* __HAVE_PCI_MSI_MSIX */ 480 1.11 cherry #endif 481 1.11 cherry 482 1.11 cherry if (pic->pic_type == PIC_XEN) { 483 1.11 cherry ih = pin; /* Port == pin */ 484 1.11 cherry return xen_intr_string(pin, buf, len, pic); 485 1.11 cherry } 486 1.11 cherry 487 1.11 cherry /* 488 1.29 andvar * If the device is pci, "legacy_irq" is always -1. Least 8 bit of "ih" 489 1.11 cherry * is only used in intr_string() to show the irq number. 490 1.11 cherry * If the device is "legacy"(such as floppy), it should not use 491 1.11 cherry * intr_string(). 492 1.11 cherry */ 493 1.11 cherry if (pic->pic_type == PIC_I8259) { 494 1.11 cherry ih = legacy_irq; 495 1.11 cherry return legacy_intr_string(ih, buf, len, pic); 496 1.11 cherry } 497 1.11 cherry 498 1.11 cherry #if NIOAPIC > 0 || NACPICA > 0 499 1.11 cherry ih = ((pic->pic_apicid << APIC_INT_APIC_SHIFT) & APIC_INT_APIC_MASK) 500 1.11 cherry | ((pin << APIC_INT_PIN_SHIFT) & APIC_INT_PIN_MASK); 501 1.11 cherry if (pic->pic_type == PIC_IOAPIC) { 502 1.11 cherry ih |= APIC_INT_VIA_APIC; 503 1.11 cherry } 504 1.11 cherry ih |= pin; 505 1.11 cherry return intr_string(ih, buf, len); 506 1.11 cherry #endif 507 1.11 cherry 508 1.11 cherry return NULL; /* No pic found! */ 509 1.11 cherry } 510 1.11 cherry 511 1.23 jdolecek static struct intrsource xen_dummy_intrsource; 512 1.23 jdolecek 513 1.23 jdolecek struct intrsource * 514 1.23 jdolecek xen_intr_allocate_io_intrsource(const char *intrid) 515 1.23 jdolecek { 516 1.23 jdolecek /* Nothing to do, required by MSI code */ 517 1.23 jdolecek return &xen_dummy_intrsource; 518 1.23 jdolecek } 519 1.23 jdolecek 520 1.23 jdolecek void 521 1.23 jdolecek xen_intr_free_io_intrsource(const char *intrid) 522 1.23 jdolecek { 523 1.23 jdolecek /* Nothing to do, required by MSI code */ 524 1.23 jdolecek } 525 1.23 jdolecek 526 1.24 bouyer #if defined(XENPV) 527 1.14 cherry __strong_alias(x86_read_psl, xen_read_psl); 528 1.14 cherry __strong_alias(x86_write_psl, xen_write_psl); 529 1.14 cherry 530 1.14 cherry __strong_alias(intr_string, xintr_string); 531 1.14 cherry __strong_alias(intr_create_intrid, xen_intr_create_intrid); 532 1.14 cherry __strong_alias(intr_establish, xen_intr_establish); 533 1.14 cherry __strong_alias(intr_establish_xname, xen_intr_establish_xname); 534 1.18 thorpej __strong_alias(intr_mask, xen_intr_mask); 535 1.18 thorpej __strong_alias(intr_unmask, xen_intr_unmask); 536 1.14 cherry __strong_alias(intr_disestablish, xen_intr_disestablish); 537 1.14 cherry __strong_alias(cpu_intr_redistribute, xen_cpu_intr_redistribute); 538 1.14 cherry __strong_alias(cpu_intr_count, xen_cpu_intr_count); 539 1.14 cherry __strong_alias(cpu_intr_init, xen_cpu_intr_init); 540 1.23 jdolecek __strong_alias(intr_allocate_io_intrsource, xen_intr_allocate_io_intrsource); 541 1.23 jdolecek __strong_alias(intr_free_io_intrsource, xen_intr_free_io_intrsource); 542 1.24 bouyer #endif /* XENPV */ 543