git: fa397e50fd88 - stable/13 - Hyper-V: vPCI: fix cpu id mis-mapping in vmbus_pcib_map_msi()

From: Wei Hu <whu_at_FreeBSD.org>
Date: Mon, 11 Mar 2024 05:30:28 UTC
The branch stable/13 has been updated by whu:

URL: https://cgit.FreeBSD.org/src/commit/?id=fa397e50fd8820446d44b90cf4017bd31e264c76

commit fa397e50fd8820446d44b90cf4017bd31e264c76
Author:     Wei Hu <whu@FreeBSD.org>
AuthorDate: 2024-03-11 05:24:53 +0000
Commit:     Wei Hu <whu@FreeBSD.org>
CommitDate: 2024-03-11 05:29:52 +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.
    
    (cherry picked from commit 999174ba03642fa63c9654752993a62db461afc9)
    
    Reported by:    NetApp
    Tested by:      whu
    Sponsored by:   Microsoft
---
 sys/dev/hyperv/pcib/vmbus_pcib.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sys/dev/hyperv/pcib/vmbus_pcib.c b/sys/dev/hyperv/pcib/vmbus_pcib.c
index 037ea7032184..ec80d97a959f 100644
--- a/sys/dev/hyperv/pcib/vmbus_pcib.c
+++ b/sys/dev/hyperv/pcib/vmbus_pcib.c
@@ -63,6 +63,7 @@
 
 #include <machine/intr_machdep.h>
 #include <x86/apicreg.h>
+#include <x86/apicvar.h>
 
 #include <dev/hyperv/include/hyperv.h>
 #include <dev/hyperv/include/hyperv_busdma.h>
@@ -1804,10 +1805,17 @@ vmbus_pcib_map_msi(device_t pcib, device_t child, int irq,
 		}
 	}
 
-	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;
 
+	if (vcpu_id > 63) {
+		/* We only support vcpu_id < 64 on current vPCI version*/
+		device_printf(pcib,
+		    "Error: vcpu_id %u overflowed\n", vcpu_id);
+		return (ENODEV);
+	}
+
 	init_completion(&comp.comp_pkt.host_event);
 
 	memset(&ctxt, 0, sizeof(ctxt));