Re: [PATCH 11/14] arm/arm64: KVM: add virtual GICv3 distributor emulation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2014/6/19 17:45, Andre Przywara wrote:

> With everything separated and prepared, we implement a model of a
> GICv3 distributor and redistributors by using the existing framework
> to provide handler functions for each register group.
> Currently we limit the emulation to a model enforcing a single
> security state, with SRE==1 (forcing system register access) and
> ARE==1 (allowing more than 8 VCPUs).
> We share some of functions provided for GICv2 emulation, but take
> the different ways of addressing (v)CPUs into account.
> Save and restore is currently not implemented.
> 
> Similar to the split-off GICv2 specific code, the new emulation code
> goes into a new file (vgic-v3-emul.c).
> 
> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>


> +
> +/*
> + * triggered by a system register access trap, called from the sysregs
> + * handling code there.
> + * The register contains the upper three affinity levels of the target
> + * processors as well as a bitmask of 16 Aff0 CPUs.
> + * Iterate over all VCPUs to check for matching ones or signal on
> + * all-but-self if the mode bit is set.
> + */
> +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	struct kvm_vcpu *c_vcpu;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	u16 target_cpus;
> +	u64 mpidr, mpidr_h, mpidr_l;
> +	int sgi, mode, c, vcpu_id;
> +	int updated = 0;
> +
> +	vcpu_id = vcpu->vcpu_id;
> +
> +	sgi = (reg >> 24) & 0xf;
> +	mode = (reg >> 40) & 0x1;
> +	target_cpus = reg & 0xffff;
> +	mpidr = ((reg >> 48) & 0xff) << MPIDR_LEVEL_SHIFT(3);
> +	mpidr |= ((reg >> 32) & 0xff) << MPIDR_LEVEL_SHIFT(2);
> +	mpidr |= ((reg >> 16) & 0xff) << MPIDR_LEVEL_SHIFT(1);
> +	mpidr &= ~MPIDR_LEVEL_MASK;
> +
> +	/*
> +	 * We take the dist lock here, because we come from the sysregs
> +	 * code path and not from MMIO (where this is already done)
> +	 */
> +	spin_lock(&dist->lock);
> +	kvm_for_each_vcpu(c, c_vcpu, kvm) {
> +		if (target_cpus == 0)
> +			break;


I can't understand here !
First, when target_cpus == 0, if you want to break and return, it should take
	if (target_cpus == 0)
		break;
code out of the loop, is it?

Second, I think this case (target_cpus == 0) should be not break, when mode == 1, it should
send SGI to all processors in the system, excluding itself.(spec 18)


> +		if (mode && c == vcpu_id)       /* not to myself */
> +			continue;

Is there a mistake? for example: vcpu3 want to send sgi to all *other* vcpu, but , it will send SGI
to all vcpu, *INCLUDE* vcpu3.

> +		if (!mode) {
> +			mpidr_h = kvm_vcpu_get_mpidr(c_vcpu);
> +			mpidr_l = MPIDR_AFFINITY_LEVEL(mpidr_h, 0);
> +			mpidr_h &= ~MPIDR_LEVEL_MASK;
> +			if (mpidr != mpidr_h)
> +				continue;
> +			if (!(target_cpus & BIT(mpidr_l)))
> +				continue;
> +			target_cpus &= ~BIT(mpidr_l);
> +		}
> +		/* Flag the SGI as pending */
> +		vgic_dist_irq_set(c_vcpu, sgi);
> +		updated = 1;
> +		kvm_debug("SGI%d from CPU%d to CPU%d\n", sgi, vcpu_id, c);
> +	}
> +	if (updated)
> +		vgic_update_state(vcpu->kvm);
> +	spin_unlock(&dist->lock);
> +	if (updated)
> +		vgic_kick_vcpus(vcpu->kvm);
> +}


> diff --git a/virt/kvm/arm/vgic.h b/virt/kvm/arm/vgic.h
> index 9078e2a..f24cdd0 100644
> --- a/virt/kvm/arm/vgic.h
> +++ b/virt/kvm/arm/vgic.h
> @@ -34,6 +34,8 @@
>  
>  #define VCPU_NOT_ALLOCATED ((u8)-1)
>  
> +#define VCPU_NOT_ALLOCATED ((u8)-1)


This are two same defines...

> +
>  unsigned long *vgic_bitmap_get_shared_map(struct vgic_bitmap *x);
>  
>  void vgic_update_state(struct kvm *kvm);
> @@ -112,3 +114,4 @@ int vgic_set_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
>  
>  bool vgic_v2_init_emulation_ops(struct kvm *kvm, int type);
> +bool vgic_v3_init_emulation_ops(struct kvm *kvm, int type);
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 4b6c01b..c2fac5d 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2286,6 +2286,9 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
>  	case KVM_DEV_TYPE_ARM_VGIC_V2:
>  		ops = &kvm_arm_vgic_v2_ops;
>  		break;
> +	case KVM_DEV_TYPE_ARM_VGIC_V3:
> +		ops = &kvm_arm_vgic_v3_ops;
> +		break;
>  #endif
>  #ifdef CONFIG_S390
>  	case KVM_DEV_TYPE_FLIC:



_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm




[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux