154 lines
4.4 KiB
Diff
154 lines
4.4 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Shuo A Liu <shuo.a.liu@intel.com>
|
|
Date: Fri, 30 Nov 2018 14:06:10 +0800
|
|
Subject: [PATCH] vhm: destroy VM and release all its resources while closing
|
|
vhm device
|
|
|
|
With closing vhm device, we need release all resources hold by VM in
|
|
vhm, or we might leak resources and cannot re-create it next time.
|
|
|
|
Tracked-On: projectacrn/acrn-hypervisor#2058
|
|
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
|
|
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
---
|
|
drivers/char/vhm/vhm_dev.c | 40 +++++++++++++++++++++------------
|
|
drivers/vhm/vhm_ioreq.c | 14 +++++-------
|
|
include/linux/vhm/vhm_vm_mngt.h | 16 +++++++++++--
|
|
3 files changed, 46 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/drivers/char/vhm/vhm_dev.c b/drivers/char/vhm/vhm_dev.c
|
|
index 2dcdbef01bd3..74615e0a6ab4 100644
|
|
--- a/drivers/char/vhm/vhm_dev.c
|
|
+++ b/drivers/char/vhm/vhm_dev.c
|
|
@@ -200,7 +200,8 @@ static long vhm_dev_ioctl(struct file *filep,
|
|
pr_err("vhm: invalid VM !\n");
|
|
return -EFAULT;
|
|
}
|
|
- if ((vm->vmid == ACRN_INVALID_VMID) && (ioctl_num != IC_CREATE_VM)) {
|
|
+ if (((vm->vmid == ACRN_INVALID_VMID) && (ioctl_num != IC_CREATE_VM)) ||
|
|
+ test_bit(VHM_VM_DESTROYED, &vm->flags)) {
|
|
pr_err("vhm: invalid VM ID !\n");
|
|
return -EFAULT;
|
|
}
|
|
@@ -281,15 +282,7 @@ static long vhm_dev_ioctl(struct file *filep,
|
|
}
|
|
|
|
case IC_DESTROY_VM: {
|
|
- acrn_ioeventfd_deinit(vm->vmid);
|
|
- acrn_irqfd_deinit(vm->vmid);
|
|
- acrn_ioreq_free(vm);
|
|
- ret = hcall_destroy_vm(vm->vmid);
|
|
- if (ret < 0) {
|
|
- pr_err("failed to destroy VM %ld\n", vm->vmid);
|
|
- return -EFAULT;
|
|
- }
|
|
- vm->vmid = ACRN_INVALID_VMID;
|
|
+ ret = vhm_vm_destroy(vm);
|
|
break;
|
|
}
|
|
|
|
@@ -771,6 +764,28 @@ static void vhm_intr_handler(void)
|
|
tasklet_schedule(&vhm_io_req_tasklet);
|
|
}
|
|
|
|
+int vhm_vm_destroy(struct vhm_vm *vm)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (test_and_set_bit(VHM_VM_DESTROYED, &vm->flags))
|
|
+ return -ENODEV;
|
|
+
|
|
+ acrn_ioeventfd_deinit(vm->vmid);
|
|
+ acrn_irqfd_deinit(vm->vmid);
|
|
+ acrn_ioreq_free(vm);
|
|
+
|
|
+ ret = hcall_destroy_vm(vm->vmid);
|
|
+ if (ret < 0)
|
|
+ pr_err("Failed to destroy VM %ld!\n", vm->vmid);
|
|
+ write_lock_bh(&vhm_vm_list_lock);
|
|
+ list_del_init(&vm->list);
|
|
+ write_unlock_bh(&vhm_vm_list_lock);
|
|
+ vm->vmid = ACRN_INVALID_VMID;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int vhm_dev_release(struct inode *inodep, struct file *filep)
|
|
{
|
|
struct vhm_vm *vm = filep->private_data;
|
|
@@ -779,10 +794,7 @@ static int vhm_dev_release(struct inode *inodep, struct file *filep)
|
|
pr_err("vhm: invalid VM !\n");
|
|
return -EFAULT;
|
|
}
|
|
- acrn_ioreq_free(vm);
|
|
- write_lock_bh(&vhm_vm_list_lock);
|
|
- list_del_init(&vm->list);
|
|
- write_unlock_bh(&vhm_vm_list_lock);
|
|
+ vhm_vm_destroy(vm);
|
|
put_vm(vm);
|
|
filep->private_data = NULL;
|
|
return 0;
|
|
diff --git a/drivers/vhm/vhm_ioreq.c b/drivers/vhm/vhm_ioreq.c
|
|
index 8aab2c3cb55d..85c7f902c781 100644
|
|
--- a/drivers/vhm/vhm_ioreq.c
|
|
+++ b/drivers/vhm/vhm_ioreq.c
|
|
@@ -1080,15 +1080,13 @@ void acrn_ioreq_free(struct vhm_vm *vm)
|
|
* The below is used to assure that the client is still released even when
|
|
* it is not called.
|
|
*/
|
|
- if (!test_and_set_bit(VHM_VM_IOREQ, &vm->flags)) {
|
|
- get_vm(vm);
|
|
- list_for_each_safe(pos, tmp, &vm->ioreq_client_list) {
|
|
- struct ioreq_client *client =
|
|
- container_of(pos, struct ioreq_client, list);
|
|
- acrn_ioreq_destroy_client(client->id);
|
|
- }
|
|
- put_vm(vm);
|
|
+ get_vm(vm);
|
|
+ list_for_each_safe(pos, tmp, &vm->ioreq_client_list) {
|
|
+ struct ioreq_client *client =
|
|
+ container_of(pos, struct ioreq_client, list);
|
|
+ acrn_ioreq_destroy_client(client->id);
|
|
}
|
|
+ put_vm(vm);
|
|
|
|
}
|
|
|
|
diff --git a/include/linux/vhm/vhm_vm_mngt.h b/include/linux/vhm/vhm_vm_mngt.h
|
|
index 6e61d4f80517..1f89f25502c6 100644
|
|
--- a/include/linux/vhm/vhm_vm_mngt.h
|
|
+++ b/include/linux/vhm/vhm_vm_mngt.h
|
|
@@ -71,8 +71,11 @@ extern rwlock_t vhm_vm_list_lock;
|
|
#define HUGEPAGE_HLIST_ARRAY_SIZE (HUGEPAGE_2M_HLIST_ARRAY_SIZE + \
|
|
HUGEPAGE_1G_HLIST_ARRAY_SIZE)
|
|
|
|
-enum VM_FREE_BITS {
|
|
- VHM_VM_IOREQ = 0,
|
|
+/**
|
|
+ * enum vhm_vm_flags - vhm vm flags definition
|
|
+ */
|
|
+enum vhm_vm_flags {
|
|
+ VHM_VM_DESTROYED = 0,
|
|
};
|
|
|
|
/**
|
|
@@ -182,6 +185,15 @@ int vhm_inject_msi(unsigned long vmid, unsigned long msi_addr,
|
|
*/
|
|
unsigned long vhm_vm_gpa2hpa(unsigned long vmid, unsigned long gpa);
|
|
|
|
+/**
|
|
+ * vhm_vm_destroy() - destroy VM and release its resources
|
|
+ *
|
|
+ * @vm: pointer to vhm_vm which identify specific guest
|
|
+ *
|
|
+ * Return: 0 on success, <0 on error
|
|
+ */
|
|
+int vhm_vm_destroy(struct vhm_vm *vm);
|
|
+
|
|
void vm_list_add(struct list_head *list);
|
|
|
|
#endif
|
|
--
|
|
https://clearlinux.org
|
|
|