forked from luck/tmp_suning_uos_patched
KVM: arm/arm64: Introduce an allocator for in-kernel irq lines
Having multiple devices being able to signal the same interrupt line is very confusing and almost certainly guarantees a configuration error. Therefore, introduce a very simple allocator which allows a device to claim an interrupt line from the vgic for a given VM. Signed-off-by: Christoffer Dall <cdall@linaro.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
99a1db7a2c
commit
c6ccd30e0d
|
@ -121,6 +121,9 @@ struct vgic_irq {
|
||||||
u8 source; /* GICv2 SGIs only */
|
u8 source; /* GICv2 SGIs only */
|
||||||
u8 priority;
|
u8 priority;
|
||||||
enum vgic_irq_config config; /* Level or edge */
|
enum vgic_irq_config config; /* Level or edge */
|
||||||
|
|
||||||
|
void *owner; /* Opaque pointer to reserve an interrupt
|
||||||
|
for in-kernel devices. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vgic_register_region;
|
struct vgic_register_region;
|
||||||
|
@ -340,4 +343,6 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
|
||||||
*/
|
*/
|
||||||
int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
|
int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
|
||||||
|
|
||||||
|
int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
|
||||||
|
|
||||||
#endif /* __KVM_ARM_VGIC_H */
|
#endif /* __KVM_ARM_VGIC_H */
|
||||||
|
|
|
@ -434,6 +434,39 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kvm_vgic_set_owner - Set the owner of an interrupt for a VM
|
||||||
|
*
|
||||||
|
* @vcpu: Pointer to the VCPU (used for PPIs)
|
||||||
|
* @intid: The virtual INTID identifying the interrupt (PPI or SPI)
|
||||||
|
* @owner: Opaque pointer to the owner
|
||||||
|
*
|
||||||
|
* Returns 0 if intid is not already used by another in-kernel device and the
|
||||||
|
* owner is set, otherwise returns an error code.
|
||||||
|
*/
|
||||||
|
int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
|
||||||
|
{
|
||||||
|
struct vgic_irq *irq;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!vgic_initialized(vcpu->kvm))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
/* SGIs and LPIs cannot be wired up to any device */
|
||||||
|
if (!irq_is_ppi(intid) && !vgic_valid_spi(vcpu->kvm, intid))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
|
||||||
|
spin_lock(&irq->irq_lock);
|
||||||
|
if (irq->owner && irq->owner != owner)
|
||||||
|
ret = -EEXIST;
|
||||||
|
else
|
||||||
|
irq->owner = owner;
|
||||||
|
spin_unlock(&irq->irq_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vgic_prune_ap_list - Remove non-relevant interrupts from the list
|
* vgic_prune_ap_list - Remove non-relevant interrupts from the list
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user