Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d60eacb0 authored by Will Deacon's avatar Will Deacon Committed by Paolo Bonzini
Browse files

KVM: device: add simple registration mechanism for kvm_device_ops



kvm_ioctl_create_device currently has knowledge of all the device types
and their associated ops. This is fairly inflexible when adding support
for new in-kernel device emulations, so move what we currently have out
into a table, which can support dynamic registration of ops by new
drivers for virtual hardware.

Cc: Alex Williamson <Alex.Williamson@redhat.com>
Cc: Alex Graf <agraf@suse.de>
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 184564ef
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -1064,6 +1064,7 @@ struct kvm_device_ops {
void kvm_device_get(struct kvm_device *dev);
void kvm_device_get(struct kvm_device *dev);
void kvm_device_put(struct kvm_device *dev);
void kvm_device_put(struct kvm_device *dev);
struct kvm_device *kvm_device_from_filp(struct file *filp);
struct kvm_device *kvm_device_from_filp(struct file *filp);
int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type);


extern struct kvm_device_ops kvm_mpic_ops;
extern struct kvm_device_ops kvm_mpic_ops;
extern struct kvm_device_ops kvm_xics_ops;
extern struct kvm_device_ops kvm_xics_ops;
+16 −6
Original line number Original line Diff line number Diff line
@@ -943,15 +943,25 @@ struct kvm_device_attr {
	__u64	addr;		/* userspace address of attr data */
	__u64	addr;		/* userspace address of attr data */
};
};


#define KVM_DEV_TYPE_FSL_MPIC_20	1
#define KVM_DEV_TYPE_FSL_MPIC_42	2
#define KVM_DEV_TYPE_XICS		3
#define KVM_DEV_TYPE_VFIO		4
#define  KVM_DEV_VFIO_GROUP			1
#define  KVM_DEV_VFIO_GROUP			1
#define   KVM_DEV_VFIO_GROUP_ADD			1
#define   KVM_DEV_VFIO_GROUP_ADD			1
#define   KVM_DEV_VFIO_GROUP_DEL			2
#define   KVM_DEV_VFIO_GROUP_DEL			2
#define KVM_DEV_TYPE_ARM_VGIC_V2	5

#define KVM_DEV_TYPE_FLIC		6
enum kvm_device_type {
	KVM_DEV_TYPE_FSL_MPIC_20	= 1,
#define KVM_DEV_TYPE_FSL_MPIC_20	KVM_DEV_TYPE_FSL_MPIC_20
	KVM_DEV_TYPE_FSL_MPIC_42,
#define KVM_DEV_TYPE_FSL_MPIC_42	KVM_DEV_TYPE_FSL_MPIC_42
	KVM_DEV_TYPE_XICS,
#define KVM_DEV_TYPE_XICS		KVM_DEV_TYPE_XICS
	KVM_DEV_TYPE_VFIO,
#define KVM_DEV_TYPE_VFIO		KVM_DEV_TYPE_VFIO
	KVM_DEV_TYPE_ARM_VGIC_V2,
#define KVM_DEV_TYPE_ARM_VGIC_V2	KVM_DEV_TYPE_ARM_VGIC_V2
	KVM_DEV_TYPE_FLIC,
#define KVM_DEV_TYPE_FLIC		KVM_DEV_TYPE_FLIC
	KVM_DEV_TYPE_MAX,
};


/*
/*
 * ioctls for VM fds
 * ioctls for VM fds
+38 −27
Original line number Original line Diff line number Diff line
@@ -2272,45 +2272,56 @@ struct kvm_device *kvm_device_from_filp(struct file *filp)
	return filp->private_data;
	return filp->private_data;
}
}


static int kvm_ioctl_create_device(struct kvm *kvm,
static struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = {
				   struct kvm_create_device *cd)
{
	struct kvm_device_ops *ops = NULL;
	struct kvm_device *dev;
	bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
	int ret;

	switch (cd->type) {
#ifdef CONFIG_KVM_MPIC
#ifdef CONFIG_KVM_MPIC
	case KVM_DEV_TYPE_FSL_MPIC_20:
	[KVM_DEV_TYPE_FSL_MPIC_20]	= &kvm_mpic_ops,
	case KVM_DEV_TYPE_FSL_MPIC_42:
	[KVM_DEV_TYPE_FSL_MPIC_42]	= &kvm_mpic_ops,
		ops = &kvm_mpic_ops;
		break;
#endif
#endif

#ifdef CONFIG_KVM_XICS
#ifdef CONFIG_KVM_XICS
	case KVM_DEV_TYPE_XICS:
	[KVM_DEV_TYPE_XICS]		= &kvm_xics_ops,
		ops = &kvm_xics_ops;
		break;
#endif
#endif

#ifdef CONFIG_KVM_VFIO
#ifdef CONFIG_KVM_VFIO
	case KVM_DEV_TYPE_VFIO:
	[KVM_DEV_TYPE_VFIO]		= &kvm_vfio_ops,
		ops = &kvm_vfio_ops;
		break;
#endif
#endif

#ifdef CONFIG_KVM_ARM_VGIC
#ifdef CONFIG_KVM_ARM_VGIC
	case KVM_DEV_TYPE_ARM_VGIC_V2:
	[KVM_DEV_TYPE_ARM_VGIC_V2]	= &kvm_arm_vgic_v2_ops,
		ops = &kvm_arm_vgic_v2_ops;
		break;
#endif
#endif

#ifdef CONFIG_S390
#ifdef CONFIG_S390
	case KVM_DEV_TYPE_FLIC:
	[KVM_DEV_TYPE_FLIC]		= &kvm_flic_ops,
		ops = &kvm_flic_ops;
		break;
#endif
#endif
	default:
};
		return -ENODEV;

int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type)
{
	if (type >= ARRAY_SIZE(kvm_device_ops_table))
		return -ENOSPC;

	if (kvm_device_ops_table[type] != NULL)
		return -EEXIST;

	kvm_device_ops_table[type] = ops;
	return 0;
}
}


static int kvm_ioctl_create_device(struct kvm *kvm,
				   struct kvm_create_device *cd)
{
	struct kvm_device_ops *ops = NULL;
	struct kvm_device *dev;
	bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
	int ret;

	if (cd->type >= ARRAY_SIZE(kvm_device_ops_table))
		return -ENODEV;

	ops = kvm_device_ops_table[cd->type];
	if (ops == NULL)
		return -ENODEV;

	if (test)
	if (test)
		return 0;
		return 0;