diff options
author | Will Deacon <will.deacon@arm.com> | 2014-09-02 05:27:33 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-09-17 07:10:08 -0400 |
commit | d60eacb07053142bfb9b41582074a89a790a9d46 (patch) | |
tree | de5bddd60b8cf78dbe0c7eabbe4d46ae656713a7 | |
parent | 184564efae4d775225c8fe3b762a56956fb1f827 (diff) |
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: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 22 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 65 |
3 files changed, 55 insertions, 33 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index e098dce179df..b6e954742951 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1064,6 +1064,7 @@ struct kvm_device_ops { | |||
1064 | void kvm_device_get(struct kvm_device *dev); | 1064 | void kvm_device_get(struct kvm_device *dev); |
1065 | void kvm_device_put(struct kvm_device *dev); | 1065 | void kvm_device_put(struct kvm_device *dev); |
1066 | struct kvm_device *kvm_device_from_filp(struct file *filp); | 1066 | struct kvm_device *kvm_device_from_filp(struct file *filp); |
1067 | int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type); | ||
1067 | 1068 | ||
1068 | extern struct kvm_device_ops kvm_mpic_ops; | 1069 | extern struct kvm_device_ops kvm_mpic_ops; |
1069 | extern struct kvm_device_ops kvm_xics_ops; | 1070 | extern struct kvm_device_ops kvm_xics_ops; |
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 0695a1e3e332..60768822b140 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h | |||
@@ -943,15 +943,25 @@ struct kvm_device_attr { | |||
943 | __u64 addr; /* userspace address of attr data */ | 943 | __u64 addr; /* userspace address of attr data */ |
944 | }; | 944 | }; |
945 | 945 | ||
946 | #define KVM_DEV_TYPE_FSL_MPIC_20 1 | ||
947 | #define KVM_DEV_TYPE_FSL_MPIC_42 2 | ||
948 | #define KVM_DEV_TYPE_XICS 3 | ||
949 | #define KVM_DEV_TYPE_VFIO 4 | ||
950 | #define KVM_DEV_VFIO_GROUP 1 | 946 | #define KVM_DEV_VFIO_GROUP 1 |
951 | #define KVM_DEV_VFIO_GROUP_ADD 1 | 947 | #define KVM_DEV_VFIO_GROUP_ADD 1 |
952 | #define KVM_DEV_VFIO_GROUP_DEL 2 | 948 | #define KVM_DEV_VFIO_GROUP_DEL 2 |
953 | #define KVM_DEV_TYPE_ARM_VGIC_V2 5 | 949 | |
954 | #define KVM_DEV_TYPE_FLIC 6 | 950 | enum kvm_device_type { |
951 | KVM_DEV_TYPE_FSL_MPIC_20 = 1, | ||
952 | #define KVM_DEV_TYPE_FSL_MPIC_20 KVM_DEV_TYPE_FSL_MPIC_20 | ||
953 | KVM_DEV_TYPE_FSL_MPIC_42, | ||
954 | #define KVM_DEV_TYPE_FSL_MPIC_42 KVM_DEV_TYPE_FSL_MPIC_42 | ||
955 | KVM_DEV_TYPE_XICS, | ||
956 | #define KVM_DEV_TYPE_XICS KVM_DEV_TYPE_XICS | ||
957 | KVM_DEV_TYPE_VFIO, | ||
958 | #define KVM_DEV_TYPE_VFIO KVM_DEV_TYPE_VFIO | ||
959 | KVM_DEV_TYPE_ARM_VGIC_V2, | ||
960 | #define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2 | ||
961 | KVM_DEV_TYPE_FLIC, | ||
962 | #define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC | ||
963 | KVM_DEV_TYPE_MAX, | ||
964 | }; | ||
955 | 965 | ||
956 | /* | 966 | /* |
957 | * ioctls for VM fds | 967 | * ioctls for VM fds |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c338599804e0..686d783387a0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -2272,44 +2272,55 @@ struct kvm_device *kvm_device_from_filp(struct file *filp) | |||
2272 | return filp->private_data; | 2272 | return filp->private_data; |
2273 | } | 2273 | } |
2274 | 2274 | ||
2275 | static int kvm_ioctl_create_device(struct kvm *kvm, | 2275 | static struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = { |
2276 | struct kvm_create_device *cd) | ||
2277 | { | ||
2278 | struct kvm_device_ops *ops = NULL; | ||
2279 | struct kvm_device *dev; | ||
2280 | bool test = cd->flags & KVM_CREATE_DEVICE_TEST; | ||
2281 | int ret; | ||
2282 | |||
2283 | switch (cd->type) { | ||
2284 | #ifdef CONFIG_KVM_MPIC | 2276 | #ifdef CONFIG_KVM_MPIC |
2285 | case KVM_DEV_TYPE_FSL_MPIC_20: | 2277 | [KVM_DEV_TYPE_FSL_MPIC_20] = &kvm_mpic_ops, |
2286 | case KVM_DEV_TYPE_FSL_MPIC_42: | 2278 | [KVM_DEV_TYPE_FSL_MPIC_42] = &kvm_mpic_ops, |
2287 | ops = &kvm_mpic_ops; | ||
2288 | break; | ||
2289 | #endif | 2279 | #endif |
2280 | |||
2290 | #ifdef CONFIG_KVM_XICS | 2281 | #ifdef CONFIG_KVM_XICS |
2291 | case KVM_DEV_TYPE_XICS: | 2282 | [KVM_DEV_TYPE_XICS] = &kvm_xics_ops, |
2292 | ops = &kvm_xics_ops; | ||
2293 | break; | ||
2294 | #endif | 2283 | #endif |
2284 | |||
2295 | #ifdef CONFIG_KVM_VFIO | 2285 | #ifdef CONFIG_KVM_VFIO |
2296 | case KVM_DEV_TYPE_VFIO: | 2286 | [KVM_DEV_TYPE_VFIO] = &kvm_vfio_ops, |
2297 | ops = &kvm_vfio_ops; | ||
2298 | break; | ||
2299 | #endif | 2287 | #endif |
2288 | |||
2300 | #ifdef CONFIG_KVM_ARM_VGIC | 2289 | #ifdef CONFIG_KVM_ARM_VGIC |
2301 | case KVM_DEV_TYPE_ARM_VGIC_V2: | 2290 | [KVM_DEV_TYPE_ARM_VGIC_V2] = &kvm_arm_vgic_v2_ops, |
2302 | ops = &kvm_arm_vgic_v2_ops; | ||
2303 | break; | ||
2304 | #endif | 2291 | #endif |
2292 | |||
2305 | #ifdef CONFIG_S390 | 2293 | #ifdef CONFIG_S390 |
2306 | case KVM_DEV_TYPE_FLIC: | 2294 | [KVM_DEV_TYPE_FLIC] = &kvm_flic_ops, |
2307 | ops = &kvm_flic_ops; | ||
2308 | break; | ||
2309 | #endif | 2295 | #endif |
2310 | default: | 2296 | }; |
2297 | |||
2298 | int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type) | ||
2299 | { | ||
2300 | if (type >= ARRAY_SIZE(kvm_device_ops_table)) | ||
2301 | return -ENOSPC; | ||
2302 | |||
2303 | if (kvm_device_ops_table[type] != NULL) | ||
2304 | return -EEXIST; | ||
2305 | |||
2306 | kvm_device_ops_table[type] = ops; | ||
2307 | return 0; | ||
2308 | } | ||
2309 | |||
2310 | static int kvm_ioctl_create_device(struct kvm *kvm, | ||
2311 | struct kvm_create_device *cd) | ||
2312 | { | ||
2313 | struct kvm_device_ops *ops = NULL; | ||
2314 | struct kvm_device *dev; | ||
2315 | bool test = cd->flags & KVM_CREATE_DEVICE_TEST; | ||
2316 | int ret; | ||
2317 | |||
2318 | if (cd->type >= ARRAY_SIZE(kvm_device_ops_table)) | ||
2319 | return -ENODEV; | ||
2320 | |||
2321 | ops = kvm_device_ops_table[cd->type]; | ||
2322 | if (ops == NULL) | ||
2311 | return -ENODEV; | 2323 | return -ENODEV; |
2312 | } | ||
2313 | 2324 | ||
2314 | if (test) | 2325 | if (test) |
2315 | return 0; | 2326 | return 0; |