1/*
2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <autoconf.h>
8
9#include <string.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <utils/util.h>
13
14#include <sel4vm/guest_vm.h>
15#include <sel4vm/boot.h>
16#include <sel4vm/guest_vm_exits.h>
17#include <sel4vm/guest_vm_util.h>
18
19#include "vm_boot.h"
20
21static int curr_vcpu_index = 0;
22
23int vm_init(vm_t *vm, vka_t *vka, simple_t *host_simple, vspace_t host_vspace,
24            ps_io_ops_t *io_ops, seL4_CPtr host_endpoint, const char *name)
25{
26    int err;
27    bzero(vm, sizeof(vm_t));
28    /* Initialise vm fields */
29    vm->vka = vka;
30    vm->simple = host_simple;
31    vm->io_ops = io_ops;
32    vm->mem.vmm_vspace = host_vspace;
33    vm->host_endpoint = host_endpoint;
34    vm->vm_name = strndup(name, strlen(name));
35    vm->run.exit_reason = VM_GUEST_UNKNOWN_EXIT;
36    /* Initialise ram region */
37    vm->mem.num_ram_regions = 0;
38    vm->mem.ram_regions = malloc(0);
39    assert(vm->vcpus);
40    /* Initialise vm memory management interface */
41    err = vm_memory_init(vm);
42    if (err) {
43        ZF_LOGE("Failed to initialise VM memory manager");
44        return err;
45    }
46
47    /* Initialise vm architecture support */
48    err = vm_init_arch(vm);
49    if (err) {
50        ZF_LOGE("Failed to initialise VM architecture support");
51        return err;
52    }
53
54    /* Flag that the vm has been initialised */
55    vm->vm_initialised = true;
56    return 0;
57}
58
59vm_vcpu_t *vm_create_vcpu(vm_t *vm, int priority)
60{
61    int err;
62    if (vm->num_vcpus >= CONFIG_MAX_NUM_NODES) {
63        ZF_LOGE("Failed to create vcpu, reached maximum number of support vcpus");
64        return NULL;
65    }
66    vm_vcpu_t *vcpu_new = calloc(1, sizeof(vm_vcpu_t));
67    assert(vcpu_new);
68    /* Create VCPU */
69    err = vka_alloc_vcpu(vm->vka, &vcpu_new->vcpu);
70    assert(!err);
71    /* Initialise vcpu fields */
72    vcpu_new->vm = vm;
73    vcpu_new->vcpu_id = curr_vcpu_index++;
74    vcpu_new->tcb.priority = priority;
75    vcpu_new->vcpu_online = false;
76    vcpu_new->target_cpu = -1;
77    err = vm_create_vcpu_arch(vm, vcpu_new);
78    assert(!err);
79    vm->vcpus[vm->num_vcpus] = vcpu_new;
80    vm->num_vcpus++;
81    return vcpu_new;
82}
83
84int vm_assign_vcpu_target(vm_vcpu_t *vcpu, int target_cpu)
85{
86    if (vcpu == NULL) {
87        ZF_LOGE("Failed to assign target cpu - Invalid vcpu");
88        return -1;
89    }
90    vm_vcpu_t *target_vcpu = vm_vcpu_for_target_cpu(vcpu->vm, target_cpu);
91    if (target_vcpu) {
92        ZF_LOGE("Failed to assign target cpu - A VCPU is already assigned to core %d", target_cpu);
93        return -1;
94    }
95    vcpu->target_cpu = target_cpu;
96    return 0;
97}
98