Ejemplo n.º 1
0
int evtchn_send(struct domain *d, unsigned int lport)
{
    struct evtchn *lchn, *rchn;
    struct domain *ld = d, *rd;
    struct vcpu   *rvcpu;
    int            rport, ret = 0;

    spin_lock(&ld->event_lock);

    if ( unlikely(!port_is_valid(ld, lport)) )
    {
        spin_unlock(&ld->event_lock);
        return -EINVAL;
    }

    lchn = evtchn_from_port(ld, lport);

    /* Guest cannot send via a Xen-attached event channel. */
    if ( unlikely(consumer_is_xen(lchn)) )
    {
        spin_unlock(&ld->event_lock);
        return -EINVAL;
    }

    ret = xsm_evtchn_send(ld, lchn);
    if ( ret )
        goto out;

    switch ( lchn->state )
    {
    case ECS_INTERDOMAIN:
        rd    = lchn->u.interdomain.remote_dom;
        rport = lchn->u.interdomain.remote_port;
        rchn  = evtchn_from_port(rd, rport);
        rvcpu = rd->vcpu[rchn->notify_vcpu_id];
        if ( consumer_is_xen(rchn) )
            (*xen_notification_fn(rchn))(rvcpu, rport);
        else
            evtchn_set_pending(rvcpu, rport);
        break;
    case ECS_IPI:
        evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
        break;
    case ECS_UNBOUND:
        /* silently drop the notification */
        break;
    default:
        ret = -EINVAL;
    }

out:
    spin_unlock(&ld->event_lock);

    return ret;
}
Ejemplo n.º 2
0
long evtchn_send(unsigned int lport)
{
    struct evtchn *lchn, *rchn;
    struct domain *ld = current->domain, *rd;
    struct vcpu   *rvcpu;
    int            rport, ret = 0;

    spin_lock(&ld->evtchn_lock);

    if ( unlikely(!port_is_valid(ld, lport)) )
    {
        spin_unlock(&ld->evtchn_lock);
        return -EINVAL;
    }

    lchn = evtchn_from_port(ld, lport);

    /* Guest cannot send via a Xen-attached event channel. */
    if ( unlikely(lchn->consumer_is_xen) )
    {
        spin_unlock(&ld->evtchn_lock);
        return -EINVAL;
    }

    ret = xsm_evtchn_send(ld, lchn);
    if ( ret )
        goto out;

    switch ( lchn->state )
    {
    case ECS_INTERDOMAIN:
        rd    = lchn->u.interdomain.remote_dom;
        rport = lchn->u.interdomain.remote_port;
        rchn  = evtchn_from_port(rd, rport);
        rvcpu = rd->vcpu[rchn->notify_vcpu_id];
        if ( rchn->consumer_is_xen )
        {
            /* Xen consumers need notification only if they are blocked. */
            if ( test_and_clear_bit(_VPF_blocked_in_xen,
                                    &rvcpu->pause_flags) )
                vcpu_wake(rvcpu);
        }
        else
        {
            evtchn_set_pending(rvcpu, rport);
        }
        break;
    case ECS_IPI:
        evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
        break;
    case ECS_UNBOUND:
        /* silently drop the notification */
        break;
    default:
        ret = -EINVAL;
    }

out:
    spin_unlock(&ld->evtchn_lock);

    return ret;
}