1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ACRN_HSM: Virtual Machine management 4 * 5 * Copyright (C) 2020 Intel Corporation. All rights reserved. 6 * 7 * Authors: 8 * Jason Chen CJ <jason.cj.chen@intel.com> 9 * Yakui Zhao <yakui.zhao@intel.com> 10 */ 11 #include <linux/io.h> 12 #include <linux/mm.h> 13 #include <linux/slab.h> 14 15 #include "acrn_drv.h" 16 17 /* List of VMs */ 18 LIST_HEAD(acrn_vm_list); 19 /* 20 * acrn_vm_list is read in a worker thread which dispatch I/O requests and 21 * is wrote in VM creation ioctl. Use the rwlock mechanism to protect it. 22 */ 23 DEFINE_RWLOCK(acrn_vm_list_lock); 24 25 struct acrn_vm *acrn_vm_create(struct acrn_vm *vm, 26 struct acrn_vm_creation *vm_param) 27 { 28 int ret; 29 30 ret = hcall_create_vm(virt_to_phys(vm_param)); 31 if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) { 32 dev_err(acrn_dev.this_device, 33 "Failed to create VM! Error: %d\n", ret); 34 return NULL; 35 } 36 37 mutex_init(&vm->regions_mapping_lock); 38 INIT_LIST_HEAD(&vm->ioreq_clients); 39 spin_lock_init(&vm->ioreq_clients_lock); 40 vm->vmid = vm_param->vmid; 41 vm->vcpu_num = vm_param->vcpu_num; 42 43 if (acrn_ioreq_init(vm, vm_param->ioreq_buf) < 0) { 44 hcall_destroy_vm(vm_param->vmid); 45 vm->vmid = ACRN_INVALID_VMID; 46 return NULL; 47 } 48 49 write_lock_bh(&acrn_vm_list_lock); 50 list_add(&vm->list, &acrn_vm_list); 51 write_unlock_bh(&acrn_vm_list_lock); 52 53 dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid); 54 return vm; 55 } 56 57 int acrn_vm_destroy(struct acrn_vm *vm) 58 { 59 int ret; 60 61 if (vm->vmid == ACRN_INVALID_VMID || 62 test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags)) 63 return 0; 64 65 /* Remove from global VM list */ 66 write_lock_bh(&acrn_vm_list_lock); 67 list_del_init(&vm->list); 68 write_unlock_bh(&acrn_vm_list_lock); 69 70 acrn_ioreq_deinit(vm); 71 72 ret = hcall_destroy_vm(vm->vmid); 73 if (ret < 0) { 74 dev_err(acrn_dev.this_device, 75 "Failed to destroy VM %u\n", vm->vmid); 76 clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags); 77 return ret; 78 } 79 80 acrn_vm_all_ram_unmap(vm); 81 82 dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid); 83 vm->vmid = ACRN_INVALID_VMID; 84 return 0; 85 } 86