diff options
author | Jan Beulich <jbeulich@novell.com> | 2011-06-23 11:32:43 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2011-06-23 11:32:43 +0100 |
commit | c24536b636f23e4d3202968fcad129d979881e2c (patch) | |
tree | e3e188d484b371f8770714bc0453f6395d6da241 /xen/arch/x86/irq.c | |
parent | eebfd58f212c5fb75e602ac1aa126863452375da (diff) | |
download | xen-c24536b636f23e4d3202968fcad129d979881e2c.tar.gz xen-c24536b636f23e4d3202968fcad129d979881e2c.tar.bz2 xen-c24536b636f23e4d3202968fcad129d979881e2c.zip |
replace d->nr_pirqs sized arrays with radix tree
With this it is questionable whether retaining struct domain's
nr_pirqs is actually necessary - the value now only serves for bounds
checking, and this boundary could easily be nr_irqs.
Note that ia64, the build of which is broken currently anyway, is only
being partially fixed up.
v2: adjustments for split setup/teardown of translation data
v3: re-sync with radix tree implementation changes
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/arch/x86/irq.c')
-rw-r--r-- | xen/arch/x86/irq.c | 304 |
1 files changed, 199 insertions, 105 deletions
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 0a84bf8dfb..b8366bedc4 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -814,7 +814,7 @@ static void irq_guest_eoi_timer_fn(void *data) { struct domain *d = action->guest[i]; unsigned int pirq = domain_irq_to_pirq(d, irq); - if ( test_and_clear_bit(pirq, d->pirq_mask) ) + if ( test_and_clear_bool(pirq_info(d, pirq)->masked) ) action->in_flight--; } } @@ -874,11 +874,12 @@ static void __do_IRQ_guest(int irq) for ( i = 0; i < action->nr_guests; i++ ) { - unsigned int pirq; + struct pirq *pirq; + d = action->guest[i]; - pirq = domain_irq_to_pirq(d, irq); + pirq = pirq_info(d, domain_irq_to_pirq(d, irq)); if ( (action->ack_type != ACKTYPE_NONE) && - !test_and_set_bit(pirq, d->pirq_mask) ) + !test_and_set_bool(pirq->masked) ) action->in_flight++; if ( hvm_do_IRQ_dpci(d, pirq) ) { @@ -950,31 +951,74 @@ struct irq_desc *domain_spin_lock_irq_desc( return desc; } -static int prepare_domain_irq_pirq(struct domain *d, int irq, int pirq) +/* + * Same with struct pirq already looked up, and d->event_lock already + * held (thus the PIRQ <-> IRQ mapping can't change under our feet). + */ +struct irq_desc *pirq_spin_lock_irq_desc( + struct domain *d, const struct pirq *pirq, unsigned long *pflags) +{ + int irq = pirq->arch.irq; + struct irq_desc *desc; + unsigned long flags; + + ASSERT(spin_is_locked(&d->event_lock)); + + if ( irq <= 0 ) + return NULL; + + desc = irq_to_desc(irq); + spin_lock_irqsave(&desc->lock, flags); + + if ( pflags ) + *pflags = flags; + + ASSERT(pirq == pirq_info(d, domain_irq_to_pirq(d, irq))); + ASSERT(irq == pirq->arch.irq); + + return desc; +} + +static int prepare_domain_irq_pirq(struct domain *d, int irq, int pirq, + struct pirq **pinfo) { int err = radix_tree_insert(&d->arch.irq_pirq, irq, radix_tree_int_to_ptr(0)); - return (err != -EEXIST) ? err : 0; + struct pirq *info; + + if ( err && err != -EEXIST ) + return err; + info = pirq_get_info(d, pirq); + if ( !info ) + { + if ( !err ) + radix_tree_delete(&d->arch.irq_pirq, irq); + return -ENOMEM; + } + *pinfo = info; + return 0; } -static void set_domain_irq_pirq(struct domain *d, int irq, int pirq) +static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq) { radix_tree_replace_slot( radix_tree_lookup_slot(&d->arch.irq_pirq, irq), - radix_tree_int_to_ptr(pirq)); - d->arch.pirq_irq[pirq] = irq; + radix_tree_int_to_ptr(pirq->pirq)); + pirq->arch.irq = irq; } -static void clear_domain_irq_pirq(struct domain *d, int irq, int pirq) +static void clear_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq) { - d->arch.pirq_irq[pirq] = 0; + pirq->arch.irq = 0; radix_tree_replace_slot( radix_tree_lookup_slot(&d->arch.irq_pirq, irq), radix_tree_int_to_ptr(0)); } -static void cleanup_domain_irq_pirq(struct domain *d, int irq, int pirq) +static void cleanup_domain_irq_pirq(struct domain *d, int irq, + struct pirq *pirq) { + pirq_cleanup_check(pirq, d); radix_tree_delete(&d->arch.irq_pirq, irq); } @@ -989,12 +1033,14 @@ int init_domain_irq_mapping(struct domain *d) for ( i = 1; platform_legacy_irq(i); ++i ) { + struct pirq *info; + if ( IO_APIC_IRQ(i) ) continue; - err = prepare_domain_irq_pirq(d, i, i); + err = prepare_domain_irq_pirq(d, i, i, &info); if ( err ) break; - set_domain_irq_pirq(d, i, i); + set_domain_irq_pirq(d, i, info); } if ( err ) @@ -1009,6 +1055,48 @@ void cleanup_domain_irq_mapping(struct domain *d) radix_tree_destroy(&d->arch.hvm_domain.emuirq_pirq, NULL); } +struct pirq *alloc_pirq_struct(struct domain *d) +{ + size_t sz = is_hvm_domain(d) ? sizeof(struct pirq) : + offsetof(struct pirq, arch.hvm); + struct pirq *pirq = xmalloc_bytes(sz); + + if ( pirq ) + { + memset(pirq, 0, sz); + if ( is_hvm_domain(d) ) + { + pirq->arch.hvm.emuirq = IRQ_UNBOUND; + pt_pirq_init(d, &pirq->arch.hvm.dpci); + } + } + + return pirq; +} + +void (pirq_cleanup_check)(struct pirq *pirq, struct domain *d) +{ + /* + * Check whether all fields have their default values, and delete + * the entry from the tree if so. + * + * NB: Common parts were already checked. + */ + if ( pirq->arch.irq ) + return; + + if ( is_hvm_domain(d) ) + { + if ( pirq->arch.hvm.emuirq != IRQ_UNBOUND ) + return; + if ( !pt_pirq_cleanup_check(&pirq->arch.hvm.dpci) ) + return; + } + + if ( radix_tree_delete(&d->pirq_tree, pirq->pirq) != pirq ) + BUG(); +} + /* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */ static void flush_ready_eoi(void) { @@ -1069,18 +1157,22 @@ static void set_eoi_ready(void *data) flush_ready_eoi(); } -static void __pirq_guest_eoi(struct domain *d, int pirq) +void pirq_guest_eoi(struct domain *d, struct pirq *pirq) +{ + struct irq_desc *desc; + + ASSERT(local_irq_is_enabled()); + desc = pirq_spin_lock_irq_desc(d, pirq, NULL); + if ( desc ) + desc_guest_eoi(d, desc, pirq); +} + +void desc_guest_eoi(struct domain *d, struct irq_desc *desc, struct pirq *pirq) { - struct irq_desc *desc; irq_guest_action_t *action; cpumask_t cpu_eoi_map; int irq; - ASSERT(local_irq_is_enabled()); - desc = domain_spin_lock_irq_desc(d, pirq, NULL); - if ( desc == NULL ) - return; - if ( !(desc->status & IRQ_GUEST) ) { spin_unlock_irq(&desc->lock); @@ -1092,12 +1184,12 @@ static void __pirq_guest_eoi(struct domain *d, int pirq) if ( action->ack_type == ACKTYPE_NONE ) { - ASSERT(!test_bit(pirq, d->pirq_mask)); + ASSERT(!pirq->masked); stop_timer(&action->eoi_timer); _irq_guest_eoi(desc); } - if ( unlikely(!test_and_clear_bit(pirq, d->pirq_mask)) || + if ( unlikely(!test_and_clear_bool(pirq->masked)) || unlikely(--action->in_flight != 0) ) { spin_unlock_irq(&desc->lock); @@ -1132,27 +1224,22 @@ static void __pirq_guest_eoi(struct domain *d, int pirq) on_selected_cpus(&cpu_eoi_map, set_eoi_ready, desc, 0); } -int pirq_guest_eoi(struct domain *d, int irq) -{ - if ( (irq < 0) || (irq >= d->nr_pirqs) ) - return -EINVAL; - - __pirq_guest_eoi(d, irq); - - return 0; -} - int pirq_guest_unmask(struct domain *d) { - unsigned int irq, nr = d->nr_pirqs; + unsigned int pirq = 0, n, i; + struct pirq *pirqs[16]; - for ( irq = find_first_bit(d->pirq_mask, nr); - irq < nr; - irq = find_next_bit(d->pirq_mask, nr, irq+1) ) - { - if ( !test_bit(d->pirq_to_evtchn[irq], &shared_info(d, evtchn_mask)) ) - __pirq_guest_eoi(d, irq); - } + do { + n = radix_tree_gang_lookup(&d->pirq_tree, (void **)pirqs, pirq, + ARRAY_SIZE(pirqs)); + for ( i = 0; i < n; ++i ) + { + pirq = pirqs[i]->pirq; + if ( pirqs[i]->masked && + !test_bit(pirqs[i]->evtchn, &shared_info(d, evtchn_mask)) ) + pirq_guest_eoi(d, pirqs[i]); + } + } while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) ); return 0; } @@ -1222,7 +1309,7 @@ int pirq_shared(struct domain *d, int pirq) return shared; } -int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) +int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, int will_share) { unsigned int irq; struct irq_desc *desc; @@ -1234,7 +1321,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) BUG_ON(!local_irq_is_enabled()); retry: - desc = domain_spin_lock_irq_desc(v->domain, pirq, NULL); + desc = pirq_spin_lock_irq_desc(v->domain, pirq, NULL); if ( desc == NULL ) { rc = -EINVAL; @@ -1250,7 +1337,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) { gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. In use by '%s'.\n", - pirq, desc->action->name); + pirq->pirq, desc->action->name); rc = -EBUSY; goto unlock_out; } @@ -1262,7 +1349,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) goto retry; gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. Out of memory.\n", - pirq); + pirq->pirq); rc = -ENOMEM; goto out; } @@ -1274,7 +1361,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) action->nr_guests = 0; action->in_flight = 0; action->shareable = will_share; - action->ack_type = pirq_acktype(v->domain, pirq); + action->ack_type = pirq_acktype(v->domain, pirq->pirq); cpus_clear(action->cpu_eoi_map); init_timer(&action->eoi_timer, irq_guest_eoi_timer_fn, desc, 0); @@ -1291,7 +1378,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) else if ( !will_share || !action->shareable ) { gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. %s.\n", - pirq, + pirq->pirq, will_share ? "Others do not share" : "Will not share with others"); @@ -1314,7 +1401,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) if ( action->nr_guests == IRQ_MAX_GUESTS ) { gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. " - "Already at max share.\n", pirq); + "Already at max share.\n", pirq->pirq); rc = -EBUSY; goto unlock_out; } @@ -1322,9 +1409,9 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) action->guest[action->nr_guests++] = v->domain; if ( action->ack_type != ACKTYPE_NONE ) - set_pirq_eoi(v->domain, pirq); + set_pirq_eoi(v->domain, pirq->pirq); else - clear_pirq_eoi(v->domain, pirq); + clear_pirq_eoi(v->domain, pirq->pirq); unlock_out: spin_unlock_irq(&desc->lock); @@ -1335,7 +1422,7 @@ int pirq_guest_bind(struct vcpu *v, int pirq, int will_share) } static irq_guest_action_t *__pirq_guest_unbind( - struct domain *d, int pirq, struct irq_desc *desc) + struct domain *d, struct pirq *pirq, struct irq_desc *desc) { unsigned int irq; irq_guest_action_t *action; @@ -1350,7 +1437,7 @@ static irq_guest_action_t *__pirq_guest_unbind( if ( unlikely(action == NULL) ) { dprintk(XENLOG_G_WARNING, "dom%d: pirq %d: desc->action is NULL!\n", - d->domain_id, pirq); + d->domain_id, pirq->pirq); return NULL; } @@ -1364,13 +1451,13 @@ static irq_guest_action_t *__pirq_guest_unbind( switch ( action->ack_type ) { case ACKTYPE_UNMASK: - if ( test_and_clear_bit(pirq, d->pirq_mask) && + if ( test_and_clear_bool(pirq->masked) && (--action->in_flight == 0) ) desc->handler->end(irq); break; case ACKTYPE_EOI: /* NB. If #guests == 0 then we clear the eoi_map later on. */ - if ( test_and_clear_bit(pirq, d->pirq_mask) && + if ( test_and_clear_bool(pirq->masked) && (--action->in_flight == 0) && (action->nr_guests != 0) ) { @@ -1388,9 +1475,9 @@ static irq_guest_action_t *__pirq_guest_unbind( /* * The guest cannot re-bind to this IRQ until this function returns. So, - * when we have flushed this IRQ from pirq_mask, it should remain flushed. + * when we have flushed this IRQ from ->masked, it should remain flushed. */ - BUG_ON(test_bit(pirq, d->pirq_mask)); + BUG_ON(pirq->masked); if ( action->nr_guests != 0 ) return NULL; @@ -1428,7 +1515,7 @@ static irq_guest_action_t *__pirq_guest_unbind( return action; } -void pirq_guest_unbind(struct domain *d, int pirq) +void pirq_guest_unbind(struct domain *d, struct pirq *pirq) { irq_guest_action_t *oldaction = NULL; struct irq_desc *desc; @@ -1437,11 +1524,11 @@ void pirq_guest_unbind(struct domain *d, int pirq) WARN_ON(!spin_is_locked(&d->event_lock)); BUG_ON(!local_irq_is_enabled()); - desc = domain_spin_lock_irq_desc(d, pirq, NULL); + desc = pirq_spin_lock_irq_desc(d, pirq, NULL); if ( desc == NULL ) { - irq = -domain_pirq_to_irq(d, pirq); + irq = -pirq->arch.irq; BUG_ON(irq <= 0); desc = irq_to_desc(irq); spin_lock_irq(&desc->lock); @@ -1463,7 +1550,7 @@ void pirq_guest_unbind(struct domain *d, int pirq) cleanup_domain_irq_pirq(d, irq, pirq); } -static int pirq_guest_force_unbind(struct domain *d, int irq) +static int pirq_guest_force_unbind(struct domain *d, struct pirq *pirq) { struct irq_desc *desc; irq_guest_action_t *action, *oldaction = NULL; @@ -1472,7 +1559,7 @@ static int pirq_guest_force_unbind(struct domain *d, int irq) WARN_ON(!spin_is_locked(&d->event_lock)); BUG_ON(!local_irq_is_enabled()); - desc = domain_spin_lock_irq_desc(d, irq, NULL); + desc = pirq_spin_lock_irq_desc(d, pirq, NULL); BUG_ON(desc == NULL); if ( !(desc->status & IRQ_GUEST) ) @@ -1482,7 +1569,7 @@ static int pirq_guest_force_unbind(struct domain *d, int irq) if ( unlikely(action == NULL) ) { dprintk(XENLOG_G_WARNING, "dom%d: pirq %d: desc->action is NULL!\n", - d->domain_id, irq); + d->domain_id, pirq->pirq); goto out; } @@ -1492,7 +1579,7 @@ static int pirq_guest_force_unbind(struct domain *d, int irq) goto out; bound = 1; - oldaction = __pirq_guest_unbind(d, irq, desc); + oldaction = __pirq_guest_unbind(d, pirq, desc); out: spin_unlock_irq(&desc->lock); @@ -1506,6 +1593,13 @@ static int pirq_guest_force_unbind(struct domain *d, int irq) return bound; } +static inline bool_t is_free_pirq(const struct domain *d, + const struct pirq *pirq) +{ + return !pirq || (!pirq->arch.irq && (!is_hvm_domain(d) || + pirq->arch.hvm.emuirq == IRQ_UNBOUND)); +} + int get_free_pirq(struct domain *d, int type, int index) { int i; @@ -1515,29 +1609,17 @@ int get_free_pirq(struct domain *d, int type, int index) if ( type == MAP_PIRQ_TYPE_GSI ) { for ( i = 16; i < nr_irqs_gsi; i++ ) - if ( !d->arch.pirq_irq[i] ) - { - if ( !is_hvm_domain(d) || - d->arch.pirq_emuirq[i] == IRQ_UNBOUND ) - break; - } - if ( i == nr_irqs_gsi ) - return -ENOSPC; + if ( is_free_pirq(d, pirq_info(d, i)) ) + return i; } else { for ( i = d->nr_pirqs - 1; i >= nr_irqs_gsi; i-- ) - if ( !d->arch.pirq_irq[i] ) - { - if ( !is_hvm_domain(d) || - d->arch.pirq_emuirq[i] == IRQ_UNBOUND ) - break; - } - if ( i < nr_irqs_gsi ) - return -ENOSPC; + if ( is_free_pirq(d, pirq_info(d, i)) ) + return i; } - return i; + return -ENOSPC; } int map_domain_pirq( @@ -1545,6 +1627,7 @@ int map_domain_pirq( { int ret = 0; int old_irq, old_pirq; + struct pirq *info; struct irq_desc *desc; unsigned long flags; struct msi_desc *msi_desc; @@ -1584,7 +1667,7 @@ int map_domain_pirq( return ret; } - ret = prepare_domain_irq_pirq(d, irq, pirq); + ret = prepare_domain_irq_pirq(d, irq, pirq, &info); if ( ret ) return ret; @@ -1609,20 +1692,20 @@ int map_domain_pirq( dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n", d->domain_id, irq); desc->handler = &pci_msi_type; - set_domain_irq_pirq(d, irq, pirq); + set_domain_irq_pirq(d, irq, info); setup_msi_irq(pdev, msi_desc, irq); spin_unlock_irqrestore(&desc->lock, flags); } else { spin_lock_irqsave(&desc->lock, flags); - set_domain_irq_pirq(d, irq, pirq); + set_domain_irq_pirq(d, irq, info); spin_unlock_irqrestore(&desc->lock, flags); } done: if ( ret ) - cleanup_domain_irq_pirq(d, irq, pirq); + cleanup_domain_irq_pirq(d, irq, info); return ret; } @@ -1633,6 +1716,7 @@ int unmap_domain_pirq(struct domain *d, int pirq) struct irq_desc *desc; int irq, ret = 0; bool_t forced_unbind; + struct pirq *info; struct msi_desc *msi_desc = NULL; if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) @@ -1641,8 +1725,8 @@ int unmap_domain_pirq(struct domain *d, int pirq) ASSERT(spin_is_locked(&pcidevs_lock)); ASSERT(spin_is_locked(&d->event_lock)); - irq = domain_pirq_to_irq(d, pirq); - if ( irq <= 0 ) + info = pirq_info(d, pirq); + if ( !info || (irq = info->arch.irq) <= 0 ) { dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", d->domain_id, pirq); @@ -1650,7 +1734,7 @@ int unmap_domain_pirq(struct domain *d, int pirq) goto done; } - forced_unbind = pirq_guest_force_unbind(d, pirq); + forced_unbind = pirq_guest_force_unbind(d, info); if ( forced_unbind ) dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", d->domain_id, pirq); @@ -1665,10 +1749,10 @@ int unmap_domain_pirq(struct domain *d, int pirq) BUG_ON(irq != domain_pirq_to_irq(d, pirq)); if ( !forced_unbind ) - clear_domain_irq_pirq(d, irq, pirq); + clear_domain_irq_pirq(d, irq, info); else { - d->arch.pirq_irq[pirq] = -irq; + info->arch.irq = -irq; radix_tree_replace_slot( radix_tree_lookup_slot(&d->arch.irq_pirq, irq), radix_tree_int_to_ptr(-pirq)); @@ -1679,7 +1763,7 @@ int unmap_domain_pirq(struct domain *d, int pirq) msi_free_irq(msi_desc); if ( !forced_unbind ) - cleanup_domain_irq_pirq(d, irq, pirq); + cleanup_domain_irq_pirq(d, irq, info); ret = irq_deny_access(d, pirq); if ( ret ) @@ -1701,7 +1785,7 @@ void free_domain_pirqs(struct domain *d) spin_lock(&d->event_lock); for ( i = 0; i < d->nr_pirqs; i++ ) - if ( d->arch.pirq_irq[i] > 0 ) + if ( domain_pirq_to_irq(d, i) > 0 ) unmap_domain_pirq(d, i); spin_unlock(&d->event_lock); @@ -1715,6 +1799,7 @@ static void dump_irqs(unsigned char key) struct irq_cfg *cfg; irq_guest_action_t *action; struct domain *d; + const struct pirq *info; unsigned long flags; printk("Guest interrupt information:\n"); @@ -1749,20 +1834,18 @@ static void dump_irqs(unsigned char key) { d = action->guest[i]; pirq = domain_irq_to_pirq(d, irq); + info = pirq_info(d, pirq); printk("%u:%3d(%c%c%c%c)", d->domain_id, pirq, - (test_bit(d->pirq_to_evtchn[pirq], + (test_bit(info->evtchn, &shared_info(d, evtchn_pending)) ? 'P' : '-'), - (test_bit(d->pirq_to_evtchn[pirq] / - BITS_PER_EVTCHN_WORD(d), + (test_bit(info->evtchn / BITS_PER_EVTCHN_WORD(d), &vcpu_info(d->vcpu[0], evtchn_pending_sel)) ? 'S' : '-'), - (test_bit(d->pirq_to_evtchn[pirq], - &shared_info(d, evtchn_mask)) ? + (test_bit(info->evtchn, &shared_info(d, evtchn_mask)) ? 'M' : '-'), - (test_bit(pirq, d->pirq_mask) ? - 'M' : '-')); + (info->masked ? 'M' : '-')); if ( i != action->nr_guests ) printk(","); } @@ -1869,6 +1952,7 @@ void fixup_irqs(void) int map_domain_emuirq_pirq(struct domain *d, int pirq, int emuirq) { int old_emuirq = IRQ_UNBOUND, old_pirq = IRQ_UNBOUND; + struct pirq *info; ASSERT(spin_is_locked(&d->event_lock)); @@ -1895,6 +1979,10 @@ int map_domain_emuirq_pirq(struct domain *d, int pirq, int emuirq) return 0; } + info = pirq_get_info(d, pirq); + if ( !info ) + return -ENOMEM; + /* do not store emuirq mappings for pt devices */ if ( emuirq != IRQ_PT ) { @@ -1912,10 +2000,11 @@ int map_domain_emuirq_pirq(struct domain *d, int pirq, int emuirq) radix_tree_int_to_ptr(pirq)); break; default: + pirq_cleanup_check(info, d); return err; } } - d->arch.pirq_emuirq[pirq] = emuirq; + info->arch.hvm.emuirq = emuirq; return 0; } @@ -1923,6 +2012,7 @@ int map_domain_emuirq_pirq(struct domain *d, int pirq, int emuirq) int unmap_domain_pirq_emuirq(struct domain *d, int pirq) { int emuirq, ret = 0; + struct pirq *info; if ( !is_hvm_domain(d) ) return -EINVAL; @@ -1941,7 +2031,12 @@ int unmap_domain_pirq_emuirq(struct domain *d, int pirq) goto done; } - d->arch.pirq_emuirq[pirq] = IRQ_UNBOUND; + info = pirq_info(d, pirq); + if ( info ) + { + info->arch.hvm.emuirq = IRQ_UNBOUND; + pirq_cleanup_check(info, d); + } if ( emuirq != IRQ_PT ) radix_tree_delete(&d->arch.hvm_domain.emuirq_pirq, emuirq); @@ -1949,10 +2044,9 @@ int unmap_domain_pirq_emuirq(struct domain *d, int pirq) return ret; } -int hvm_domain_use_pirq(struct domain *d, int pirq) +bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq) { - if ( !is_hvm_domain(d) || pirq < 0 ) - return 0; - - return (domain_pirq_to_emuirq(d, pirq) != IRQ_UNBOUND); + return is_hvm_domain(d) && pirq && + pirq->arch.hvm.emuirq != IRQ_UNBOUND && + pirq->evtchn != 0; } |