Home | History | Annotate | Line # | Download | only in x86
xen_intr.c revision 1.21.2.7
      1  1.21.2.7    bouyer /*	$NetBSD: xen_intr.c,v 1.21.2.7 2020/04/19 19:39:10 bouyer 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.21.2.7    bouyer __KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.21.2.7 2020/04/19 19:39:10 bouyer Exp $");
     34      1.19        ad 
     35      1.19        ad #include "opt_multiprocessor.h"
     36       1.2    bouyer 
     37       1.2    bouyer #include <sys/param.h>
     38      1.10    cherry #include <sys/kernel.h>
     39      1.10    cherry #include <sys/kmem.h>
     40      1.11    cherry #include <sys/cpu.h>
     41      1.19        ad #include <sys/device.h>
     42      1.11    cherry 
     43  1.21.2.5    bouyer #include <xen/intr.h>
     44      1.10    cherry #include <xen/evtchn.h>
     45      1.15    cherry #include <xen/xenfunc.h>
     46       1.2    bouyer 
     47      1.12    cherry #include <uvm/uvm.h>
     48      1.12    cherry 
     49       1.2    bouyer #include <machine/cpu.h>
     50       1.2    bouyer #include <machine/intr.h>
     51       1.2    bouyer 
     52      1.11    cherry #include "acpica.h"
     53      1.11    cherry #include "ioapic.h"
     54      1.11    cherry #include "lapic.h"
     55      1.11    cherry #include "pci.h"
     56      1.11    cherry 
     57      1.11    cherry #if NACPICA > 0
     58      1.11    cherry #include <dev/acpi/acpivar.h>
     59      1.11    cherry #endif
     60      1.11    cherry 
     61      1.11    cherry #if NIOAPIC > 0 || NACPICA > 0
     62      1.11    cherry #include <machine/i82093var.h>
     63      1.11    cherry #endif
     64      1.11    cherry 
     65      1.11    cherry #if NLAPIC > 0
     66      1.11    cherry #include <machine/i82489var.h>
     67      1.11    cherry #endif
     68      1.11    cherry 
     69      1.11    cherry #if NPCI > 0
     70      1.11    cherry #include <dev/pci/ppbreg.h>
     71      1.11    cherry #endif
     72      1.11    cherry 
     73      1.19        ad #if defined(MULTIPROCESSOR)
     74      1.19        ad static const char *xen_ipi_names[XEN_NIPIS] = XEN_IPI_NAMES;
     75      1.19        ad #endif
     76      1.19        ad 
     77      1.17    cherry #if !defined(XENPVHVM)
     78       1.2    bouyer void
     79      1.16    bouyer x86_disable_intr(void)
     80       1.2    bouyer {
     81      1.16    bouyer 	curcpu()->ci_vcpu->evtchn_upcall_mask = 1;
     82      1.16    bouyer 	x86_lfence();
     83       1.2    bouyer }
     84       1.2    bouyer 
     85       1.2    bouyer void
     86      1.16    bouyer x86_enable_intr(void)
     87       1.2    bouyer {
     88      1.16    bouyer 	volatile struct vcpu_info *_vci = curcpu()->ci_vcpu;
     89      1.16    bouyer 	__insn_barrier();
     90      1.16    bouyer 	_vci->evtchn_upcall_mask = 0;
     91      1.16    bouyer 	x86_lfence(); /* unmask then check (avoid races) */
     92      1.16    bouyer 	if (__predict_false(_vci->evtchn_upcall_pending))
     93      1.16    bouyer 		hypervisor_force_callback();
     94       1.2    bouyer }
     95       1.2    bouyer 
     96      1.17    cherry #endif /* !XENPVHVM */
     97      1.17    cherry 
     98       1.2    bouyer u_long
     99      1.11    cherry xen_read_psl(void)
    100       1.2    bouyer {
    101       1.2    bouyer 
    102       1.4    cegger 	return (curcpu()->ci_vcpu->evtchn_upcall_mask);
    103       1.2    bouyer }
    104       1.2    bouyer 
    105       1.2    bouyer void
    106      1.11    cherry xen_write_psl(u_long psl)
    107       1.2    bouyer {
    108       1.4    cegger 	struct cpu_info *ci = curcpu();
    109       1.2    bouyer 
    110       1.4    cegger 	ci->ci_vcpu->evtchn_upcall_mask = psl;
    111       1.9       jym 	xen_rmb();
    112       1.4    cegger 	if (ci->ci_vcpu->evtchn_upcall_pending && psl == 0) {
    113       1.2    bouyer 	    	hypervisor_force_callback();
    114       1.2    bouyer 	}
    115       1.2    bouyer }
    116      1.10    cherry 
    117      1.10    cherry void *
    118      1.10    cherry xen_intr_establish(int legacy_irq, struct pic *pic, int pin,
    119      1.10    cherry     int type, int level, int (*handler)(void *), void *arg,
    120      1.10    cherry     bool known_mpsafe)
    121      1.10    cherry {
    122      1.10    cherry 
    123      1.10    cherry 	return xen_intr_establish_xname(legacy_irq, pic, pin, type, level,
    124      1.10    cherry 	    handler, arg, known_mpsafe, "XEN");
    125      1.10    cherry }
    126      1.10    cherry 
    127      1.10    cherry void *
    128      1.10    cherry xen_intr_establish_xname(int legacy_irq, struct pic *pic, int pin,
    129      1.10    cherry     int type, int level, int (*handler)(void *), void *arg,
    130      1.10    cherry     bool known_mpsafe, const char *xname)
    131      1.10    cherry {
    132      1.10    cherry 	const char *intrstr;
    133      1.10    cherry 	char intrstr_buf[INTRIDBUF];
    134      1.10    cherry 
    135      1.10    cherry 	if (pic->pic_type == PIC_XEN) {
    136      1.10    cherry 		struct intrhand *rih;
    137      1.10    cherry 
    138      1.10    cherry 		intrstr = intr_create_intrid(legacy_irq, pic, pin, intrstr_buf,
    139      1.10    cherry 		    sizeof(intrstr_buf));
    140      1.10    cherry 
    141  1.21.2.6    bouyer 		rih = event_set_handler(pin, handler, arg, level,
    142  1.21.2.6    bouyer 		    intrstr, xname, known_mpsafe);
    143      1.10    cherry 
    144      1.10    cherry 		if (rih == NULL) {
    145  1.21.2.7    bouyer 			printf("%s: can't establish interrupt\n", __func__);
    146      1.10    cherry 			return NULL;
    147      1.10    cherry 		}
    148      1.10    cherry 
    149      1.10    cherry 		return rih;
    150      1.10    cherry 	} 	/* Else we assume pintr */
    151      1.10    cherry 
    152      1.14    cherry #if (NPCI > 0 || NISA > 0) && defined(XENPV) /* XXX: support PVHVM pirq */
    153      1.10    cherry 	struct pintrhand *pih;
    154      1.10    cherry 	int gsi;
    155      1.10    cherry 	int vector, evtchn;
    156      1.10    cherry 
    157      1.10    cherry 	KASSERTMSG(legacy_irq == -1 || (0 <= legacy_irq && legacy_irq < NUM_XEN_IRQS),
    158      1.10    cherry 	    "bad legacy IRQ value: %d", legacy_irq);
    159      1.10    cherry 	KASSERTMSG(!(legacy_irq == -1 && pic == &i8259_pic),
    160      1.10    cherry 	    "non-legacy IRQon i8259 ");
    161      1.10    cherry 
    162      1.10    cherry 	gsi = xen_pic_to_gsi(pic, pin);
    163      1.10    cherry 
    164      1.10    cherry 	intrstr = intr_create_intrid(gsi, pic, pin, intrstr_buf,
    165      1.10    cherry 	    sizeof(intrstr_buf));
    166      1.10    cherry 
    167      1.10    cherry 	vector = xen_vec_alloc(gsi);
    168      1.10    cherry 
    169      1.10    cherry 	if (irq2port[gsi] == 0) {
    170      1.10    cherry 		extern struct cpu_info phycpu_info_primary; /* XXX */
    171      1.10    cherry 		struct cpu_info *ci = &phycpu_info_primary;
    172      1.10    cherry 
    173      1.10    cherry 		pic->pic_addroute(pic, ci, pin, vector, type);
    174      1.10    cherry 
    175      1.10    cherry 		evtchn = bind_pirq_to_evtch(gsi);
    176      1.10    cherry 		KASSERT(evtchn > 0);
    177      1.10    cherry 		KASSERT(evtchn < NR_EVENT_CHANNELS);
    178      1.10    cherry 		irq2port[gsi] = evtchn + 1;
    179      1.10    cherry 		xen_atomic_set_bit(&ci->ci_evtmask[0], evtchn);
    180      1.10    cherry 	} else {
    181      1.10    cherry 		/*
    182      1.10    cherry 		 * Shared interrupt - we can't rebind.
    183      1.10    cherry 		 * The port is shared instead.
    184      1.10    cherry 		 */
    185      1.10    cherry 		evtchn = irq2port[gsi] - 1;
    186      1.10    cherry 	}
    187      1.10    cherry 
    188      1.10    cherry 	pih = pirq_establish(gsi, evtchn, handler, arg, level,
    189      1.21  jdolecek 			     intrstr, xname, known_mpsafe);
    190  1.21.2.6    bouyer 	pih->pic = pic;
    191      1.10    cherry 	return pih;
    192      1.10    cherry #endif /* NPCI > 0 || NISA > 0 */
    193      1.10    cherry 
    194      1.10    cherry 	/* FALLTHROUGH */
    195      1.10    cherry 	return NULL;
    196      1.10    cherry }
    197      1.10    cherry 
    198      1.10    cherry /*
    199      1.18   thorpej  * Mask an interrupt source.
    200      1.18   thorpej  */
    201      1.18   thorpej void
    202      1.18   thorpej xen_intr_mask(struct intrhand *ih)
    203      1.18   thorpej {
    204      1.18   thorpej 	/* XXX */
    205      1.18   thorpej 	panic("xen_intr_mask: not yet implemented.");
    206      1.18   thorpej }
    207      1.18   thorpej 
    208      1.18   thorpej /*
    209      1.18   thorpej  * Unmask an interrupt source.
    210      1.18   thorpej  */
    211      1.18   thorpej void
    212      1.18   thorpej xen_intr_unmask(struct intrhand *ih)
    213      1.18   thorpej {
    214      1.18   thorpej 	/* XXX */
    215      1.18   thorpej 	panic("xen_intr_unmask: not yet implemented.");
    216      1.18   thorpej }
    217      1.18   thorpej 
    218      1.18   thorpej /*
    219      1.10    cherry  * Deregister an interrupt handler.
    220      1.10    cherry  */
    221      1.10    cherry void
    222      1.10    cherry xen_intr_disestablish(struct intrhand *ih)
    223      1.10    cherry {
    224      1.10    cherry 
    225  1.21.2.6    bouyer 	if (ih->ih_pic->pic_type == PIC_XEN) {
    226      1.10    cherry 		event_remove_handler(ih->ih_pin, ih->ih_realfun,
    227      1.10    cherry 		    ih->ih_realarg);
    228  1.21.2.6    bouyer 		/* event_remove_handler frees ih */
    229      1.10    cherry 		return;
    230      1.10    cherry 	}
    231      1.10    cherry #if defined(DOM0OPS)
    232      1.10    cherry 	/*
    233      1.10    cherry 	 * Cache state, to prevent a use after free situation with
    234      1.10    cherry 	 * ih.
    235      1.10    cherry 	 */
    236      1.10    cherry 
    237      1.10    cherry 	struct pintrhand *pih = (struct pintrhand *)ih;
    238      1.10    cherry 
    239      1.10    cherry 	int pirq = pih->pirq;
    240      1.10    cherry 	int port = pih->evtch;
    241      1.10    cherry 	KASSERT(irq2port[pirq] != 0);
    242      1.10    cherry 
    243      1.10    cherry 	pirq_disestablish(pih);
    244      1.10    cherry 
    245      1.10    cherry 	if (evtsource[port] == NULL) {
    246      1.10    cherry 			/*
    247      1.10    cherry 			 * Last handler was removed by
    248      1.10    cherry 			 * event_remove_handler().
    249      1.10    cherry 			 *
    250      1.10    cherry 			 * We can safely unbind the pirq now.
    251      1.10    cherry 			 */
    252      1.10    cherry 
    253      1.10    cherry 			port = unbind_pirq_from_evtch(pirq);
    254      1.10    cherry 			KASSERT(port == pih->evtch);
    255      1.10    cherry 			irq2port[pirq] = 0;
    256      1.10    cherry 	}
    257      1.10    cherry #endif
    258      1.10    cherry 	return;
    259      1.10    cherry }
    260      1.10    cherry 
    261      1.11    cherry /* MI interface for kern_cpu.c */
    262      1.11    cherry void xen_cpu_intr_redistribute(void);
    263      1.11    cherry 
    264      1.11    cherry void
    265      1.11    cherry xen_cpu_intr_redistribute(void)
    266      1.11    cherry {
    267      1.11    cherry 	KASSERT(mutex_owned(&cpu_lock));
    268      1.11    cherry 	KASSERT(mp_online);
    269      1.11    cherry 
    270      1.11    cherry 	return;
    271      1.11    cherry }
    272      1.11    cherry 
    273      1.11    cherry /* MD - called by x86/cpu.c */
    274      1.12    cherry #if defined(INTRSTACKSIZE)
    275      1.12    cherry static inline bool
    276      1.12    cherry redzone_const_or_false(bool x)
    277      1.12    cherry {
    278      1.12    cherry #ifdef DIAGNOSTIC
    279      1.12    cherry 	return x;
    280      1.12    cherry #else
    281      1.12    cherry 	return false;
    282      1.12    cherry #endif /* !DIAGNOSTIC */
    283      1.12    cherry }
    284      1.12    cherry 
    285      1.12    cherry static inline int
    286      1.12    cherry redzone_const_or_zero(int x)
    287      1.12    cherry {
    288      1.12    cherry 	return redzone_const_or_false(true) ? x : 0;
    289      1.12    cherry }
    290      1.12    cherry #endif
    291      1.12    cherry 
    292      1.14    cherry void xen_cpu_intr_init(struct cpu_info *);
    293      1.11    cherry void
    294      1.14    cherry xen_cpu_intr_init(struct cpu_info *ci)
    295      1.11    cherry {
    296  1.21.2.3    bouyer #if defined(__HAVE_PREEMPTION)
    297  1.21.2.3    bouyer 	x86_init_preempt(ci);
    298  1.21.2.3    bouyer #endif
    299  1.21.2.3    bouyer 	x86_intr_calculatemasks(ci);
    300  1.21.2.3    bouyer 
    301      1.11    cherry #if defined(INTRSTACKSIZE)
    302      1.11    cherry 	vaddr_t istack;
    303      1.11    cherry 
    304      1.11    cherry 	/*
    305      1.11    cherry 	 * If the red zone is activated, protect both the top and
    306      1.11    cherry 	 * the bottom of the stack with an unmapped page.
    307      1.11    cherry 	 */
    308      1.11    cherry 	istack = uvm_km_alloc(kernel_map,
    309      1.11    cherry 	    INTRSTACKSIZE + redzone_const_or_zero(2 * PAGE_SIZE), 0,
    310      1.11    cherry 	    UVM_KMF_WIRED|UVM_KMF_ZERO);
    311      1.11    cherry 	if (redzone_const_or_false(true)) {
    312      1.11    cherry 		pmap_kremove(istack, PAGE_SIZE);
    313      1.11    cherry 		pmap_kremove(istack + INTRSTACKSIZE + PAGE_SIZE, PAGE_SIZE);
    314      1.11    cherry 		pmap_update(pmap_kernel());
    315      1.11    cherry 	}
    316      1.11    cherry 
    317      1.11    cherry 	/*
    318      1.11    cherry 	 * 33 used to be 1.  Arbitrarily reserve 32 more register_t's
    319      1.11    cherry 	 * of space for ddb(4) to examine some subroutine arguments
    320      1.11    cherry 	 * and to hunt for the next stack frame.
    321      1.11    cherry 	 */
    322      1.11    cherry 	ci->ci_intrstack = (char *)istack + redzone_const_or_zero(PAGE_SIZE) +
    323      1.11    cherry 	    INTRSTACKSIZE - 33 * sizeof(register_t);
    324      1.11    cherry #endif
    325      1.11    cherry 
    326      1.19        ad #ifdef MULTIPROCESSOR
    327  1.21.2.2    bouyer 	for (int i = 0; i < XEN_NIPIS; i++)
    328      1.19        ad 		evcnt_attach_dynamic(&ci->ci_ipi_events[i], EVCNT_TYPE_MISC,
    329      1.19        ad 		    NULL, device_xname(ci->ci_dev), xen_ipi_names[i]);
    330      1.19        ad #endif
    331      1.19        ad 
    332      1.11    cherry 	ci->ci_idepth = -1;
    333      1.11    cherry }
    334      1.11    cherry 
    335      1.11    cherry /*
    336      1.11    cherry  * Everything below from here is duplicated from x86/intr.c
    337      1.11    cherry  * When intr.c and xen_intr.c are unified, these will need to be
    338      1.11    cherry  * merged.
    339      1.11    cherry  */
    340      1.11    cherry 
    341      1.11    cherry u_int xen_cpu_intr_count(struct cpu_info *ci);
    342      1.11    cherry 
    343      1.11    cherry u_int
    344      1.11    cherry xen_cpu_intr_count(struct cpu_info *ci)
    345      1.11    cherry {
    346      1.11    cherry 
    347      1.11    cherry 	KASSERT(ci->ci_nintrhand >= 0);
    348      1.11    cherry 
    349      1.11    cherry 	return ci->ci_nintrhand;
    350      1.11    cherry }
    351      1.11    cherry 
    352      1.11    cherry static const char *
    353      1.11    cherry xen_intr_string(int port, char *buf, size_t len, struct pic *pic)
    354      1.11    cherry {
    355      1.11    cherry 	KASSERT(pic->pic_type == PIC_XEN);
    356      1.11    cherry 
    357      1.11    cherry 	KASSERT(port >= 0);
    358      1.11    cherry 	KASSERT(port < NR_EVENT_CHANNELS);
    359      1.11    cherry 
    360      1.11    cherry 	snprintf(buf, len, "%s channel %d", pic->pic_name, port);
    361      1.11    cherry 
    362      1.11    cherry 	return buf;
    363      1.11    cherry }
    364      1.11    cherry 
    365      1.11    cherry static const char *
    366      1.11    cherry legacy_intr_string(int ih, char *buf, size_t len, struct pic *pic)
    367      1.11    cherry {
    368      1.11    cherry 	int legacy_irq;
    369      1.11    cherry 
    370      1.11    cherry 	KASSERT(pic->pic_type == PIC_I8259);
    371      1.11    cherry #if NLAPIC > 0
    372      1.11    cherry 	KASSERT(APIC_IRQ_ISLEGACY(ih));
    373      1.11    cherry 
    374      1.11    cherry 	legacy_irq = APIC_IRQ_LEGACY_IRQ(ih);
    375      1.11    cherry #else
    376      1.11    cherry 	legacy_irq = ih;
    377      1.11    cherry #endif
    378      1.11    cherry 	KASSERT(legacy_irq >= 0 && legacy_irq < 16);
    379      1.11    cherry 
    380      1.11    cherry 	snprintf(buf, len, "%s pin %d", pic->pic_name, legacy_irq);
    381      1.11    cherry 
    382      1.11    cherry 	return buf;
    383      1.11    cherry }
    384      1.11    cherry 
    385      1.14    cherry const char * xintr_string(intr_handle_t ih, char *buf, size_t len);
    386      1.14    cherry 
    387      1.11    cherry const char *
    388      1.14    cherry xintr_string(intr_handle_t ih, char *buf, size_t len)
    389      1.11    cherry {
    390      1.11    cherry #if NIOAPIC > 0
    391      1.11    cherry 	struct ioapic_softc *pic;
    392      1.11    cherry #endif
    393      1.11    cherry 
    394      1.11    cherry 	if (ih == 0)
    395      1.11    cherry 		panic("%s: bogus handle 0x%" PRIx64, __func__, ih);
    396      1.11    cherry 
    397      1.11    cherry #if NIOAPIC > 0
    398      1.11    cherry 	if (ih & APIC_INT_VIA_APIC) {
    399      1.11    cherry 		pic = ioapic_find(APIC_IRQ_APIC(ih));
    400      1.11    cherry 		if (pic != NULL) {
    401      1.11    cherry 			snprintf(buf, len, "%s pin %d",
    402      1.11    cherry 			    device_xname(pic->sc_dev), APIC_IRQ_PIN(ih));
    403      1.11    cherry 		} else {
    404      1.11    cherry 			snprintf(buf, len,
    405      1.11    cherry 			    "apic %d int %d (irq %d)",
    406      1.11    cherry 			    APIC_IRQ_APIC(ih),
    407      1.11    cherry 			    APIC_IRQ_PIN(ih),
    408      1.11    cherry 			    APIC_IRQ_LEGACY_IRQ(ih));
    409      1.11    cherry 		}
    410      1.11    cherry 	} else
    411      1.11    cherry 		snprintf(buf, len, "irq %d", APIC_IRQ_LEGACY_IRQ(ih));
    412      1.11    cherry 
    413      1.11    cherry #elif NLAPIC > 0
    414      1.14    cherry 	snprintf(buf, len, "irq %d", APIC_IRQ_LEGACY_IRQ(ih));
    415      1.11    cherry #else
    416      1.11    cherry 	snprintf(buf, len, "irq %d", (int) ih);
    417      1.11    cherry #endif
    418      1.11    cherry 	return buf;
    419      1.11    cherry 
    420      1.11    cherry }
    421      1.11    cherry 
    422      1.11    cherry /*
    423      1.11    cherry  * Create an interrupt id such as "ioapic0 pin 9". This interrupt id is used
    424      1.11    cherry  * by MI code and intrctl(8).
    425      1.11    cherry  */
    426      1.14    cherry const char * xen_intr_create_intrid(int legacy_irq, struct pic *pic,
    427      1.14    cherry     int pin, char *buf, size_t len);
    428      1.14    cherry 
    429      1.11    cherry const char *
    430      1.14    cherry xen_intr_create_intrid(int legacy_irq, struct pic *pic, int pin, char *buf, size_t len)
    431      1.11    cherry {
    432      1.11    cherry 	int ih = 0;
    433      1.11    cherry 
    434  1.21.2.5    bouyer #if NPCI > 0 && defined(XENPV)
    435      1.11    cherry #if defined(__HAVE_PCI_MSI_MSIX)
    436      1.11    cherry 	if ((pic->pic_type == PIC_MSI) || (pic->pic_type == PIC_MSIX)) {
    437      1.11    cherry 		uint64_t pih;
    438      1.11    cherry 		int dev, vec;
    439      1.11    cherry 
    440      1.11    cherry 		dev = msipic_get_devid(pic);
    441      1.11    cherry 		vec = pin;
    442      1.11    cherry 		pih = __SHIFTIN((uint64_t)dev, MSI_INT_DEV_MASK)
    443      1.11    cherry 			| __SHIFTIN((uint64_t)vec, MSI_INT_VEC_MASK)
    444      1.11    cherry 			| APIC_INT_VIA_MSI;
    445      1.11    cherry 		if (pic->pic_type == PIC_MSI)
    446      1.11    cherry 			MSI_INT_MAKE_MSI(pih);
    447      1.11    cherry 		else if (pic->pic_type == PIC_MSIX)
    448      1.11    cherry 			MSI_INT_MAKE_MSIX(pih);
    449      1.11    cherry 
    450      1.11    cherry 		return x86_pci_msi_string(NULL, pih, buf, len);
    451      1.11    cherry 	}
    452      1.11    cherry #endif /* __HAVE_PCI_MSI_MSIX */
    453      1.11    cherry #endif
    454      1.11    cherry 
    455      1.11    cherry 	if (pic->pic_type == PIC_XEN) {
    456      1.11    cherry 		ih = pin;	/* Port == pin */
    457      1.11    cherry 		return xen_intr_string(pin, buf, len, pic);
    458      1.11    cherry 	}
    459      1.11    cherry 
    460      1.11    cherry 	/*
    461      1.11    cherry 	 * If the device is pci, "legacy_irq" is alway -1. Least 8 bit of "ih"
    462      1.11    cherry 	 * is only used in intr_string() to show the irq number.
    463      1.11    cherry 	 * If the device is "legacy"(such as floppy), it should not use
    464      1.11    cherry 	 * intr_string().
    465      1.11    cherry 	 */
    466      1.11    cherry 	if (pic->pic_type == PIC_I8259) {
    467      1.11    cherry 		ih = legacy_irq;
    468      1.11    cherry 		return legacy_intr_string(ih, buf, len, pic);
    469      1.11    cherry 	}
    470      1.11    cherry 
    471      1.11    cherry #if NIOAPIC > 0 || NACPICA > 0
    472      1.11    cherry 	ih = ((pic->pic_apicid << APIC_INT_APIC_SHIFT) & APIC_INT_APIC_MASK)
    473      1.11    cherry 	    | ((pin << APIC_INT_PIN_SHIFT) & APIC_INT_PIN_MASK);
    474      1.11    cherry 	if (pic->pic_type == PIC_IOAPIC) {
    475      1.11    cherry 		ih |= APIC_INT_VIA_APIC;
    476      1.11    cherry 	}
    477      1.11    cherry 	ih |= pin;
    478      1.11    cherry 	return intr_string(ih, buf, len);
    479      1.11    cherry #endif
    480      1.11    cherry 
    481      1.11    cherry 	return NULL; /* No pic found! */
    482      1.11    cherry }
    483      1.11    cherry 
    484  1.21.2.7    bouyer #if defined(XENPV)
    485      1.14    cherry __strong_alias(x86_read_psl, xen_read_psl);
    486      1.14    cherry __strong_alias(x86_write_psl, xen_write_psl);
    487      1.14    cherry 
    488      1.14    cherry __strong_alias(intr_string, xintr_string);
    489      1.14    cherry __strong_alias(intr_create_intrid, xen_intr_create_intrid);
    490      1.14    cherry __strong_alias(intr_establish, xen_intr_establish);
    491      1.14    cherry __strong_alias(intr_establish_xname, xen_intr_establish_xname);
    492      1.18   thorpej __strong_alias(intr_mask, xen_intr_mask);
    493      1.18   thorpej __strong_alias(intr_unmask, xen_intr_unmask);
    494      1.14    cherry __strong_alias(intr_disestablish, xen_intr_disestablish);
    495      1.14    cherry __strong_alias(cpu_intr_redistribute, xen_cpu_intr_redistribute);
    496      1.14    cherry __strong_alias(cpu_intr_count, xen_cpu_intr_count);
    497      1.14    cherry __strong_alias(cpu_intr_init, xen_cpu_intr_init);
    498  1.21.2.7    bouyer #endif /* XENPV */
    499