void
gcpu_mca_poll_start(cmi_hdl_t hdl)
{
	ASSERT(cmi_hdl_class(hdl) == CMI_HDL_SOLARIS_xVM_MCA);
	/*
	 * We are on the boot cpu (cpu 0), called at the end of its
	 * multiprocessor startup.
	 */
	if (gcpu_xpv_poll_bankregs_sz != 0 && gcpu_xpv_virq_vect == -1) {
		/*
		 * The hypervisor will poll MCA state for us, but it cannot
		 * poll MCH state so we do that via a timeout.
		 */
		if (gcpu_xpv_mch_poll_interval_secs != 0) {
			gcpu_xpv_mch_poll_timeoutid =
			    timeout(gcpu_xpv_mch_poll, GCPU_XPV_MCH_POLL_REARM,
			    drv_usectohz(gcpu_xpv_mch_poll_interval_secs *
			    MICROSEC));
		}

		/*
		 * Register handler for VIRQ_MCA; once this is in place
		 * the hypervisor will begin to forward polled MCA observations
		 * to us.
		 */
		gcpu_xpv_virq_vect = ec_bind_virq_to_irq(VIRQ_MCA, 0);
		(void) add_avintr(NULL, gcpu_xpv_virq_level,
		    (avfunc)gcpu_xpv_virq_intr, "MCA", gcpu_xpv_virq_vect,
		    NULL, NULL, NULL, NULL);
	}
}
Exemple #2
0
static int
evtchndrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	int	error;
	int	unit = ddi_get_instance(dip);


	switch (cmd) {
	case DDI_ATTACH:
		break;
	case DDI_RESUME:
		return (DDI_SUCCESS);
	default:
		cmn_err(CE_WARN, "evtchn_attach: unknown cmd 0x%x\n", cmd);
		return (DDI_FAILURE);
	}

	/* DDI_ATTACH */

	/*
	 * only one instance - but we clone using the open routine
	 */
	if (ddi_get_instance(dip) > 0)
		return (DDI_FAILURE);

	mutex_init(&evtchndrv_clone_tab_mutex, NULL, MUTEX_DRIVER,
	    NULL);

	error = ddi_create_minor_node(dip, "evtchn", S_IFCHR, unit,
	    DDI_PSEUDO, NULL);
	if (error != DDI_SUCCESS)
		goto fail;

	/*
	 * save dip for getinfo
	 */
	evtchndrv_dip = dip;
	ddi_report_dev(dip);

	mutex_init(&port_user_lock, NULL, MUTEX_DRIVER, NULL);
	(void) memset(port_user, 0, sizeof (port_user));

	ec_dev_irq = ec_dev_alloc_irq();
	(void) add_avintr(NULL, IPL_EVTCHN, (avfunc)evtchn_device_upcall,
	    "evtchn_driver", ec_dev_irq, NULL, NULL, NULL, dip);

	return (DDI_SUCCESS);

fail:
	(void) evtchndrv_detach(dip, DDI_DETACH);
	return (error);
}
void
xb_setup_intr(void)
{
#ifdef XPV_HVM_DRIVER
	ec_bind_evtchn_to_handler(xen_info->store_evtchn, IPL_XENBUS,
	    xenbus_intr, NULL);
#else
	xenbus_irq = ec_bind_evtchn_to_irq(xen_info->store_evtchn);
	if (xenbus_irq < 0) {
		cmn_err(CE_WARN, "Couldn't bind xenbus event channel");
		return;
	}
	if (!add_avintr(NULL, IPL_XENBUS, (avfunc)xenbus_intr, "xenbus",
	    xenbus_irq, NULL, NULL, NULL, NULL))
		cmn_err(CE_WARN, "XENBUS add intr failed\n");
#endif
}
Exemple #4
0
static int
isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
    ddi_intr_handle_impl_t *hdlp, void *result)
{
	struct intrspec *ispec;
#if defined(__xpv)
	int cons, ttyn;

	cons = console_hypervisor_dev_type(&ttyn);
#endif
	if (pseudo_isa)
		return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));


	/* Process the interrupt operation */
	switch (intr_op) {
	case DDI_INTROP_GETCAP:
		/* First check with pcplusmp */
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_CAP, result)) {
			*(int *)result = 0;
			return (DDI_FAILURE);
		}
		break;
	case DDI_INTROP_SETCAP:
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result))
			return (DDI_FAILURE);
		break;
	case DDI_INTROP_ALLOC:
		ASSERT(hdlp->ih_type == DDI_INTR_TYPE_FIXED);
		return (isa_alloc_intr_fixed(rdip, hdlp, result));
	case DDI_INTROP_FREE:
		ASSERT(hdlp->ih_type == DDI_INTR_TYPE_FIXED);
		return (isa_free_intr_fixed(rdip, hdlp));
	case DDI_INTROP_GETPRI:
		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
			return (DDI_FAILURE);
		*(int *)result = ispec->intrspec_pri;
		break;
	case DDI_INTROP_SETPRI:
		/* Validate the interrupt priority passed to us */
		if (*(int *)result > LOCK_LEVEL)
			return (DDI_FAILURE);

		/* Ensure that PSM is all initialized and ispec is ok */
		if ((psm_intr_ops == NULL) ||
		    ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL))
			return (DDI_FAILURE);

		/* update the ispec with the new priority */
		ispec->intrspec_pri =  *(int *)result;
		break;
	case DDI_INTROP_ADDISR:
		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
			return (DDI_FAILURE);
		ispec->intrspec_func = hdlp->ih_cb_func;
		break;
	case DDI_INTROP_REMISR:
		if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
			return (DDI_FAILURE);
		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
			return (DDI_FAILURE);
		ispec->intrspec_func = (uint_t (*)()) 0;
		break;
	case DDI_INTROP_ENABLE:
		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
			return (DDI_FAILURE);

		/* Call psmi to translate irq with the dip */
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

#if defined(__xpv)
		/*
		 * if the hypervisor is using an isa serial port for the
		 * console, make sure we don't try to use that interrupt as
		 * it will cause us to panic when xen_bind_pirq() fails.
		 */
		if (cons == CONS_TTY && ispec->intrspec_vec == asy_intrs[ttyn])
			return (DDI_FAILURE);
#endif
		((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
		    (int *)&hdlp->ih_vector) == PSM_FAILURE)
			return (DDI_FAILURE);

		/* Add the interrupt handler */
		if (!add_avintr((void *)hdlp, ispec->intrspec_pri,
		    hdlp->ih_cb_func, DEVI(rdip)->devi_name, hdlp->ih_vector,
		    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2, NULL, rdip))
			return (DDI_FAILURE);
		break;
	case DDI_INTROP_DISABLE:
		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
			return (DDI_FAILURE);

		/* Call psm_ops() to translate irq with the dip */
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
		(void) (*psm_intr_ops)(rdip, hdlp,
		    PSM_INTR_OP_XLATE_VECTOR, (int *)&hdlp->ih_vector);

		/* Remove the interrupt handler */
		rem_avintr((void *)hdlp, ispec->intrspec_pri,
		    hdlp->ih_cb_func, hdlp->ih_vector);
		break;
	case DDI_INTROP_SETMASK:
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_MASK, NULL))
			return (DDI_FAILURE);
		break;
	case DDI_INTROP_CLRMASK:
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_CLEAR_MASK, NULL))
			return (DDI_FAILURE);
		break;
	case DDI_INTROP_GETPENDING:
		if (psm_intr_ops == NULL)
			return (DDI_FAILURE);

		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_PENDING,
		    result)) {
			*(int *)result = 0;
			return (DDI_FAILURE);
		}
		break;
	case DDI_INTROP_NAVAIL:
	case DDI_INTROP_NINTRS:
		*(int *)result = i_ddi_get_intx_nintrs(rdip);
		if (*(int *)result == 0) {
			return (DDI_FAILURE);
		}
		break;
	case DDI_INTROP_SUPPORTED_TYPES:
		*(int *)result = DDI_INTR_TYPE_FIXED;	/* Always ... */
		break;
	default:
		return (DDI_FAILURE);
	}

	return (DDI_SUCCESS);
}
Exemple #5
0
int
psm_add_intr(int lvl, avfunc xxintr, char *name, int vect, caddr_t arg)
{
	return (add_avintr((void *)NULL, lvl, xxintr, name, vect,
	    arg, NULL, NULL, NULL));
}