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;
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #7
0
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;
}
Пример #9
0
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;
}
Пример #11
0
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);
}
Пример #12
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);
}
Пример #13
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);
}
Пример #14
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);
}