mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-01 14:14:56 +00:00
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:
parent
d26c565597
commit
d0cb4674df
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue