Subject: [PATCH v2 14/15] KVM: arm64: implement MSI injection in ITS emulation

From: [email-masked] (Andre Przywara)
Date: Sun, 2 Aug 2015 21:20:49 +0100

On 31/07/15 14:22, Eric Auger wrote:

Salut Eric,

> On 07/10/2015 04:21 PM, Andre Przywara wrote:
>> When userland wants to inject a MSI into the guest, we have to use
>> our data structures to find the LPI number and the VCPU to receive
>> the interrupt.
>> Use the wrapper functions to iterate the linked lists and find the
>> proper Interrupt Translation Table Entry. Then set the pending bit
>> in this ITTE to be later picked up by the LR handling code. Kick
>> the VCPU which is meant to handle this interrupt.
>> We provide a VGIC emulation model specific routine for the actual
>> MSI injection. The wrapper functions return an error for models not
>> (yet) implementing MSIs (like the GICv2 emulation).
>> We also provide the handler for the ITS "INT" command, which allows a
>> guest to trigger an MSI via the ITS command queue.
>>
>> Signed-off-by: Andre Przywara <[email-masked]>
>> ---
>>  include/kvm/arm_vgic.h      |  1 +
>>  virt/kvm/arm/its-emul.c     | 65 +++++++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/its-emul.h     |  2 ++
>>  virt/kvm/arm/vgic-v3-emul.c |  1 +
>>  4 files changed, 69 insertions(+)
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index 323c33a..9e1abf9 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -149,6 +149,7 @@ struct vgic_vm_ops {
>>  	int	(*map_resources)(struct kvm *, const struct vgic_params *);
>>  	bool	(*queue_lpis)(struct kvm_vcpu *);
>>  	void	(*unqueue_lpi)(struct kvm_vcpu *, int irq);
>> +	int	(*inject_msi)(struct kvm *, struct kvm_msi *);
>>  };
>>  
>>  struct vgic_io_device {
>> diff --git a/virt/kvm/arm/its-emul.c b/virt/kvm/arm/its-emul.c
>> index 89534c6..a1c12bb 100644
>> --- a/virt/kvm/arm/its-emul.c
>> +++ b/virt/kvm/arm/its-emul.c
>> @@ -323,6 +323,55 @@ static bool handle_mmio_gits_idregs(struct kvm_vcpu *vcpu,
>>  }
>>  
>>  /*
>> + * Translates an incoming MSI request into the redistributor (=VCPU) and
>> + * the associated LPI number. Sets the LPI pending bit and also marks the
>> + * VCPU as having a pending interrupt.
>> + */
>> +int vits_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
>> +{
>> +	struct vgic_dist *dist = &kvm->arch.vgic;
>> +	struct vgic_its *its = &dist->its;
>> +	struct its_itte *itte;
>> +	int cpuid;
>> +	bool inject = false;
>> +	int ret = 0;
>> +
>> +	if (!vgic_has_its(kvm))
>> +		return -ENODEV;
>> +
>> +	if (!(msi->flags & KVM_MSI_VALID_DEVID))
>> +		return -EINVAL;
> I am currently reworking the GSI routing series according to latest
> comments (flag usage on userside and removal of EXTENDED_MSI type on
> kernel side as you suggested). Given the data path,
> 
> kvm_send_userspace_msi (kvm_msi*)
> |_ kvm_set_msi (kvm_kernel_irq_routing_entry *)
> 	|_ kvm->arch.vgic.vm_ops.inject_msi (kvm_msi *)
> 
> the above check is useless I think since in kvm_set_msi I need to
> populate a kvm_msi struct from a kernel routing entry struct. The kernel
> routing entry struct has no info about the validity of devid so I
> systematically sets the flag in kvm_msi.
> 
> I am still dubious about not storing the KVM_MSI_VALID_DEVID info
> somewhere in the kernel routing entry struct.

When I reworked our code to only use a flag and not a separate routing
type I ended up with the flag only guarding assignments, which wouldn't
hurt if done unconditionally (since they are all u32's). So the whole
usage of the flag is somewhat in jeopardy now.
Either the eventual MSI consumer requires a DevID (ITS emulation, which
will not work without it) or the consumer does not care at all and can
totally ignore it (GICv2m). So I think we can always pass on the DevID
field and let the final function decide whether to use it or not. But
somehow this doesn't sound right to me, so maybe I am missing something
here?

Cheers,
Andre.