269 lines
8.0 KiB
Diff
269 lines
8.0 KiB
Diff
# HG changeset patch
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
# Date 1222349872 -3600
|
|
# Node ID e1507b441be45d6d1cac25a196b53beff857a083
|
|
# Parent ddf62f69611127319e3c756b9fbc82e29f59ef36
|
|
x86: Clean up and fix 18539:31f09a5e24cf8
|
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
--- a/xen/arch/ia64/xen/irq.c
|
|
+++ b/xen/arch/ia64/xen/irq.c
|
|
@@ -459,12 +459,12 @@ int pirq_guest_bind(struct vcpu *v, int
|
|
return rc;
|
|
}
|
|
|
|
-int pirq_guest_unbind(struct domain *d, int irq)
|
|
+void pirq_guest_unbind(struct domain *d, int irq)
|
|
{
|
|
irq_desc_t *desc = &irq_desc[irq];
|
|
irq_guest_action_t *action;
|
|
unsigned long flags;
|
|
- int i, rc = 0;
|
|
+ int i;
|
|
|
|
spin_lock_irqsave(&desc->lock, flags);
|
|
|
|
@@ -472,11 +472,7 @@ int pirq_guest_unbind(struct domain *d,
|
|
|
|
for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
|
|
continue;
|
|
- if ( i == action->nr_guests )
|
|
- {
|
|
- rc = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
+ BUG_ON(i == action->nr_guests);
|
|
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
|
|
action->nr_guests--;
|
|
|
|
@@ -496,9 +492,7 @@ int pirq_guest_unbind(struct domain *d,
|
|
desc->handler->shutdown(irq);
|
|
}
|
|
|
|
- out:
|
|
spin_unlock_irqrestore(&desc->lock, flags);
|
|
- return rc;
|
|
}
|
|
|
|
void
|
|
--- a/xen/arch/x86/irq.c
|
|
+++ b/xen/arch/x86/irq.c
|
|
@@ -508,14 +508,14 @@ int pirq_guest_bind(struct vcpu *v, int
|
|
unsigned int vector;
|
|
irq_desc_t *desc;
|
|
irq_guest_action_t *action;
|
|
- unsigned long flags;
|
|
int rc = 0;
|
|
cpumask_t cpumask = CPU_MASK_NONE;
|
|
|
|
WARN_ON(!spin_is_locked(&v->domain->evtchn_lock));
|
|
+ BUG_ON(!local_irq_is_enabled());
|
|
|
|
retry:
|
|
- desc = domain_spin_lock_irq_desc(v->domain, irq, &flags);
|
|
+ desc = domain_spin_lock_irq_desc(v->domain, irq, NULL);
|
|
if ( desc == NULL )
|
|
return -EINVAL;
|
|
|
|
@@ -575,7 +575,7 @@ int pirq_guest_bind(struct vcpu *v, int
|
|
*/
|
|
ASSERT(action->ack_type == ACKTYPE_EOI);
|
|
ASSERT(desc->status & IRQ_DISABLED);
|
|
- spin_unlock_irqrestore(&desc->lock, flags);
|
|
+ spin_unlock_irq(&desc->lock);
|
|
cpu_relax();
|
|
goto retry;
|
|
}
|
|
@@ -591,43 +591,25 @@ int pirq_guest_bind(struct vcpu *v, int
|
|
action->guest[action->nr_guests++] = v->domain;
|
|
|
|
out:
|
|
- spin_unlock_irqrestore(&desc->lock, flags);
|
|
+ spin_unlock_irq(&desc->lock);
|
|
return rc;
|
|
}
|
|
|
|
-int pirq_guest_unbind(struct domain *d, int irq)
|
|
+static void __pirq_guest_unbind(struct domain *d, int irq, irq_desc_t *desc)
|
|
{
|
|
- int vector;
|
|
- irq_desc_t *desc;
|
|
+ unsigned int vector;
|
|
irq_guest_action_t *action;
|
|
cpumask_t cpu_eoi_map;
|
|
- unsigned long flags;
|
|
- int i, rc = 0;
|
|
+ int i;
|
|
|
|
- WARN_ON(!spin_is_locked(&d->evtchn_lock));
|
|
-
|
|
- desc = domain_spin_lock_irq_desc(d, irq, &flags);
|
|
- if ( unlikely(desc == NULL) )
|
|
- {
|
|
- if ( !msi_enable || (vector = -domain_irq_to_vector(d, irq)) == 0 )
|
|
- return -EINVAL;
|
|
- BUG_ON(vector <= 0);
|
|
- desc = &irq_desc[vector];
|
|
- spin_lock_irqsave(&desc->lock, flags);
|
|
- d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
|
|
- goto out;
|
|
- }
|
|
+ BUG_ON(!(desc->status & IRQ_GUEST));
|
|
|
|
action = (irq_guest_action_t *)desc->action;
|
|
vector = desc - irq_desc;
|
|
|
|
for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
|
|
continue;
|
|
- if ( i == action->nr_guests )
|
|
- {
|
|
- rc = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
+ BUG_ON(i == action->nr_guests);
|
|
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
|
|
action->nr_guests--;
|
|
|
|
@@ -645,9 +627,9 @@ int pirq_guest_unbind(struct domain *d,
|
|
(action->nr_guests != 0) )
|
|
{
|
|
cpu_eoi_map = action->cpu_eoi_map;
|
|
- spin_unlock_irqrestore(&desc->lock, flags);
|
|
+ spin_unlock_irq(&desc->lock);
|
|
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
|
|
- spin_lock_irqsave(&desc->lock, flags);
|
|
+ spin_lock_irq(&desc->lock);
|
|
}
|
|
break;
|
|
}
|
|
@@ -659,7 +641,7 @@ int pirq_guest_unbind(struct domain *d,
|
|
BUG_ON(test_bit(irq, d->pirq_mask));
|
|
|
|
if ( action->nr_guests != 0 )
|
|
- goto out;
|
|
+ return;
|
|
|
|
BUG_ON(action->in_flight != 0);
|
|
|
|
@@ -679,9 +661,9 @@ int pirq_guest_unbind(struct domain *d,
|
|
if ( !cpus_empty(cpu_eoi_map) )
|
|
{
|
|
BUG_ON(action->ack_type != ACKTYPE_EOI);
|
|
- spin_unlock_irqrestore(&desc->lock, flags);
|
|
+ spin_unlock_irq(&desc->lock);
|
|
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 1);
|
|
- spin_lock_irqsave(&desc->lock, flags);
|
|
+ spin_lock_irq(&desc->lock);
|
|
}
|
|
|
|
BUG_ON(!cpus_empty(action->cpu_eoi_map));
|
|
@@ -692,10 +674,63 @@ int pirq_guest_unbind(struct domain *d,
|
|
desc->status &= ~IRQ_INPROGRESS;
|
|
kill_timer(&irq_guest_eoi_timer[vector]);
|
|
desc->handler->shutdown(vector);
|
|
+}
|
|
+
|
|
+void pirq_guest_unbind(struct domain *d, int irq)
|
|
+{
|
|
+ irq_desc_t *desc;
|
|
+ int vector;
|
|
+
|
|
+ WARN_ON(!spin_is_locked(&d->evtchn_lock));
|
|
+
|
|
+ BUG_ON(!local_irq_is_enabled());
|
|
+ desc = domain_spin_lock_irq_desc(d, irq, NULL);
|
|
+
|
|
+ if ( desc == NULL )
|
|
+ {
|
|
+ if ( !msi_enable )
|
|
+ return;
|
|
+ vector = -domain_irq_to_vector(d, irq);
|
|
+ BUG_ON(vector <= 0);
|
|
+ desc = &irq_desc[vector];
|
|
+ spin_lock_irq(&desc->lock);
|
|
+ d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ __pirq_guest_unbind(d, irq, desc);
|
|
+ }
|
|
+
|
|
+ spin_unlock_irq(&desc->lock);
|
|
+}
|
|
+
|
|
+int pirq_guest_force_unbind(struct domain *d, int irq)
|
|
+{
|
|
+ irq_desc_t *desc;
|
|
+ irq_guest_action_t *action;
|
|
+ int i, bound = 0;
|
|
+
|
|
+ WARN_ON(!spin_is_locked(&d->evtchn_lock));
|
|
+
|
|
+ BUG_ON(!local_irq_is_enabled());
|
|
+ desc = domain_spin_lock_irq_desc(d, irq, NULL);
|
|
+ BUG_ON(desc == NULL);
|
|
+
|
|
+ if ( !(desc->status & IRQ_GUEST) )
|
|
+ goto out;
|
|
+
|
|
+ action = (irq_guest_action_t *)desc->action;
|
|
+ for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
|
|
+ continue;
|
|
+ if ( i == action->nr_guests )
|
|
+ goto out;
|
|
+
|
|
+ bound = 1;
|
|
+ __pirq_guest_unbind(d, irq, desc);
|
|
|
|
out:
|
|
- spin_unlock_irqrestore(&desc->lock, flags);
|
|
- return rc;
|
|
+ spin_unlock_irq(&desc->lock);
|
|
+ return bound;
|
|
}
|
|
|
|
extern void dump_ioapic_irq_info(void);
|
|
--- a/xen/arch/x86/physdev.c
|
|
+++ b/xen/arch/x86/physdev.c
|
|
@@ -147,7 +147,7 @@ static int unmap_domain_pirq(struct doma
|
|
{
|
|
unsigned long flags;
|
|
irq_desc_t *desc;
|
|
- bool_t forced_unbind = (pirq_guest_unbind(d, pirq) == 0);
|
|
+ bool_t forced_unbind = pirq_guest_force_unbind(d, pirq);
|
|
|
|
if ( forced_unbind )
|
|
dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
|
|
--- a/xen/common/event_channel.c
|
|
+++ b/xen/common/event_channel.c
|
|
@@ -376,8 +376,7 @@ static long __evtchn_close(struct domain
|
|
break;
|
|
|
|
case ECS_PIRQ:
|
|
- if ( pirq_guest_unbind(d1, chn1->u.pirq) != 0 )
|
|
- BUG();
|
|
+ pirq_guest_unbind(d1, chn1->u.pirq);
|
|
d1->pirq_to_evtchn[chn1->u.pirq] = 0;
|
|
break;
|
|
|
|
--- a/xen/include/asm-x86/irq.h
|
|
+++ b/xen/include/asm-x86/irq.h
|
|
@@ -55,4 +55,6 @@ int pirq_shared(struct domain *d , int i
|
|
#define domain_irq_to_vector(d, irq) (msi_enable ? (d)->arch.pirq_vector[irq] : irq_to_vector(irq))
|
|
#define domain_vector_to_irq(d, vec) (msi_enable ? (d)->arch.vector_pirq[vec] : vector_to_irq(vec))
|
|
|
|
+int pirq_guest_force_unbind(struct domain *d, int irq);
|
|
+
|
|
#endif /* _ASM_HW_IRQ_H */
|
|
--- a/xen/include/xen/irq.h
|
|
+++ b/xen/include/xen/irq.h
|
|
@@ -77,7 +77,7 @@ struct vcpu;
|
|
extern int pirq_guest_eoi(struct domain *d, int irq);
|
|
extern int pirq_guest_unmask(struct domain *d);
|
|
extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share);
|
|
-extern int pirq_guest_unbind(struct domain *d, int irq);
|
|
+extern void pirq_guest_unbind(struct domain *d, int irq);
|
|
|
|
static inline void set_native_irq_info(int irq, cpumask_t mask)
|
|
{
|