The branch stable/14 has been updated by whu:

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

commit d56a912f2fb6fb26a00e950a26e420729e6ef775
Author:     Wei Hu <[email protected]>
AuthorDate: 2024-06-15 14:07:58 +0000
Commit:     Wei Hu <[email protected]>
CommitDate: 2024-07-01 13:33:08 +0000

    Hyper-V: move memory alloc call for tlb hypercall out of smp_rendezvous
    
    The allocation call could result in sleep lock violation if it is in
    smp_rendezvous. Move it out. Also move the pcpu memory pointer to
    vmbus_pcpu_data since it is only used on Hyper-V.
    
    PR:             279738
    Reported by:    gbe
    Fixes:          2b887687edc25bb4553f0d8a1183f454a85d413d
    MFC after:      2 weeks
    Sponsored by:   Microsoft
    
    (cherry picked from commit d0cb4674df97aa638d5d17861c364b1625f79401)
---
 sys/dev/hyperv/vmbus/hyperv_mmu.c |  6 +--
 sys/dev/hyperv/vmbus/vmbus.c      | 88 +++++++++++++++++++++++++++++----------
 sys/dev/hyperv/vmbus/vmbus_var.h  |  5 ++-
 3 files changed, 71 insertions(+), 28 deletions(-)

diff --git a/sys/dev/hyperv/vmbus/hyperv_mmu.c 
b/sys/dev/hyperv/vmbus/hyperv_mmu.c
index 13b1f52fa1f6..7c29fe294093 100644
--- a/sys/dev/hyperv/vmbus/hyperv_mmu.c
+++ b/sys/dev/hyperv/vmbus/hyperv_mmu.c
@@ -144,7 +144,7 @@ hv_vm_tlb_flush(pmap_t pmap, vm_offset_t addr1, vm_offset_t 
addr2,
                return smp_targeted_tlb_shootdown_native(pmap, addr1, addr2,
                    curcpu_cb, op);
 
-       flush = *DPCPU_PTR(hv_pcpu_mem);
+       flush = *VMBUS_PCPU_PTR(sc, cpu_mem, curcpu);
        if (flush == NULL)
                return smp_targeted_tlb_shootdown_native(pmap, addr1, addr2,
                    curcpu_cb, op);
@@ -253,9 +253,9 @@ hv_flush_tlb_others_ex(pmap_t pmap, vm_offset_t addr1, 
vm_offset_t addr2,
 {
        int nr_bank = 0, max_gvas, gva_n;
        struct hv_tlb_flush_ex *flush;
-       if(*DPCPU_PTR(hv_pcpu_mem) == NULL)
+       if(*VMBUS_PCPU_PTR(sc, cpu_mem, curcpu) == NULL)
                return EINVAL;
-       flush = *DPCPU_PTR(hv_pcpu_mem);
+       flush = *VMBUS_PCPU_PTR(sc, cpu_mem, curcpu);
        uint64_t status = 0;
        uint64_t cr3;
 
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 786b2611dcd7..6a26527768c4 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -139,7 +139,10 @@ static void                        
vmbus_event_proc_dummy(struct vmbus_softc *,
                                    int);
 static bus_dma_tag_t   vmbus_get_dma_tag(device_t parent, device_t child);
 static struct vmbus_softc      *vmbus_sc;
-static void free_pcpu_ptr(void);
+#if defined(__x86_64__)
+static int vmbus_alloc_cpu_mem(struct vmbus_softc *sc);
+static void vmbus_free_cpu_mem(struct vmbus_softc *sc);
+#endif
 
 SYSCTL_NODE(_hw, OID_AUTO, vmbus, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
     "Hyper-V vmbus");
@@ -217,7 +220,6 @@ static driver_t vmbus_driver = {
 };
 
 uint32_t hv_max_vp_index;
-DPCPU_DEFINE(void *, hv_pcpu_mem);
 
 DRIVER_MODULE(vmbus, pcib, vmbus_driver, NULL, NULL);
 DRIVER_MODULE(vmbus, acpi_syscontainer, vmbus_driver, NULL, NULL);
@@ -750,7 +752,6 @@ vmbus_synic_setup(void *xsc)
        int cpu = curcpu;
        uint64_t val, orig;
        uint32_t sint;
-       void **hv_cpu_mem;
 
        if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
                /* Save virtual processor id. */
@@ -762,19 +763,6 @@ vmbus_synic_setup(void *xsc)
 
        if (VMBUS_PCPU_GET(sc, vcpuid, cpu) > hv_max_vp_index)
                hv_max_vp_index = VMBUS_PCPU_GET(sc, vcpuid, cpu);
-       hv_cpu_mem = DPCPU_ID_PTR(cpu, hv_pcpu_mem);
-       *hv_cpu_mem = contigmalloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO,
-           0ul, ~0ul, PAGE_SIZE, 0);
-
-#if defined(__x86_64__)
-       if (*hv_cpu_mem == NULL && hv_tlb_hcall) {
-               hv_tlb_hcall = 0;
-               if (bootverbose && sc)
-                       device_printf(sc->vmbus_dev,
-                           "cannot alloc contig memory for hv_pcpu_mem, "
-                           "use system provided tlb flush call.\n");
-       }
-#endif
 
        /*
         * Setup the SynIC message.
@@ -858,7 +846,6 @@ vmbus_synic_teardown(void *arg)
         */
        orig = RDMSR(MSR_HV_SIEFP);
        WRMSR(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
-       free_pcpu_ptr();
 }
 
 static int
@@ -1412,15 +1399,41 @@ vmbus_probe(device_t dev)
        return (BUS_PROBE_DEFAULT);
 }
 
+#if defined(__x86_64__)
+static int
+vmbus_alloc_cpu_mem(struct vmbus_softc *sc)
+{
+       int cpu;
 
-static void free_pcpu_ptr(void)
+       CPU_FOREACH(cpu) {
+               void **hv_cpu_mem;
+
+               hv_cpu_mem = VMBUS_PCPU_PTR(sc, cpu_mem, cpu);
+               *hv_cpu_mem = contigmalloc(PAGE_SIZE, M_DEVBUF,
+                   M_NOWAIT | M_ZERO, 0ul, ~0ul, PAGE_SIZE, 0);
+
+               if (*hv_cpu_mem == NULL)
+                       return ENOMEM;
+       }
+
+       return 0;
+}
+
+static void
+vmbus_free_cpu_mem(struct vmbus_softc *sc)
 {
-       int cpu = curcpu;
-       void **hv_cpu_mem;
-       hv_cpu_mem = DPCPU_ID_PTR(cpu, hv_pcpu_mem);
-       if(*hv_cpu_mem)
-               contigfree(*hv_cpu_mem, PAGE_SIZE, M_DEVBUF);
+       int cpu;
+
+       CPU_FOREACH(cpu) {
+               void **hv_cpu_mem;
+               hv_cpu_mem = VMBUS_PCPU_PTR(sc, cpu_mem, cpu);
+               if(*hv_cpu_mem != NULL) {
+                       contigfree(*hv_cpu_mem, PAGE_SIZE, M_DEVBUF);
+                       *hv_cpu_mem = NULL;
+               }
+       }
 }
+#endif
 
 /**
  * @brief Main vmbus driver initialization routine.
@@ -1511,6 +1524,25 @@ vmbus_doattach(struct vmbus_softc *sc)
        if (ret != 0)
                goto cleanup;
 
+#if defined(__x86_64__)
+       /*
+        * Alloc per cpu memory for tlb flush hypercall
+        */
+       if (hv_tlb_hcall) {
+               ret = vmbus_alloc_cpu_mem(sc);
+               if (ret != 0) {
+                       hv_tlb_hcall = 0;
+                       if (bootverbose)
+                               device_printf(sc->vmbus_dev,
+                                   "cannot alloc contig memory for "
+                                   "cpu_mem, use system provided "
+                                   "tlb flush call.\n");
+
+                       vmbus_free_cpu_mem(sc);
+               }
+       }
+#endif
+
        /*
         * Setup SynIC.
         */
@@ -1627,6 +1659,16 @@ vmbus_detach(device_t dev)
                smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
        }
 
