summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/x86/x86/msi.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/sys/x86/x86/msi.c b/sys/x86/x86/msi.c
index 20fda2cd58d5..19a427a9b628 100644
--- a/sys/x86/x86/msi.c
+++ b/sys/x86/x86/msi.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/sx.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <x86/apicreg.h>
#include <machine/cputypes.h>
@@ -148,6 +149,16 @@ struct pic msi_pic = {
.pic_reprogram_pin = NULL,
};
+/*
+ * Xen hypervisors prior to 4.6.0 do not properly handle updates to
+ * enabled MSI-X table entries. Allow migration of MSI-X interrupts
+ * to be disabled via a tunable.
+ */
+static int msix_disable_migration = 0;
+SYSCTL_INT(_machdep, OID_AUTO, disable_msix_migration, CTLFLAG_RDTUN,
+ &msix_disable_migration, 0,
+ "Disable migration of MSI-X interrupts between CPUs");
+
static int msi_enabled;
static int msi_last_irq;
static struct mtx msi_lock;
@@ -226,6 +237,9 @@ msi_assign_cpu(struct intsrc *isrc, u_int apic_id)
if (msi->msi_first != msi)
return (EINVAL);
+ if (msix_disable_migration && msi->msi_msix)
+ return (EINVAL);
+
/* Store information to free existing irq. */
old_vector = msi->msi_vector;
old_id = msi->msi_cpu;