Module Name: src Committed By: jdolecek Date: Sun Jul 19 14:27:07 UTC 2020
Modified Files: src/sys/arch/x86/pci: pci_msi_machdep.c src/sys/arch/xen/include: intr.h src/sys/arch/xen/x86: pintr.c Log Message: for Xen MSI, fallback to INTx when PHYSDEVOP_map_pirq fails for the device apparently Xen requires VT-d to be enabled in BIOS for PHYSDEVOP_map_pirq to work, this change makes it work on systems with VT-d disabled or missing adresses the panic part of PR port-xen/55285 by Patrick Welche To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/arch/x86/pci/pci_msi_machdep.c cvs rdiff -u -r1.57 -r1.58 src/sys/arch/xen/include/intr.h cvs rdiff -u -r1.17 -r1.18 src/sys/arch/xen/x86/pintr.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/pci/pci_msi_machdep.c diff -u src/sys/arch/x86/pci/pci_msi_machdep.c:1.13 src/sys/arch/x86/pci/pci_msi_machdep.c:1.14 --- src/sys/arch/x86/pci/pci_msi_machdep.c:1.13 Fri Jul 28 14:26:50 2017 +++ src/sys/arch/x86/pci/pci_msi_machdep.c Sun Jul 19 14:27:07 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_msi_machdep.c,v 1.13 2017/07/28 14:26:50 maxv Exp $ */ +/* $NetBSD: pci_msi_machdep.c,v 1.14 2020/07/19 14:27:07 jdolecek Exp $ */ /* * Copyright (c) 2015 Internet Initiative Japan Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_msi_machdep.c,v 1.13 2017/07/28 14:26:50 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_msi_machdep.c,v 1.14 2020/07/19 14:27:07 jdolecek Exp $"); #include "opt_intrdebug.h" #include "ioapic.h" @@ -175,6 +175,14 @@ pci_msi_alloc_common(pci_intr_handle_t * return EINVAL; } +#ifdef XENPV + if (xen_pci_msi_probe(msi_pic, *count)) { + DPRINTF(("xen_pci_msi_probe() failed\n")); + msipic_destruct_msi_pic(msi_pic); + return EINVAL; + } +#endif + vectors = NULL; while (*count > 0) { vectors = pci_msi_alloc_vectors(msi_pic, NULL, count); @@ -262,6 +270,14 @@ pci_msix_alloc_common(pci_intr_handle_t if (msix_pic == NULL) return EINVAL; +#ifdef XENPV + if (xen_pci_msi_probe(msix_pic, *count)) { + DPRINTF(("xen_pci_msi_probe() failed\n")); + msipic_destruct_msix_pic(msix_pic); + return EINVAL; + } +#endif + vectors = NULL; while (*count > 0) { vectors = pci_msi_alloc_vectors(msix_pic, table_indexes, count); Index: src/sys/arch/xen/include/intr.h diff -u src/sys/arch/xen/include/intr.h:1.57 src/sys/arch/xen/include/intr.h:1.58 --- src/sys/arch/xen/include/intr.h:1.57 Fri May 15 07:42:58 2020 +++ src/sys/arch/xen/include/intr.h Sun Jul 19 14:27:07 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.h,v 1.57 2020/05/15 07:42:58 jdolecek Exp $ */ +/* $NetBSD: intr.h,v 1.58 2020/07/19 14:27:07 jdolecek Exp $ */ /* NetBSD intr.h,v 1.15 2004/10/31 10:39:34 yamt Exp */ /*- @@ -72,6 +72,7 @@ int xen_intr_biglock_wrapper(void *); #if defined(DOM0OPS) || NPCI > 0 int xen_pic_to_gsi(struct pic *, int); +int xen_pci_msi_probe(struct pic *, int); #endif /* defined(DOM0OPS) || NPCI > 0 */ #ifdef MULTIPROCESSOR Index: src/sys/arch/xen/x86/pintr.c diff -u src/sys/arch/xen/x86/pintr.c:1.17 src/sys/arch/xen/x86/pintr.c:1.18 --- src/sys/arch/xen/x86/pintr.c:1.17 Sat May 23 14:51:19 2020 +++ src/sys/arch/xen/x86/pintr.c Sun Jul 19 14:27:07 2020 @@ -103,7 +103,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pintr.c,v 1.17 2020/05/23 14:51:19 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pintr.c,v 1.18 2020/07/19 14:27:07 jdolecek Exp $"); #include "opt_multiprocessor.h" #include "opt_xen.h" @@ -163,6 +163,67 @@ short irq2port[NR_EVENT_CHANNELS] = {0}; #endif #if defined(DOM0OPS) || NPCI > 0 + +static int +xen_map_msi_pirq(struct pic *pic, int count, int *gsi) +{ + struct physdev_map_pirq map_irq; + const struct msipic_pci_info *i = msipic_get_pci_info(pic); + int ret; + + if (count == -1) + count = i->mp_veccnt; + KASSERT(count > 0); + + memset(&map_irq, 0, sizeof(map_irq)); + map_irq.domid = DOMID_SELF; + map_irq.type = MAP_PIRQ_TYPE_MSI_SEG; + map_irq.index = -1; + map_irq.pirq = -1; + map_irq.bus = i->mp_bus; + map_irq.devfn = (i->mp_dev << 3) | i->mp_fun; + map_irq.entry_nr = count; + if (pic->pic_type == PIC_MSI && i->mp_veccnt > 1) { + map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI; + } else if (pic->pic_type == PIC_MSIX) { + map_irq.table_base = i->mp_table_base; + } + + ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); + + if (ret == 0) { + KASSERT(map_irq.entry_nr == count); + *gsi = map_irq.pirq; + } + + return ret; +} + +/* + * Check if we can map MSI interrupt. The Xen call fails if VT-d is not + * available or disabled. + */ +int +xen_pci_msi_probe(struct pic *pic, int count) +{ + int pirq, ret; + + ret = xen_map_msi_pirq(pic, count, &pirq); + + if (ret == 0) { + struct physdev_unmap_pirq unmap_irq; + unmap_irq.domid = DOMID_SELF; + unmap_irq.pirq = pirq; + + (void)HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); + } else { + aprint_debug("PHYSDEVOP_map_pirq() failed %d, MSI disabled\n", + ret); + } + + return ret; +} + /* * This function doesn't "allocate" anything. It merely translates our * understanding of PIC to the XEN 'gsi' namespace. In the case of @@ -213,32 +274,11 @@ xen_pic_to_gsi(struct pic *pic, int pin) case PIC_MSI: case PIC_MSIX: #ifdef __HAVE_PCI_MSI_MSIX - { - struct physdev_map_pirq map_irq; - const struct msipic_pci_info *i = msipic_get_pci_info(pic); - - memset(&map_irq, 0, sizeof(map_irq)); - map_irq.domid = DOMID_SELF; - map_irq.type = MAP_PIRQ_TYPE_MSI_SEG; - map_irq.index = -1; - map_irq.pirq = -1; - map_irq.bus = i->mp_bus; - map_irq.devfn = (i->mp_dev << 3) | i->mp_fun; - KASSERT(i->mp_veccnt > 0); - map_irq.entry_nr = i->mp_veccnt; - if (pic->pic_type == PIC_MSI && i->mp_veccnt > 1) { - map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI; - } else if (pic->pic_type == PIC_MSIX) { - map_irq.table_base = i->mp_table_base; - } - ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); + ret = xen_map_msi_pirq(pic, -1, &gsi); if (ret != 0) panic("physdev_op(PHYSDEVOP_map_pirq) MSI fail %d", ret); - KASSERT(map_irq.entry_nr == i->mp_veccnt); - gsi = map_irq.pirq; break; - } #endif default: panic("unknown pic_type %d", pic->pic_type);