static void vmbus_bus_exit(void) { int i; hv_vmbus_release_unattached_channels(); hv_vmbus_disconnect(); smp_rendezvous(NULL, hv_vmbus_synic_cleanup, NULL, NULL); for(i = 0; i < 2 * MAXCPU; i++) { if (setup_args.page_buffers[i] != 0) free(setup_args.page_buffers[i], M_DEVBUF); } hv_vmbus_cleanup(); /* remove swi */ CPU_FOREACH(i) { if (hv_vmbus_g_context.msg_swintr[i] != NULL) swi_remove(hv_vmbus_g_context.msg_swintr[i]); if (hv_vmbus_g_context.event_swintr[i] != NULL) swi_remove(hv_vmbus_g_context.event_swintr[i]); hv_vmbus_g_context.hv_msg_intr_event[i] = NULL; hv_vmbus_g_context.hv_event_intr_event[i] = NULL; } vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); return; }
static void rtTimerFreeBSDCallback(void *pvTimer) { PRTTIMER pTimer = (PRTTIMER)pvTimer; /* calculate and set the next timeout */ pTimer->iTick++; if (!pTimer->u64NanoInterval) { pTimer->fSuspended = true; callout_stop(&pTimer->Callout); } else { struct timeval tv; const uint64_t u64NanoTS = RTTimeNanoTS(); pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval; if (pTimer->u64NextTS < u64NanoTS) pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2; tv.tv_sec = pTimer->u64NextTS / 1000000000; tv.tv_usec = (pTimer->u64NextTS % 1000000000) / 1000; callout_reset(&pTimer->Callout, tvtohz(&tv), rtTimerFreeBSDCallback, pTimer); } /* callback */ if ( !pTimer->fSpecificCpu || pTimer->iCpu == curcpu) pTimer->pfnTimer(pTimer, pTimer->pvUser, pTimer->iTick); else smp_rendezvous(NULL, rtTimerFreeBSDIpiAction, NULL, pvTimer); }
static void vmbus_bus_exit(void) { int i; hv_vmbus_release_unattached_channels(); hv_vmbus_disconnect(); smp_rendezvous(NULL, hv_vmbus_synic_cleanup, NULL, NULL); for(i = 0; i < 2; i++) { if (setup_args.page_buffers[i] != 0) free(setup_args.page_buffers[i], M_DEVBUF); } hv_vmbus_cleanup(); /* remove swi, bus and intr resource */ bus_teardown_intr(vmbus_devp, intr_res, vmbus_cookiep); bus_release_resource(vmbus_devp, SYS_RES_IRQ, vmbus_rid, intr_res); swi_remove(msg_swintr); swi_remove(event_swintr); return; }
int lapic_enable_pmc(void) { #ifdef HWPMC_HOOKS u_int32_t maxlvt; /* Fail if the local APIC is not present. */ if (lapic == NULL) return (0); /* Fail if the PMC LVT is not present. */ maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT; if (maxlvt < LVT_PMC) return (0); lvts[LVT_PMC].lvt_masked = 0; #ifdef SMP /* * If hwpmc was loaded at boot time then the APs may not be * started yet. In that case, don't forward the request to * them as they will program the lvt when they start. */ if (smp_started) smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL); else #endif lapic_update_pmc(NULL); return (1); #else return (0); #endif }
RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { /* Will panic if no rendezvousing cpus, so check up front. */ if (RTMpGetOnlineCount() > 1) { #if __FreeBSD_version >= 900000 cpuset_t Mask; #elif __FreeBSD_version >= 700000 cpumask_t Mask; #endif RTMPARGS Args; Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = RTMpCpuId(); Args.cHits = 0; #if __FreeBSD_version >= 700000 # if __FreeBSD_version >= 900000 Mask = all_cpus; CPU_CLR(curcpu, &Mask); # else Mask = ~(cpumask_t)curcpu; # endif smp_rendezvous_cpus(Mask, NULL, rtmpOnOthersFreeBSDWrapper, smp_no_rendezvous_barrier, &Args); #else smp_rendezvous(NULL, rtmpOnOthersFreeBSDWrapper, NULL, &Args); #endif } return VINF_SUCCESS; }
RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { #if __FreeBSD_version >= 900000 cpuset_t Mask; #elif __FreeBSD_version >= 700000 cpumask_t Mask; #endif RTMPARGS Args; /* Will panic if no rendezvousing cpus, so make sure the cpu is online. */ if (!RTMpIsCpuOnline(idCpu)) return VERR_CPU_NOT_FOUND; Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = idCpu; Args.cHits = 0; #if __FreeBSD_version >= 700000 # if __FreeBSD_version >= 900000 CPU_SETOF(idCpu, &Mask); # else Mask = (cpumask_t)1 << idCpu; # endif smp_rendezvous_cpus(Mask, NULL, rtmpOnSpecificFreeBSDWrapper, smp_no_rendezvous_barrier, &Args); #else smp_rendezvous(NULL, rtmpOnSpecificFreeBSDWrapper, NULL, &Args); #endif return Args.cHits == 1 ? VINF_SUCCESS : VERR_CPU_NOT_FOUND; }
void ept_invalidate_mappings(u_long eptp) { struct invept_desc invept_desc = { 0 }; invept_desc.eptp = eptp; smp_rendezvous(NULL, invept_single_context, NULL, &invept_desc); }
RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) { RTMPARGS Args; Args.pfnWorker = pfnWorker; Args.pvUser1 = pvUser1; Args.pvUser2 = pvUser2; Args.idCpu = NIL_RTCPUID; Args.cHits = 0; smp_rendezvous(NULL, rtmpOnAllFreeBSDWrapper, smp_no_rendezvous_barrier, &Args); return VINF_SUCCESS; }
int windrv_libinit(void) { STAILQ_INIT(&drvdb_head); mtx_init(&drvdb_mtx, "Windows driver DB lock", "Windows internal lock", MTX_DEF); #ifdef __amd64__ LIST_INIT(&fpu_free_head); LIST_INIT(&fpu_busy_head); mtx_init(&fpu_free_mtx, "free fpu context list lock", NULL, MTX_DEF); mtx_init(&fpu_busy_mtx, "busy fpu context list lock", NULL, MTX_DEF); #endif /* * PCI and pccard devices don't need to use IRPs to * interact with their bus drivers (usually), so our * emulated PCI and pccard drivers are just stubs. * USB devices, on the other hand, do all their I/O * by exchanging IRPs with the USB bus driver, so * for that we need to provide emulator dispatcher * routines, which are in a separate module. */ windrv_bus_attach(&fake_pci_driver, "PCI Bus"); windrv_bus_attach(&fake_pccard_driver, "PCCARD Bus"); #ifdef __i386__ /* * In order to properly support SMP machines, we have * to modify the GDT on each CPU, since we never know * on which one we'll end up running. */ my_tids = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct tid) * mp_ncpus, 0); if (my_tids == NULL) panic("failed to allocate thread info blocks"); smp_rendezvous(NULL, x86_newldt, NULL, NULL); #endif return (0); }
static void vmbus_bus_exit(void) { hv_vmbus_release_unattached_channels(); hv_vmbus_disconnect(); smp_rendezvous(NULL, hv_vmbus_synic_cleanup, NULL, NULL); hv_vmbus_cleanup(); /* remove swi, bus and intr resource */ bus_teardown_intr(vmbus_devp, intr_res, vmbus_cookiep); bus_release_resource(vmbus_devp, SYS_RES_IRQ, vmbus_rid, intr_res); swi_remove(msg_swintr); swi_remove(event_swintr); return; }
static int mpc85xx_jog_set(device_t dev, const struct cf_setting *set) { struct mpc85xx_jog_softc *sc; struct jog_rv_args args; if (set == NULL) return (EINVAL); sc = device_get_softc(dev); args.slow = (set->freq <= sc->min_freq); args.mult = set->spec[0]; args.cpu = PCPU_GET(cpuid); args.inprogress = 1; smp_rendezvous(smp_no_rendezvous_barrier, mpc85xx_jog_set_int, smp_no_rendezvous_barrier, &args); return (0); }
int windrv_libfini(void) { struct drvdb_ent *d; #ifdef __amd64__ struct fpu_cc_ent *ent; #endif mtx_lock(&drvdb_mtx); while(STAILQ_FIRST(&drvdb_head) != NULL) { d = STAILQ_FIRST(&drvdb_head); STAILQ_REMOVE_HEAD(&drvdb_head, link); free(d, M_DEVBUF); } mtx_unlock(&drvdb_mtx); RtlFreeUnicodeString(&fake_pci_driver.dro_drivername); RtlFreeUnicodeString(&fake_pccard_driver.dro_drivername); mtx_destroy(&drvdb_mtx); #ifdef __i386__ smp_rendezvous(NULL, x86_oldldt, NULL, NULL); ExFreePool(my_tids); #endif #ifdef __amd64__ while ((ent = LIST_FIRST(&fpu_free_head)) != NULL) { LIST_REMOVE(ent, entries); fpu_kern_free_ctx(ent->ctx); free(ent, M_DEVBUF); } mtx_destroy(&fpu_free_mtx); ent = LIST_FIRST(&fpu_busy_head); KASSERT(ent == NULL, ("busy fpu context list is not empty")); mtx_destroy(&fpu_busy_mtx); #endif return (0); }
int windrv_libfini(void) { struct drvdb_ent *d; mtx_lock(&drvdb_mtx); while(STAILQ_FIRST(&drvdb_head) != NULL) { d = STAILQ_FIRST(&drvdb_head); STAILQ_REMOVE_HEAD(&drvdb_head, link); free(d, M_DEVBUF); } mtx_unlock(&drvdb_mtx); RtlFreeUnicodeString(&fake_pci_driver.dro_drivername); RtlFreeUnicodeString(&fake_pccard_driver.dro_drivername); mtx_destroy(&drvdb_mtx); #ifdef __i386__ smp_rendezvous(NULL, x86_oldldt, NULL, NULL); ExFreePool(my_tids); #endif return (0); }
void lapic_disable_pmc(void) { #ifdef HWPMC_HOOKS u_int32_t maxlvt; /* Fail if the local APIC is not present. */ if (lapic == NULL) return; /* Fail if the PMC LVT is not present. */ maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT; if (maxlvt < LVT_PMC) return; lvts[LVT_PMC].lvt_masked = 1; #ifdef SMP /* The APs should always be started when hwpmc is unloaded. */ KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early")); #endif smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL); #endif }
/** * @brief Main vmbus driver initialization routine. * * Here, we * - initialize the vmbus driver context * - setup various driver entry points * - invoke the vmbus hv main init routine * - get the irq resource * - invoke the vmbus to add the vmbus root device * - setup the vmbus root device * - retrieve the channel offers */ static int vmbus_bus_init(void) { struct ioapic_intsrc { struct intsrc io_intsrc; u_int io_irq; u_int io_intpin:8; u_int io_vector:8; u_int io_cpu:8; u_int io_activehi:1; u_int io_edgetrigger:1; u_int io_masked:1; int io_bus:4; uint32_t io_lowreg; }; int ret; unsigned int vector = 0; struct intsrc *isrc; struct ioapic_intsrc *intpin; if (vmbus_inited) return (0); vmbus_inited = 1; ret = hv_vmbus_init(); if (ret) { if(bootverbose) printf("Error VMBUS: Hypervisor Initialization Failed!\n"); return (ret); } ret = swi_add(&hv_msg_intr_event, "hv_msg", vmbus_msg_swintr, NULL, SWI_CLOCK, 0, &msg_swintr); if (ret) goto cleanup; /* * Message SW interrupt handler checks a per-CPU page and * thus the thread needs to be bound to CPU-0 - which is where * all interrupts are processed. */ ret = intr_event_bind(hv_msg_intr_event, 0); if (ret) goto cleanup1; ret = swi_add(&hv_event_intr_event, "hv_event", hv_vmbus_on_events, NULL, SWI_CLOCK, 0, &event_swintr); if (ret) goto cleanup1; intr_res = bus_alloc_resource(vmbus_devp, SYS_RES_IRQ, &vmbus_rid, vmbus_irq, vmbus_irq, 1, RF_ACTIVE); if (intr_res == NULL) { ret = ENOMEM; /* XXXKYS: Need a better errno */ goto cleanup2; } /* * Setup interrupt filter handler */ ret = bus_setup_intr(vmbus_devp, intr_res, INTR_TYPE_NET | INTR_MPSAFE, hv_vmbus_isr, NULL, NULL, &vmbus_cookiep); if (ret != 0) goto cleanup3; ret = bus_bind_intr(vmbus_devp, intr_res, 0); if (ret != 0) goto cleanup4; isrc = intr_lookup_source(vmbus_irq); if ((isrc == NULL) || (isrc->is_event == NULL)) { ret = EINVAL; goto cleanup4; } /* vector = isrc->is_event->ie_vector; */ intpin = (struct ioapic_intsrc *)isrc; vector = intpin->io_vector; if(bootverbose) printf("VMBUS: irq 0x%x vector 0x%x\n", vmbus_irq, vector); /** * Notify the hypervisor of our irq. */ smp_rendezvous(NULL, hv_vmbus_synic_init, NULL, &vector); /** * Connect to VMBus in the root partition */ ret = hv_vmbus_connect(); if (ret) goto cleanup4; hv_vmbus_request_channel_offers(); return (ret); cleanup4: /* * remove swi, bus and intr resource */ bus_teardown_intr(vmbus_devp, intr_res, vmbus_cookiep); cleanup3: bus_release_resource(vmbus_devp, SYS_RES_IRQ, vmbus_rid, intr_res); cleanup2: swi_remove(event_swintr); cleanup1: swi_remove(msg_swintr); cleanup: hv_vmbus_cleanup(); return (ret); }
/** * @brief Main vmbus driver initialization routine. * * Here, we * - initialize the vmbus driver context * - setup various driver entry points * - invoke the vmbus hv main init routine * - get the irq resource * - invoke the vmbus to add the vmbus root device * - setup the vmbus root device * - retrieve the channel offers */ static int vmbus_bus_init(void) { int i, j, n, ret; if (vmbus_inited) return (0); vmbus_inited = 1; ret = hv_vmbus_init(); if (ret) { if(bootverbose) printf("Error VMBUS: Hypervisor Initialization Failed!\n"); return (ret); } /* * Find a free IDT slot for vmbus callback. */ hv_vmbus_g_context.hv_cb_vector = vmbus_vector_alloc(); if (hv_vmbus_g_context.hv_cb_vector == 0) { if(bootverbose) printf("Error VMBUS: Cannot find free IDT slot for " "vmbus callback!\n"); goto cleanup; } if(bootverbose) printf("VMBUS: vmbus callback vector %d\n", hv_vmbus_g_context.hv_cb_vector); /* * Notify the hypervisor of our vector. */ setup_args.vector = hv_vmbus_g_context.hv_cb_vector; CPU_FOREACH(j) { hv_vmbus_intr_cpu[j] = 0; hv_vmbus_swintr_event_cpu[j] = 0; hv_vmbus_g_context.hv_event_intr_event[j] = NULL; hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; hv_vmbus_g_context.event_swintr[j] = NULL; hv_vmbus_g_context.msg_swintr[j] = NULL; for (i = 0; i < 2; i++) setup_args.page_buffers[2 * j + i] = NULL; } /* * Per cpu setup. */ CPU_FOREACH(j) { /* * Setup software interrupt thread and handler for msg handling. */ ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j], "hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0, &hv_vmbus_g_context.msg_swintr[j]); if (ret) { if(bootverbose) printf("VMBUS: failed to setup msg swi for " "cpu %d\n", j); goto cleanup1; } /* * Bind the swi thread to the cpu. */ ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j], j); if (ret) { if(bootverbose) printf("VMBUS: failed to bind msg swi thread " "to cpu %d\n", j); goto cleanup1; } /* * Setup software interrupt thread and handler for * event handling. */ ret = swi_add(&hv_vmbus_g_context.hv_event_intr_event[j], "hv_event", hv_vmbus_on_events, (void *)(long)j, SWI_CLOCK, 0, &hv_vmbus_g_context.event_swintr[j]); if (ret) { if(bootverbose) printf("VMBUS: failed to setup event swi for " "cpu %d\n", j); goto cleanup1; } /* * Prepare the per cpu msg and event pages to be called on each cpu. */ for(i = 0; i < 2; i++) { setup_args.page_buffers[2 * j + i] = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); if (setup_args.page_buffers[2 * j + i] == NULL) { KASSERT(setup_args.page_buffers[2 * j + i] != NULL, ("Error VMBUS: malloc failed!")); goto cleanup1; } } } if (bootverbose) printf("VMBUS: Calling smp_rendezvous, smp_started = %d\n", smp_started); smp_rendezvous(NULL, hv_vmbus_synic_init, NULL, &setup_args); /* * Connect to VMBus in the root partition */ ret = hv_vmbus_connect(); if (ret != 0) goto cleanup1; hv_vmbus_request_channel_offers(); return (ret); cleanup1: /* * Free pages alloc'ed */ for (n = 0; n < 2 * MAXCPU; n++) if (setup_args.page_buffers[n] != NULL) free(setup_args.page_buffers[n], M_DEVBUF); /* * remove swi and vmbus callback vector; */ CPU_FOREACH(j) { if (hv_vmbus_g_context.msg_swintr[j] != NULL) swi_remove(hv_vmbus_g_context.msg_swintr[j]); if (hv_vmbus_g_context.event_swintr[j] != NULL) swi_remove(hv_vmbus_g_context.event_swintr[j]); hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; hv_vmbus_g_context.hv_event_intr_event[j] = NULL; } vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); cleanup: hv_vmbus_cleanup(); return (ret); }