Merge branch 'kvm-arm/vgic-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into fixes
This commit is contained in:
commit
7fb476c231
@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
|
|||||||
lr, irq, vgic_cpu->vgic_lr[lr]);
|
lr, irq, vgic_cpu->vgic_lr[lr]);
|
||||||
BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
|
BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
|
||||||
vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
|
vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
|
||||||
|
return true;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to use another LR for this interrupt */
|
/* Try to use another LR for this interrupt */
|
||||||
@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
|
|||||||
vgic_cpu->vgic_irq_lr_map[irq] = lr;
|
vgic_cpu->vgic_irq_lr_map[irq] = lr;
|
||||||
set_bit(lr, vgic_cpu->lr_used);
|
set_bit(lr, vgic_cpu->lr_used);
|
||||||
|
|
||||||
out:
|
|
||||||
if (!vgic_irq_is_edge(vcpu, irq))
|
if (!vgic_irq_is_edge(vcpu, irq))
|
||||||
vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
|
vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
|
||||||
|
|
||||||
@ -1018,21 +1016,6 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
|
kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
|
||||||
|
|
||||||
/*
|
|
||||||
* We do not need to take the distributor lock here, since the only
|
|
||||||
* action we perform is clearing the irq_active_bit for an EOIed
|
|
||||||
* level interrupt. There is a potential race with
|
|
||||||
* the queuing of an interrupt in __kvm_vgic_flush_hwstate(), where we
|
|
||||||
* check if the interrupt is already active. Two possibilities:
|
|
||||||
*
|
|
||||||
* - The queuing is occurring on the same vcpu: cannot happen,
|
|
||||||
* as we're already in the context of this vcpu, and
|
|
||||||
* executing the handler
|
|
||||||
* - The interrupt has been migrated to another vcpu, and we
|
|
||||||
* ignore this interrupt for this run. Big deal. It is still
|
|
||||||
* pending though, and will get considered when this vcpu
|
|
||||||
* exits.
|
|
||||||
*/
|
|
||||||
if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
|
if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
|
||||||
/*
|
/*
|
||||||
* Some level interrupts have been EOIed. Clear their
|
* Some level interrupts have been EOIed. Clear their
|
||||||
@ -1054,6 +1037,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
|
|||||||
} else {
|
} else {
|
||||||
vgic_cpu_irq_clear(vcpu, irq);
|
vgic_cpu_irq_clear(vcpu, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Despite being EOIed, the LR may not have
|
||||||
|
* been marked as empty.
|
||||||
|
*/
|
||||||
|
set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
|
||||||
|
vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,9 +1054,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sync back the VGIC state after a guest run. We do not really touch
|
* Sync back the VGIC state after a guest run. The distributor lock is
|
||||||
* the distributor here (the irq_pending_on_cpu bit is safe to set),
|
* needed so we don't get preempted in the middle of the state processing.
|
||||||
* so there is no need for taking its lock.
|
|
||||||
*/
|
*/
|
||||||
static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
@ -1112,10 +1101,14 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
|
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
|
||||||
|
|
||||||
if (!irqchip_in_kernel(vcpu->kvm))
|
if (!irqchip_in_kernel(vcpu->kvm))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
spin_lock(&dist->lock);
|
||||||
__kvm_vgic_sync_hwstate(vcpu);
|
__kvm_vgic_sync_hwstate(vcpu);
|
||||||
|
spin_unlock(&dist->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
|
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
|
||||||
|
Loading…
Reference in New Issue
Block a user