[PATCH v2] KVM: arm64: ITS: move ITS registration into first VCPU run

Auger Eric eric.auger at redhat.com
Tue Aug 9 00:49:07 PDT 2016


Hi Andre,
On 08/08/2016 17:45, Andre Przywara wrote:
> Currently we register an ITS device upon userland issuing the CTLR_INIT
> ioctl to mark initialization of the ITS as done.
> This deviates from the initialization sequence of the existing GIC
> devices and does not play well with the way QEMU handles things.
> To be more in line with what we are used to, register the ITS(es) just
> before the first VCPU is about to run, so in the map_resources() call.
> This involves iterating through the list of KVM devices and map each
> ITS that we find.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - remove not yet upstreamed locking
> - remove pointless de-registration on rollback
> 
>  virt/kvm/arm/vgic/vgic-its.c | 43 +++++++++++++++++++++++++++++++++----------
>  virt/kvm/arm/vgic/vgic-v3.c  |  8 ++++++++
>  virt/kvm/arm/vgic/vgic.h     |  6 ++++++
>  3 files changed, 47 insertions(+), 10 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 07411cf..7180994 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1288,13 +1288,13 @@ void vgic_enable_lpis(struct kvm_vcpu *vcpu)
>  		its_sync_lpi_pending_table(vcpu);
>  }
>  
> -static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
> +static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
>  {
>  	struct vgic_io_device *iodev = &its->iodev;
>  	int ret;
>  
> -	if (its->initialized)
> -		return 0;
> +	if (!its->initialized)
> +		return -EBUSY;
>  
>  	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
>  		return -ENXIO;
> @@ -1311,9 +1311,6 @@ static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
>  				      KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
>  	mutex_unlock(&kvm->slots_lock);
>  
> -	if (!ret)
> -		its->initialized = true;
> -
>  	return ret;
>  }
>  
> @@ -1435,9 +1432,6 @@ static int vgic_its_set_attr(struct kvm_device *dev,
>  		if (type != KVM_VGIC_ITS_ADDR_TYPE)
>  			return -ENODEV;
>  
> -		if (its->initialized)
> -			return -EBUSY;
> -
>  		if (copy_from_user(&addr, uaddr, sizeof(addr)))
>  			return -EFAULT;
>  
> @@ -1453,7 +1447,9 @@ static int vgic_its_set_attr(struct kvm_device *dev,
>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
>  		switch (attr->attr) {
>  		case KVM_DEV_ARM_VGIC_CTRL_INIT:
> -			return vgic_its_init_its(dev->kvm, its);
> +			its->initialized = true;
> +
> +			return 0;
>  		}
>  		break;
>  	}
> @@ -1498,3 +1494,30 @@ int kvm_vgic_register_its_device(void)
>  	return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
>  				       KVM_DEV_TYPE_ARM_VGIC_ITS);
>  }
> +
> +/*
> + * Registers all ITSes with the kvm_io_bus framework.
> + * To follow the existing VGIC initialization sequence, this has to be
> + * done as late as possible, just before the first VCPU runs.
> + */
> +int vgic_register_its_iodevs(struct kvm *kvm)
> +{
> +	struct kvm_device *dev;
> +	int ret = 0;
> +
> +	list_for_each_entry(dev, &kvm->devices, vm_node) {
> +		if (dev->ops != &kvm_arm_vgic_its_ops)
> +			continue;
> +
> +		ret = vgic_register_its_iodev(kvm, dev->private);
> +		if (ret)
> +			return ret;
> +		/*
> +		 * We don't need to care about tearing down previously
> +		 * registered ITSes, as the kvm_io_bus framework removes
> +		 * them for us if the VM gets destroyed.
> +		 */
> +	}
> +
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 0506543..9f0dae3 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -289,6 +289,14 @@ int vgic_v3_map_resources(struct kvm *kvm)
>  		goto out;
>  	}
>  
> +	if (vgic_has_its(kvm)) {
> +		ret = vgic_register_its_iodevs(kvm);
> +		if (ret) {
> +			kvm_err("Unable to register VGIC ITS MMIO regions\n");
> +			goto out;
> +		}
> +	}
> +
>  	dist->ready = true;
>  
>  out:
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 1d8e21d..6c4625c 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -84,6 +84,7 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu);
>  int vgic_v3_probe(const struct gic_kvm_info *info);
>  int vgic_v3_map_resources(struct kvm *kvm);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
> +int vgic_register_its_iodevs(struct kvm *kvm);
>  bool vgic_has_its(struct kvm *kvm);
>  int kvm_vgic_register_its_device(void);
>  void vgic_enable_lpis(struct kvm_vcpu *vcpu);
> @@ -140,6 +141,11 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  	return -ENODEV;
>  }
>  
> +static inline int vgic_register_its_iodevs(struct kvm *kvm)
> +{
> +	return -ENODEV;
> +}
> +
>  static inline bool vgic_has_its(struct kvm *kvm)
>  {
>  	return false;
> 

Reviewed-by: Eric Auger <eric.auger at redhat.com>
Tested-by: Eric Auger <eric.auger at redhat.com>

Tested on Cavium with QEMU (with accordingly modified init sequence)

Cheers

Eric



More information about the linux-arm-kernel mailing list