aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorWei Hu <whu@FreeBSD.org>2024-06-15 14:07:58 +0000
committerWei Hu <whu@FreeBSD.org>2024-06-15 14:07:58 +0000
commitd0cb4674df97aa638d5d17861c364b1625f79401 (patch)
tree2fc936ded6777043ca36e686d0ee4aee391569a2 /sys/dev/hyperv
parentd26c565597b88eb5c6000dbba9e348debe7095e3 (diff)
downloadsrc-d0cb4674df97aa638d5d17861c364b1625f79401.tar.gz
src-d0cb4674df97aa638d5d17861c364b1625f79401.zip
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
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_mmu.c6
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c88
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h5
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 f55f0329b017..dee738f6e373 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;