[PATCH v7 17/17] KVM: arm64: enable ITS emulation as a virtual MSI controller

Auger Eric eric.auger at redhat.com
Wed Jun 29 09:34:59 PDT 2016


Hi Andre,

On 28/06/2016 14:32, Andre Przywara wrote:
> Now that all ITS emulation functionality is in place, we advertise
> MSI functionality to userland and also the ITS device to the guest - if
> userland has configured that.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  Documentation/virtual/kvm/api.txt |  2 +-
>  arch/arm64/kvm/Kconfig            |  1 +
>  arch/arm64/kvm/reset.c            | 10 ++++++++++
>  include/kvm/vgic/vgic.h           |  5 +++++
>  virt/kvm/arm/vgic.c               |  5 +++++
>  virt/kvm/arm/vgic/vgic-init.c     |  3 +++
>  virt/kvm/arm/vgic/vgic-mmio-v3.c  | 14 ++++++++++----
>  virt/kvm/arm/vgic/vgic.c          |  8 ++++++++
>  8 files changed, 43 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index bf76639..f60b137 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2156,7 +2156,7 @@ after pausing the vcpu, but before it is resumed.
>  4.71 KVM_SIGNAL_MSI
>  
>  Capability: KVM_CAP_SIGNAL_MSI
> -Architectures: x86
> +Architectures: x86 arm64
>  Type: vm ioctl
>  Parameters: struct kvm_msi (in)
>  Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> index c4f26ef..446686a 100644
> --- a/arch/arm64/kvm/Kconfig
> +++ b/arch/arm64/kvm/Kconfig
> @@ -36,6 +36,7 @@ config KVM
>  	select HAVE_KVM_IRQFD
>  	select KVM_ARM_VGIC_V3-ENODEV
>  	select KVM_ARM_PMU if HW_PERF_EVENTS
> +	select HAVE_KVM_MSI
don't you want to enable the modality only with new VGIC? If I am not
wrong an attempt to inject an msi from userspace with old vgic will
return  -ENODEV.

Thanks

Eric
>  	---help---
>  	  Support hosting virtualized guest machines.
>  	  We don't support KVM with 16K page tables yet, due to the multiple
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 6ec9dfe..409d188 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -86,6 +86,16 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
>  	case KVM_CAP_VCPU_ATTRIBUTES:
>  		r = 1;
>  		break;
> +	case KVM_CAP_MSI_DEVID:
> +#ifdef CONFIG_KVM_NEW_VGIC
> +		if (!kvm)
> +			r = -EINVAL;
> +		else
> +			r = kvm->arch.vgic.msis_require_devid;
> +#else
> +		r = -EINVAL;
> +#endif
> +		break;
>  	default:
>  		r = 0;
>  	}
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2b00fb3..d7a6da3 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -154,6 +154,9 @@ struct vgic_dist {
>  	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
>  	u32			vgic_model;
>  
> +	/* Do injected MSIs require an additional device ID? */
> +	bool			msis_require_devid;
> +
>  	int			nr_spis;
>  
>  	/* TODO: Consider moving to global state */
> @@ -298,4 +301,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
>  	return kvm_vgic_global_state.max_gic_vcpus;
>  }
>  
> +int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
> +
>  #endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index c3bfbb9..26db30a 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -2438,3 +2438,8 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
>  {
>  	return 0;
>  }
> +
> +int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
> +{
> +	return -ENODEV;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 535e713..01a60dc 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -258,6 +258,9 @@ int vgic_init(struct kvm *kvm)
>  	if (ret)
>  		goto out;
>  
> +	if (vgic_has_its(kvm))
> +		dist->msis_require_devid = true;
> +
>  	kvm_for_each_vcpu(i, vcpu, kvm)
>  		kvm_vgic_vcpu_init(vcpu);
>  
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index dfa79c7..26f4779 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -66,7 +66,12 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
>  	case GICD_TYPER:
>  		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>  		value = (value >> 5) - 1;
> -		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
> +		if (vgic_has_its(vcpu->kvm)) {
> +			value |= (INTERRUPT_ID_BITS_ITS - 1) << 19;
> +			value |= GICD_TYPER_LPIS;
> +		} else {
> +			value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
> +		}
>  		break;
>  	case GICD_IIDR:
>  		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> @@ -161,9 +166,8 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,
>  
>  	vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS;
>  
> -	if (!was_enabled && vgic_cpu->lpis_enabled) {
> -		/* Eventually do something */
> -	}
> +	if (!was_enabled && vgic_cpu->lpis_enabled)
> +		vgic_enable_lpis(vcpu);
>  }
>  
>  static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
> @@ -177,6 +181,8 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
>  	value |= ((target_vcpu_id & 0xffff) << 8);
>  	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
>  		value |= GICR_TYPER_LAST;
> +	if (vgic_has_its(vcpu->kvm))
> +		value |= GICR_TYPER_PLPIS;
>  
>  	return extract_bytes(value, addr & 7, len);
>  }
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 8111d49..f93f8dd 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -682,3 +682,11 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
>  
>  	return map_is_active;
>  }
> +
> +int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
> +{
> +	if (vgic_has_its(kvm))
> +		return vits_inject_msi(kvm, msi);
> +	else
> +		return -ENODEV;
> +}
> 



More information about the linux-arm-kernel mailing list