+#if defined(__x86_64__)
+       /*
+        * Restore the tlb flush to native call
+        */
+       if (hv_tlb_hcall) {
+               smp_targeted_tlb_shootdown = &smp_targeted_tlb_shootdown_native;
+               vmbus_free_cpu_mem(sc);
+       }
+#endif
+
        vmbus_intr_teardown(sc);
        vmbus_dma_free(sc);
 
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index 4f0668476716..4e0a769402d5 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -74,6 +74,9 @@ struct vmbus_pcpu_data {
        uint32_t                vcpuid;         /* virtual cpuid */
        int                     event_flags_cnt;/* # of event flags */
        struct vmbus_evtflags   *event_flags;   /* event flags from host */
+#if defined(__x86_64__)
+       void                    *cpu_mem;       /* For Hyper-V tlb hypercall */
+#endif
 
        /* Rarely used fields */
        struct taskqueue        *event_tq;      /* event taskq */
@@ -216,8 +219,6 @@ void    vmbus_synic_teardown1(void);
 int     vmbus_setup_intr1(struct vmbus_softc *sc);
 void    vmbus_intr_teardown1(struct vmbus_softc *sc);
 
-DPCPU_DECLARE(void *, hv_pcpu_mem);
-
 extern uint32_t hv_max_vp_index;
 
 

Reply via email to