19c5137aeSShuo Liu // SPDX-License-Identifier: GPL-2.0 29c5137aeSShuo Liu /* 39c5137aeSShuo Liu * ACRN_HSM: Virtual Machine management 49c5137aeSShuo Liu * 59c5137aeSShuo Liu * Copyright (C) 2020 Intel Corporation. All rights reserved. 69c5137aeSShuo Liu * 79c5137aeSShuo Liu * Authors: 89c5137aeSShuo Liu * Jason Chen CJ <jason.cj.chen@intel.com> 99c5137aeSShuo Liu * Yakui Zhao <yakui.zhao@intel.com> 109c5137aeSShuo Liu */ 119c5137aeSShuo Liu #include <linux/io.h> 129c5137aeSShuo Liu #include <linux/mm.h> 139c5137aeSShuo Liu #include <linux/slab.h> 149c5137aeSShuo Liu 159c5137aeSShuo Liu #include "acrn_drv.h" 169c5137aeSShuo Liu 179c5137aeSShuo Liu /* List of VMs */ 189c5137aeSShuo Liu static LIST_HEAD(acrn_vm_list); 199c5137aeSShuo Liu /* To protect acrn_vm_list */ 209c5137aeSShuo Liu static DEFINE_MUTEX(acrn_vm_list_lock); 219c5137aeSShuo Liu 229c5137aeSShuo Liu struct acrn_vm *acrn_vm_create(struct acrn_vm *vm, 239c5137aeSShuo Liu struct acrn_vm_creation *vm_param) 249c5137aeSShuo Liu { 259c5137aeSShuo Liu int ret; 269c5137aeSShuo Liu 279c5137aeSShuo Liu ret = hcall_create_vm(virt_to_phys(vm_param)); 289c5137aeSShuo Liu if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) { 299c5137aeSShuo Liu dev_err(acrn_dev.this_device, 309c5137aeSShuo Liu "Failed to create VM! Error: %d\n", ret); 319c5137aeSShuo Liu return NULL; 329c5137aeSShuo Liu } 339c5137aeSShuo Liu 34*88f537d5SShuo Liu mutex_init(&vm->regions_mapping_lock); 359c5137aeSShuo Liu vm->vmid = vm_param->vmid; 369c5137aeSShuo Liu vm->vcpu_num = vm_param->vcpu_num; 379c5137aeSShuo Liu 389c5137aeSShuo Liu mutex_lock(&acrn_vm_list_lock); 399c5137aeSShuo Liu list_add(&vm->list, &acrn_vm_list); 409c5137aeSShuo Liu mutex_unlock(&acrn_vm_list_lock); 419c5137aeSShuo Liu 429c5137aeSShuo Liu dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid); 439c5137aeSShuo Liu return vm; 449c5137aeSShuo Liu } 459c5137aeSShuo Liu 469c5137aeSShuo Liu int acrn_vm_destroy(struct acrn_vm *vm) 479c5137aeSShuo Liu { 489c5137aeSShuo Liu int ret; 499c5137aeSShuo Liu 509c5137aeSShuo Liu if (vm->vmid == ACRN_INVALID_VMID || 519c5137aeSShuo Liu test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags)) 529c5137aeSShuo Liu return 0; 539c5137aeSShuo Liu 549c5137aeSShuo Liu /* Remove from global VM list */ 559c5137aeSShuo Liu mutex_lock(&acrn_vm_list_lock); 569c5137aeSShuo Liu list_del_init(&vm->list); 579c5137aeSShuo Liu mutex_unlock(&acrn_vm_list_lock); 589c5137aeSShuo Liu 599c5137aeSShuo Liu ret = hcall_destroy_vm(vm->vmid); 609c5137aeSShuo Liu if (ret < 0) { 619c5137aeSShuo Liu dev_err(acrn_dev.this_device, 629c5137aeSShuo Liu "Failed to destroy VM %u\n", vm->vmid); 639c5137aeSShuo Liu clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags); 649c5137aeSShuo Liu return ret; 659c5137aeSShuo Liu } 66*88f537d5SShuo Liu 67*88f537d5SShuo Liu acrn_vm_all_ram_unmap(vm); 68*88f537d5SShuo Liu 699c5137aeSShuo Liu dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid); 709c5137aeSShuo Liu vm->vmid = ACRN_INVALID_VMID; 719c5137aeSShuo Liu return 0; 729c5137aeSShuo Liu } 73