Commit 619064af authored by Marc Zyngier's avatar Marc Zyngier
Browse files

KVM: arm64: vgic: Tidy-up calls to vgic_{get,set}_common_attr()



The userspace accessors have an early call to vgic_{get,set}_common_attr()
that makes the code hard to follow. Move it to the default: clause of
the decoding switch statement, which results in a nice cleanup.

This requires us to move the handling of the pending table into the
common handling, even if it is strictly a GICv3 feature (it has the
benefit of keeping the whole control group handling in the same
function).

Also cleanup vgic_v3_{get,set}_attr() while we're at it, deduplicating
the calls to vgic_v3_attr_regs_access().

Suggested-by: default avatarReiji Watanabe <reijiw@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 4b85080f
Loading
Loading
Loading
Loading
+26 −52
Original line number Diff line number Diff line
@@ -246,6 +246,24 @@ static int vgic_set_common_attr(struct kvm_device *dev,
			r = vgic_init(dev->kvm);
			mutex_unlock(&dev->kvm->lock);
			return r;
		case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
			/*
			 * OK, this one isn't common at all, but we
			 * want to handle all control group attributes
			 * in a single place.
			 */
			if (vgic_check_type(dev->kvm, KVM_DEV_TYPE_ARM_VGIC_V3))
				return -ENXIO;
			mutex_lock(&dev->kvm->lock);

			if (!lock_all_vcpus(dev->kvm)) {
				mutex_unlock(&dev->kvm->lock);
				return -EBUSY;
			}
			r = vgic_v3_save_pending_tables(dev->kvm);
			unlock_all_vcpus(dev->kvm);
			mutex_unlock(&dev->kvm->lock);
			return r;
		}
		break;
	}
@@ -427,37 +445,25 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
static int vgic_v2_set_attr(struct kvm_device *dev,
			    struct kvm_device_attr *attr)
{
	int ret;

	ret = vgic_set_common_attr(dev, attr);
	if (ret != -ENXIO)
		return ret;

	switch (attr->group) {
	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
		return vgic_v2_attr_regs_access(dev, attr, true);
	default:
		return vgic_set_common_attr(dev, attr);
	}

	return -ENXIO;
}

static int vgic_v2_get_attr(struct kvm_device *dev,
			    struct kvm_device_attr *attr)
{
	int ret;

	ret = vgic_get_common_attr(dev, attr);
	if (ret != -ENXIO)
		return ret;

	switch (attr->group) {
	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
		return vgic_v2_attr_regs_access(dev, attr, false);
	default:
		return vgic_get_common_attr(dev, attr);
	}

	return -ENXIO;
}

static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -618,61 +624,29 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
static int vgic_v3_set_attr(struct kvm_device *dev,
			    struct kvm_device_attr *attr)
{
	int ret;

	ret = vgic_set_common_attr(dev, attr);
	if (ret != -ENXIO)
		return ret;

	switch (attr->group) {
	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
	case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
		return vgic_v3_attr_regs_access(dev, attr, true);
	case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
		return vgic_v3_attr_regs_access(dev, attr, true);
	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
		return vgic_v3_attr_regs_access(dev, attr, true);
	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
		int ret;

		switch (attr->attr) {
		case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
			mutex_lock(&dev->kvm->lock);

			if (!lock_all_vcpus(dev->kvm)) {
				mutex_unlock(&dev->kvm->lock);
				return -EBUSY;
			}
			ret = vgic_v3_save_pending_tables(dev->kvm);
			unlock_all_vcpus(dev->kvm);
			mutex_unlock(&dev->kvm->lock);
			return ret;
		}
		break;
	}
	default:
		return vgic_set_common_attr(dev, attr);
	}
	return -ENXIO;
}

static int vgic_v3_get_attr(struct kvm_device *dev,
			    struct kvm_device_attr *attr)
{
	int ret;

	ret = vgic_get_common_attr(dev, attr);
	if (ret != -ENXIO)
		return ret;

	switch (attr->group) {
	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
	case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
		return vgic_v3_attr_regs_access(dev, attr, false);
	case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
		return vgic_v3_attr_regs_access(dev, attr, false);
	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
		return vgic_v3_attr_regs_access(dev, attr, false);
	default:
		return vgic_get_common_attr(dev, attr);
	}
	return -ENXIO;
}

static int vgic_v3_has_attr(struct kvm_device *dev,