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:		2b887687ed
MFC after:	2 weeks
Sponsored by:	Microsoft
This commit is contained in:
Wei Hu 2024-06-15 14:07:58 +00:00
parent d26c565597
commit d0cb4674df
3 changed files with 72 additions and 29 deletions

View file

@ -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;

View file

@ -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,16 +1399,42 @@ vmbus_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
static void free_pcpu_ptr(void)
#if defined(__x86_64__)
static int
vmbus_alloc_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);
*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;
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);

View file

@ -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;