Index: head/sys/amd64/include/intr_machdep.h =================================================================== --- head/sys/amd64/include/intr_machdep.h +++ head/sys/amd64/include/intr_machdep.h @@ -149,6 +149,8 @@ extern struct mtx icu_lock; extern int elcr_found; +extern int msix_disable_migration; + #ifndef DEV_ATPIC void atpic_reset(void); #endif Index: head/sys/i386/include/intr_machdep.h =================================================================== --- head/sys/i386/include/intr_machdep.h +++ head/sys/i386/include/intr_machdep.h @@ -140,6 +140,8 @@ extern struct mtx icu_lock; extern int elcr_found; +extern int msix_disable_migration; + #ifndef DEV_ATPIC void atpic_reset(void); #endif Index: head/sys/x86/x86/msi.c =================================================================== --- head/sys/x86/x86/msi.c +++ head/sys/x86/x86/msi.c @@ -149,12 +149,16 @@ .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. + * to be disabled via a tunable. Values have the following meaning: + * + * -1: automatic detection by FreeBSD + * 0: enable migration + * 1: disable migration */ -static int msix_disable_migration = 0; +int msix_disable_migration = -1; SYSCTL_INT(_machdep, OID_AUTO, disable_msix_migration, CTLFLAG_RDTUN, &msix_disable_migration, 0, "Disable migration of MSI-X interrupts between CPUs"); @@ -312,6 +316,11 @@ return; } + if (msix_disable_migration == -1) { + /* The default is to allow migration of MSI-X interrupts. */ + msix_disable_migration = 0; + } + msi_enabled = 1; intr_register_pic(&msi_pic); mtx_init(&msi_lock, "msi", NULL, MTX_DEF); Index: head/sys/x86/xen/hvm.c =================================================================== --- head/sys/x86/xen/hvm.c +++ head/sys/x86/xen/hvm.c @@ -134,9 +134,29 @@ return (ENXIO); if (init_type == XEN_HVM_INIT_COLD) { + int major, minor; + do_cpuid(base + 1, regs); - printf("XEN: Hypervisor version %d.%d detected.\n", - regs[0] >> 16, regs[0] & 0xffff); + + major = regs[0] >> 16; + minor = regs[0] & 0xffff; + printf("XEN: Hypervisor version %d.%d detected.\n", major, + minor); + + if (((major < 4) || (major == 4 && minor <= 5)) && + msix_disable_migration == -1) { + /* + * Xen hypervisors prior to 4.6.0 do not properly + * handle updates to enabled MSI-X table entries, + * so disable MSI-X interrupt migration in that + * case. + */ + if (bootverbose) + printf( +"Disabling MSI-X interrupt migration due to Xen hypervisor bug.\n" +"Set machdep.msix_disable_migration=0 to forcefully enable it.\n"); + msix_disable_migration = 1; + } } /*