int hax_vcpu_create(int id) { struct hax_vcpu_state *vcpu = NULL; int ret; if (!hax_global.vm) { fprintf(stderr, "vcpu %x created failed, vm is null\n", id); return -1; } if (hax_global.vm->vcpus[id]) { fprintf(stderr, "vcpu %x allocated already\n", id); return 0; } vcpu = g_new0(struct hax_vcpu_state, 1); ret = hax_host_create_vcpu(hax_global.vm->fd, id); if (ret) { fprintf(stderr, "Failed to create vcpu %x\n", id); goto error; } vcpu->vcpu_id = id; vcpu->fd = hax_host_open_vcpu(hax_global.vm->id, id); if (hax_invalid_fd(vcpu->fd)) { fprintf(stderr, "Failed to open the vcpu\n"); ret = -ENODEV; goto error; } hax_global.vm->vcpus[id] = vcpu; ret = hax_host_setup_vcpu_channel(vcpu); if (ret) { fprintf(stderr, "Invalid hax tunnel size\n"); ret = -EINVAL; goto error; } return 0; error: /* vcpu and tunnel will be closed automatically */ if (vcpu && !hax_invalid_fd(vcpu->fd)) { hax_close_fd(vcpu->fd); } hax_global.vm->vcpus[id] = NULL; g_free(vcpu); return -1; }
int hax_vm_destroy(struct hax_vm *vm) { int i; for (i = 0; i < HAX_MAX_VCPU; i++) if (vm->vcpus[i]) { fprintf(stderr, "VCPU should be cleaned before vm clean\n"); return -1; } hax_close_fd(vm->fd); g_free(vm); hax_global.vm = NULL; return 0; }
int hax_vcpu_destroy(CPUState *cpu) { struct hax_vcpu_state *vcpu = cpu->hax_vcpu; if (!hax_global.vm) { fprintf(stderr, "vcpu %x destroy failed, vm is null\n", vcpu->vcpu_id); return -1; } if (!vcpu) { return 0; } /* * 1. The hax_tunnel is also destroyed when vcpu is destroyed * 2. close fd will cause hax module vcpu be cleaned */ hax_close_fd(vcpu->fd); hax_global.vm->vcpus[vcpu->vcpu_id] = NULL; g_free(vcpu); return 0; }
bool VCpu_Destroy(hax_state *Hax, hax_vcpu_state *CPU) { if (!Hax->vm) { printf("vCPU %x destroy failed, vm is null\n", CPU->vcpu_id); return false; } // Get a direct pointer to the index auto vCPU = Hax->vm->vcpus[CPU->vcpu_id]; // Check if valid if (!vCPU) return false; // 1. The hax_tunnel is also destroyed at vcpu_destroy // 2. hax_close_fd will require the HAX kernel module to free vCPU Hax->vm->vcpus[CPU->vcpu_id] = nullptr; hax_close_fd(vCPU->fd); free(vCPU); return true; }
hax_vcpu_state *VCpu_Create(hax_state *Hax) { if (!Hax->vm) { printf("vCPU created failed, vm is null\n"); return nullptr; } // Find the next free vCPU index int cpuId = -1; for (int i = 0; i < ARRAYSIZE(Hax->vm->vcpus); i++) { if (Hax->vm->vcpus[i]) continue; cpuId = i; break; } if (cpuId == -1) { printf("Maximum number of vCPUs have been allocated for this VM!\n"); return nullptr; } // Allocate the virtual CPU instance structure and // zero memory auto vCPU = (hax_vcpu_state *)malloc(sizeof(hax_vcpu_state)); if (!vCPU) { printf("Failed to alloc vCPU state\n"); return nullptr; } memset(vCPU, 0, sizeof(hax_vcpu_state)); // Tell the driver to create the vCPU instance vCPU->vcpu_id = cpuId; if (hax_host_create_vcpu(Hax->vm->fd, cpuId) < 0) { printf("Failed to create vCPU %x\n", cpuId); goto error; } // Grab a handle to the driver's instance vCPU->fd = hax_host_open_vcpu(Hax->vm->id, cpuId); if (hax_invalid_fd(vCPU->fd)) { printf("Failed to open the vCPU handle\n"); goto error; } // Mark the CPU index as used with a pointer Hax->vm->vcpus[cpuId] = vCPU; // Create the tunnel to kernel data if (hax_host_setup_vcpu_channel(vCPU) < 0) { printf("Invalid HAX tunnel size \n"); goto error; } return vCPU; error: // vCPU and tunnel will be closed automatically if (vCPU && !hax_invalid_fd(vCPU->fd)) hax_close_fd(vCPU->fd); Hax->vm->vcpus[cpuId] = nullptr; free(vCPU); return nullptr; }