aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-04-18 06:39:41 -0400
committerPaul Mackerras <paulus@ozlabs.org>2019-04-30 05:35:16 -0400
commit2bde9b3ec8bdf60788e9e2ce8c07a2f8d6003dbd (patch)
treed4998665dc62f3c003fbd7e8c28a65651c7ad7ff
parent3fab2d10588e09abd4bd7b9bacce5e4e435993f6 (diff)
KVM: Introduce a 'release' method for KVM devices
When a P9 sPAPR VM boots, the CAS negotiation process determines which interrupt mode to use (XICS legacy or XIVE native) and invokes a machine reset to activate the chosen mode. To be able to switch from one interrupt mode to another, we introduce the capability to release a KVM device without destroying the VM. The KVM device interface is extended with a new 'release' method which is called when the file descriptor of the device is closed. Once 'release' is called, the 'destroy' method will not be called anymore as the device is removed from the device list of the VM. Cc: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
-rw-r--r--include/linux/kvm_host.h9
-rw-r--r--virt/kvm/kvm_main.c13
2 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 831d963451d8..722692e2f745 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1240,6 +1240,15 @@ struct kvm_device_ops {
1240 */ 1240 */
1241 void (*destroy)(struct kvm_device *dev); 1241 void (*destroy)(struct kvm_device *dev);
1242 1242
1243 /*
1244 * Release is an alternative method to free the device. It is
1245 * called when the device file descriptor is closed. Once
1246 * release is called, the destroy method will not be called
1247 * anymore as the device is removed from the device list of
1248 * the VM. kvm->lock is held.
1249 */
1250 void (*release)(struct kvm_device *dev);
1251
1243 int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); 1252 int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
1244 int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); 1253 int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
1245 int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); 1254 int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index ea2018ae1cd7..ea2619d5ca98 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2938,6 +2938,19 @@ static int kvm_device_release(struct inode *inode, struct file *filp)
2938 struct kvm_device *dev = filp->private_data; 2938 struct kvm_device *dev = filp->private_data;
2939 struct kvm *kvm = dev->kvm; 2939 struct kvm *kvm = dev->kvm;
2940 2940
2941 if (!dev)
2942 return -ENODEV;
2943
2944 if (dev->kvm != kvm)
2945 return -EPERM;
2946
2947 if (dev->ops->release) {
2948 mutex_lock(&kvm->lock);
2949 list_del(&dev->vm_node);
2950 dev->ops->release(dev);
2951 mutex_unlock(&kvm->lock);
2952 }
2953
2941 kvm_put_kvm(kvm); 2954 kvm_put_kvm(kvm);
2942 return 0; 2955 return 0;
2943} 2956}