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);

Reply via email to