0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/io.h>
0012 #include <linux/mm.h>
0013 #include <linux/slab.h>
0014
0015 #include "acrn_drv.h"
0016
0017
0018 LIST_HEAD(acrn_vm_list);
0019
0020
0021
0022
0023 DEFINE_RWLOCK(acrn_vm_list_lock);
0024
0025 struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
0026 struct acrn_vm_creation *vm_param)
0027 {
0028 int ret;
0029
0030 ret = hcall_create_vm(virt_to_phys(vm_param));
0031 if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) {
0032 dev_err(acrn_dev.this_device,
0033 "Failed to create VM! Error: %d\n", ret);
0034 return NULL;
0035 }
0036
0037 mutex_init(&vm->regions_mapping_lock);
0038 INIT_LIST_HEAD(&vm->ioreq_clients);
0039 spin_lock_init(&vm->ioreq_clients_lock);
0040 vm->vmid = vm_param->vmid;
0041 vm->vcpu_num = vm_param->vcpu_num;
0042
0043 if (acrn_ioreq_init(vm, vm_param->ioreq_buf) < 0) {
0044 hcall_destroy_vm(vm_param->vmid);
0045 vm->vmid = ACRN_INVALID_VMID;
0046 return NULL;
0047 }
0048
0049 write_lock_bh(&acrn_vm_list_lock);
0050 list_add(&vm->list, &acrn_vm_list);
0051 write_unlock_bh(&acrn_vm_list_lock);
0052
0053 acrn_ioeventfd_init(vm);
0054 acrn_irqfd_init(vm);
0055 dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid);
0056 return vm;
0057 }
0058
0059 int acrn_vm_destroy(struct acrn_vm *vm)
0060 {
0061 int ret;
0062
0063 if (vm->vmid == ACRN_INVALID_VMID ||
0064 test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags))
0065 return 0;
0066
0067 ret = hcall_destroy_vm(vm->vmid);
0068 if (ret < 0) {
0069 dev_err(acrn_dev.this_device,
0070 "Failed to destroy VM %u\n", vm->vmid);
0071 clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags);
0072 return ret;
0073 }
0074
0075
0076 write_lock_bh(&acrn_vm_list_lock);
0077 list_del_init(&vm->list);
0078 write_unlock_bh(&acrn_vm_list_lock);
0079
0080 acrn_ioeventfd_deinit(vm);
0081 acrn_irqfd_deinit(vm);
0082 acrn_ioreq_deinit(vm);
0083
0084 if (vm->monitor_page) {
0085 put_page(vm->monitor_page);
0086 vm->monitor_page = NULL;
0087 }
0088
0089 acrn_vm_all_ram_unmap(vm);
0090
0091 dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid);
0092 vm->vmid = ACRN_INVALID_VMID;
0093 return 0;
0094 }
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 int acrn_msi_inject(struct acrn_vm *vm, u64 msi_addr, u64 msi_data)
0105 {
0106 struct acrn_msi_entry *msi;
0107 int ret;
0108
0109
0110 msi = kzalloc(sizeof(*msi), GFP_ATOMIC);
0111 if (!msi)
0112 return -ENOMEM;
0113
0114
0115
0116
0117
0118 msi->msi_addr = msi_addr;
0119 msi->msi_data = msi_data;
0120 ret = hcall_inject_msi(vm->vmid, virt_to_phys(msi));
0121 if (ret < 0)
0122 dev_err(acrn_dev.this_device,
0123 "Failed to inject MSI to VM %u!\n", vm->vmid);
0124 kfree(msi);
0125 return ret;
0126 }