Esempio n. 1
0
int set_global_virq_handler(struct domain *d, uint32_t virq)
{
    struct domain *old;

    if (virq >= NR_VIRQS)
        return -EINVAL;
    if (!virq_is_global(virq))
        return -EINVAL;

    if (global_virq_handlers[virq] == d)
        return 0;

    if (unlikely(!get_domain(d)))
        return -EINVAL;

    spin_lock(&global_virq_handlers_lock);
    old = global_virq_handlers[virq];
    global_virq_handlers[virq] = d;
    spin_unlock(&global_virq_handlers_lock);

    if (old != NULL)
        put_domain(old);

    return 0;
}
Esempio n. 2
0
void send_global_virq(uint32_t virq)
{
    ASSERT(virq < NR_VIRQS);
    ASSERT(virq_is_global(virq));

    send_guest_global_virq(global_virq_handlers[virq] ?: dom0, virq);
}
Esempio n. 3
0
static void send_guest_global_virq(struct domain *d, uint32_t virq)
{
    unsigned long flags;
    int port;
    struct vcpu *v;
    struct evtchn *chn;

    ASSERT(virq_is_global(virq));

    if ( unlikely(d == NULL) || unlikely(d->vcpu == NULL) )
        return;

    v = d->vcpu[0];
    if ( unlikely(v == NULL) )
        return;

    spin_lock_irqsave(&v->virq_lock, flags);

    port = v->virq_to_evtchn[virq];
    if ( unlikely(port == 0) )
        goto out;

    chn = evtchn_from_port(d, port);
    evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);

 out:
    spin_unlock_irqrestore(&v->virq_lock, flags);
}
Esempio n. 4
0
long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id)
{
    struct domain *d = current->domain;
    struct evtchn *chn;
    long           rc = 0;

    if ( (vcpu_id >= d->max_vcpus) || (d->vcpu[vcpu_id] == NULL) )
        return -ENOENT;

    spin_lock(&d->event_lock);

    if ( !port_is_valid(d, port) )
    {
        rc = -EINVAL;
        goto out;
    }

    chn = evtchn_from_port(d, port);

    /* Guest cannot re-bind a Xen-attached event channel. */
    if ( unlikely(consumer_is_xen(chn)) )
    {
        rc = -EINVAL;
        goto out;
    }

    switch ( chn->state )
    {
    case ECS_VIRQ:
        if ( virq_is_global(chn->u.virq) )
            chn->notify_vcpu_id = vcpu_id;
        else
            rc = -EINVAL;
        break;
    case ECS_UNBOUND:
    case ECS_INTERDOMAIN:
        chn->notify_vcpu_id = vcpu_id;
        break;
    case ECS_PIRQ:
        if ( chn->notify_vcpu_id == vcpu_id )
            break;
        unlink_pirq_port(chn, d->vcpu[chn->notify_vcpu_id]);
        chn->notify_vcpu_id = vcpu_id;
        pirq_set_affinity(d, chn->u.pirq.irq,
                          cpumask_of(d->vcpu[vcpu_id]->processor));
        link_pirq_port(port, chn, d->vcpu[vcpu_id]);
        break;
    default:
        rc = -EINVAL;
        break;
    }

 out:
    spin_unlock(&d->event_lock);

    return rc;
}
Esempio n. 5
0
void send_guest_vcpu_virq(struct vcpu *v, uint32_t virq)
{
    unsigned long flags;
    int port;

    ASSERT(!virq_is_global(virq));

    spin_lock_irqsave(&v->virq_lock, flags);

    port = v->virq_to_evtchn[virq];
    if ( unlikely(port == 0) )
        goto out;

    evtchn_set_pending(v, port);

 out:
    spin_unlock_irqrestore(&v->virq_lock, flags);
}
static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
{
    struct evtchn *chn;
    struct vcpu   *v;
    struct domain *d = current->domain;
    int            port, virq = bind->virq, vcpu = bind->vcpu;
    long           rc = 0;

    if ( (virq < 0) || (virq >= ARRAY_SIZE(v->virq_to_evtchn)) )
        return -EINVAL;

    if ( virq_is_global(virq) && (vcpu != 0) )
        return -EINVAL;

    if ( (vcpu < 0) || (vcpu >= ARRAY_SIZE(d->vcpu)) ||
         ((v = d->vcpu[vcpu]) == NULL) )
        return -ENOENT;

    spin_lock(&d->evtchn_lock);

    if ( v->virq_to_evtchn[virq] != 0 )
        ERROR_EXIT(-EEXIST);

    if ( (port = get_free_port(d)) < 0 )
        ERROR_EXIT(port);

    chn = evtchn_from_port(d, port);
    chn->state          = ECS_VIRQ;
    chn->notify_vcpu_id = vcpu;
    chn->u.virq         = virq;

    v->virq_to_evtchn[virq] = bind->port = port;

 out:
    spin_unlock(&d->evtchn_lock);

    return rc;
}