This is a call to forget to check NULL if we
decide to use the function in the future.
Also, I would like a comment on top of irq_to_pending stating this can
return NULL as you change the semantic of the function.
Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
---
xen/arch/arm/gic.c | 37 ++++++++++++++++++++++++++++++++-----
xen/arch/arm/vgic.c | 6 ++++++
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index dcb1783..62ae3b8 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -408,9 +408,15 @@ void gic_remove_from_queues(struct vcpu *v,
unsigned int virtual_irq)
spin_lock_irqsave(&v->arch.vgic.lock, flags);
p = irq_to_pending(v, virtual_irq);
-
- if ( !list_empty(&p->lr_queue) )
- list_del_init(&p->lr_queue);
+ /*
+ * If an LPIs has been removed meanwhile, it has been cleaned up
+ * already, so nothing to remove here.
+ */
+ if ( p )
+ {
+ if ( !list_empty(&p->lr_queue) )
+ list_del_init(&p->lr_queue);
+ }
This could be simplified with:
if ( p && !list_empty(&p->lr_queue) )
list_del_init(...);
Also, you probably want a likely(p).
spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
}
@@ -418,6 +424,10 @@ void gic_raise_inflight_irq(struct vcpu *v,
unsigned int virtual_irq)
{
struct pending_irq *n = irq_to_pending(v, virtual_irq);
+ /* If an LPI has been removed meanwhile, there is nothing left to
raise. */
+ if ( !n )
if ( unlikely(!n) )
+ return;
+
ASSERT(spin_is_locked(&v->arch.vgic.lock));
if ( list_empty(&n->lr_queue) )
@@ -437,6 +447,11 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned
int virtual_irq,
{
int i;
unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
+ struct pending_irq *p = irq_to_pending(v, virtual_irq);
+
+ if ( !p )
if ( unlikely(!p) )
+ /* An unmapped LPI does not need to be raised. */
+ return;
Please move this check after the ASSERT to keep the check on all the paths.
ASSERT(spin_is_locked(&v->arch.vgic.lock));
@@ -445,12 +460,12 @@ void gic_raise_guest_irq(struct vcpu *v,
unsigned int virtual_irq,
i = find_first_zero_bit(&this_cpu(lr_mask), nr_lrs);
if (i < nr_lrs) {
set_bit(i, &this_cpu(lr_mask));
- gic_set_lr(i, irq_to_pending(v, virtual_irq),
GICH_LR_PENDING);
+ gic_set_lr(i, p, GICH_LR_PENDING);
return;
}
}
- gic_add_to_lr_pending(v, irq_to_pending(v, virtual_irq));
+ gic_add_to_lr_pending(v, p);
}
static void gic_update_one_lr(struct vcpu *v, int i)
@@ -464,7 +479,19 @@ static void gic_update_one_lr(struct vcpu *v, int i)
gic_hw_ops->read_lr(i, &lr_val);
irq = lr_val.virq;
+
4th time I am saying this.... Spurious line.
p = irq_to_pending(v, irq);
+ /* An LPI might have been unmapped, in which case we just clean
up here. */
+ if ( !p )
unlikely(!p)
+ {
+ ASSERT(is_lpi(irq));
+
+ gic_hw_ops->clear_lr(i);
+ clear_bit(i, &this_cpu(lr_mask));
+
+ return;
+ }
+
if ( lr_val.state & GICH_LR_ACTIVE )
{
set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index c953f13..b9fc837 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -473,6 +473,12 @@ void vgic_vcpu_inject_irq(struct vcpu *v,
unsigned int virq)
spin_lock_irqsave(&v->arch.vgic.lock, flags);
n = irq_to_pending(v, virq);
+ /* If an LPI has been removed, there is nothing to inject here. */
+ if ( !n )
unlikely(...)
+ {
+ spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+ return;
+ }
priority = vgic_get_virq_priority(v, virq);
Cheers,