git: 999174ba0364 - main - Hyper-V: vPCI: fix cpu id mis-mapping in vmbus_pcib_map_msi()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 08 Mar 2024 10:25:44 UTC
The branch main has been updated by whu: URL: https://cgit.FreeBSD.org/src/commit/?id=999174ba03642fa63c9654752993a62db461afc9 commit 999174ba03642fa63c9654752993a62db461afc9 Author: Wei Hu <whu@FreeBSD.org> AuthorDate: 2024-03-08 10:00:25 +0000 Commit: Wei Hu <whu@FreeBSD.org> CommitDate: 2024-03-08 10:16:10 +0000 Hyper-V: vPCI: fix cpu id mis-mapping in vmbus_pcib_map_msi() The msi address contains apic id. The code in vmbus_pcib_map_msi() treats it as cpu id, which could cause mis-configuration of msix IRQs, leading to missing interrupts for SRIOV devices. This happens when apic id is not the same as cpu id on certain large VM sizes with multiple numa domains in Azure. Fix this issue by correctly mapping apic ids to cpu ids. On vPCI version before 1.4, it only supports up to 64 vcpus for msi/msix interrupt. This change also adds a check and returns error if the vcpu_id is greater than 63. Reported by: NetApp Tested by: whu MFC after: 1 week --- sys/dev/hyperv/pcib/vmbus_pcib.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sys/dev/hyperv/pcib/vmbus_pcib.c b/sys/dev/hyperv/pcib/vmbus_pcib.c index f7c825d1bcf9..3fa349b0c0c5 100644 --- a/sys/dev/hyperv/pcib/vmbus_pcib.c +++ b/sys/dev/hyperv/pcib/vmbus_pcib.c @@ -67,6 +67,7 @@ #if defined(__i386__) || defined(__amd64__) #include <machine/intr_machdep.h> #include <x86/apicreg.h> +#include <x86/apicvar.h> #endif #if defined(__aarch64__) #include <contrib/dev/acpica/include/acpi.h> @@ -1927,11 +1928,21 @@ vmbus_pcib_map_msi(device_t pcib, device_t child, int irq, vcpu_id = VMBUS_GET_VCPU_ID(device_get_parent(pcib), pcib, cpu); vector = v_data; #else - cpu = (v_addr & MSI_INTEL_ADDR_DEST) >> 12; + cpu = apic_cpuid((v_addr & MSI_INTEL_ADDR_DEST) >> 12); vcpu_id = VMBUS_GET_VCPU_ID(device_get_parent(pcib), pcib, cpu); vector = v_data & MSI_INTEL_DATA_INTVEC; #endif + if (hpdev->hbus->protocol_version < PCI_PROTOCOL_VERSION_1_4 && + vcpu_id > 63) { + /* We only support vcpu_id < 64 before vPCI version 1.4 */ + device_printf(pcib, + "Error: " + "vcpu_id %u overflowed on PCI VMBus version 0x%x\n", + vcpu_id, hpdev->hbus->protocol_version); + return (ENODEV); + } + init_completion(&comp.comp_pkt.host_event); memset(&ctxt, 0, sizeof(ctxt));