kconfig: use pkg-config for ncurses detection
[akaros.git] / user / vmm / include / vmm / vmm.h
1 /* Copyright (c) 2015 Google Inc.
2  * Ron Minnich <rminnich@google.com>
3  * See LICENSE for details.
4  *
5  * VMM.h */
6
7 #pragma once
8
9 #include <ros/vmm.h>
10 #include <vmm/sched.h>
11 #include <vmm/linux_bootparam.h>
12 #include <parlib/stdio.h>
13 #include <libelf.h>
14
15 // We need to reserve an area of the low 4G for thinks like tables, APIC, and
16 // so on. So far, 256 MiB has been more than enough, so ...
17 #define MiB 0x100000ull
18 #define MinMemory (16*MiB)
19 #define GiB (0x40000000ULL)
20 #define _4GiB (0x100000000ULL)
21 // BIOS conventions from 1978 make it smart to reserve the low 64k
22 #define LOW64K 65536
23 // The RESERVED area is for all the random junk like devices, ACPI, etc.
24 // We just give it the top 1 GiB of the 32-bit address space, which
25 // nicely translates to one GiB PTE.
26 #define RESERVED 0xC0000000ULL
27 #define RESERVEDSIZE (_4GiB - RESERVED)
28 // Start the VM at 16 MiB, a standard number for 64 bit kernels on amd64
29 #define KERNSTART 0x1000000
30
31 #define VM_PAGE_FAULT                   14
32
33 // APIC Guest Physical Address, a well known constant.
34 #define APIC_GPA                        0xfee00000ULL
35
36 /* The listing of VIRTIO MMIO devices. We currently only expect to have 2,
37  * console and network. Only the console is fully implemented right now.*/
38 enum {
39         VIRTIO_MMIO_CONSOLE_DEV,
40         VIRTIO_MMIO_NETWORK_DEV,
41         VIRTIO_MMIO_BLOCK_DEV,
42
43         /* This should always be the last entry. */
44         VIRTIO_MMIO_MAX_NUM_DEV,
45 };
46
47 /* Structure to encapsulate all of the bookkeeping for a VM. */
48 struct virtual_machine {
49         /* Big mutext for pagetables and __gths/ nr_gpcs */
50         uth_mutex_t                     mtx;
51         struct guest_thread             **__gths;
52         unsigned int                    gth_array_elem;
53         unsigned int                    nr_gpcs;
54         /* up_gpcs should not need synchronization. only the BSP should be
55          * making startup vmcalls. For security's sake we might still want to
56          * lock in the future. TODO(ganshun)
57          * up_gpcs refers to the number of guest pcores that have been started
58          * so far. */
59         unsigned int                    up_gpcs;
60
61         /* TODO: put these in appropriate structures.  e.g., virtio things in
62          * something related to virtio.  low4k in something related to the
63          * guest's memory. */
64         uint8_t                         *low4k;
65         struct virtio_mmio_dev *virtio_mmio_devices[VIRTIO_MMIO_MAX_NUM_DEV];
66
67         /* minimum and maximum physical memory addresses. When we set up the
68          * initial default page tables we use this range. Note that even if the
69          * "physical" memory has holes, we'll create PTEs for it. This seems
70          * enough for now but we shall see. */
71         uintptr_t                       minphys;
72         uintptr_t                       maxphys;
73
74         /* Default root pointer to use if one is not set in a guest thread. We
75          * expect this to be the common case, where all guests share a page
76          * table. It's not required however. setup_paging now updates this to
77          * point to the initial set of page tables for the guest. */
78                 void                    *root;
79
80         /* Default value for whether guest threads halt on an exit. */
81         bool                            halt_exit;
82         /* Override for vmcall (vthreads) */
83         bool (*vmcall)(struct guest_thread *gth, struct vm_trapframe *);
84 };
85
86 struct elf_aux {
87         unsigned long v[2];
88 };
89
90 /* TODO: x86-specific */
91 #define VMM_MAX_INSN_SZ 15
92 typedef int (*emu_mem_access)(struct guest_thread *gth, uintptr_t gpa,
93                               unsigned long *regp, size_t size,
94                               bool store);
95 int emulate_mem_insn(struct guest_thread *gth, uint8_t *insn,
96                      emu_mem_access access, int *advance);
97 int io(struct guest_thread *vm_thread);
98 void showstatus(FILE *f, struct guest_thread *vm_thread);
99 int gva2gpa(struct guest_thread *vm_thread, uint64_t va, uint64_t *pa);
100 int rippa(struct guest_thread *vm_thread, uint64_t *pa);
101 int fetch_insn(struct guest_thread *gth, uint8_t *insn);
102 int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
103           uint32_t opcode);
104 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa, uint64_t *regp,
105               bool store);
106 bool handle_vmexit(struct guest_thread *gth);
107 int __apic_access(struct guest_thread *gth, uint64_t gpa, uint64_t *regp,
108                   size_t size, bool store);
109 int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
110                         unsigned int vector);
111 uintptr_t load_elf(char *filename, uint64_t offset, uint64_t *highest,
112                    Elf64_Ehdr *ehdr_out);
113 ssize_t setup_initrd(char *filename, void *membase, size_t memsize);
114
115 /* Lookup helpers */
116
117 static struct virtual_machine *gth_to_vm(struct guest_thread *gth)
118 {
119         return ((struct vmm_thread*)gth)->vm;
120 }
121
122 static struct vm_trapframe *gth_to_vmtf(struct guest_thread *gth)
123 {
124         return &gth->uthread.u_ctx.tf.vm_tf;
125 }
126
127 static struct vmm_gpcore_init *gth_to_gpci(struct guest_thread *gth)
128 {
129         return &gth->gpci;
130 }
131
132 static struct guest_thread *gpcid_to_gth(struct virtual_machine *vm,
133                                          unsigned int gpc_id)
134 {
135         struct guest_thread **array;
136         struct guest_thread *gth;
137
138         /* Syncing with any dynamic growth of __gths */
139         do {
140                 array = ACCESS_ONCE(vm->__gths);
141                 gth = array[gpc_id];
142                 rmb();  /* read ret before rereading array pointer */
143         } while (array != ACCESS_ONCE(vm->__gths));
144         return gth;
145 }
146
147 static struct vm_trapframe *gpcid_to_vmtf(struct virtual_machine *vm,
148                                           unsigned int gpc_id)
149 {
150         return gth_to_vmtf(gpcid_to_gth(vm, gpc_id));
151 }
152
153 static struct virtual_machine *get_my_vm(void)
154 {
155         return ((struct vmm_thread*)current_uthread)->vm;
156 }
157
158 /* memory helpers */
159 void *init_e820map(struct virtual_machine *vm, struct boot_params *bp);
160 void checkmemaligned(uintptr_t memstart, size_t memsize);
161 void mmap_memory(struct virtual_machine *vm, uintptr_t memstart,
162                  size_t memsize);
163 bool mmap_file(const char *path, uintptr_t memstart, size_t memsize,
164                uint64_t protections, size_t offset);
165 void add_pte_entries(struct virtual_machine *vm, uintptr_t start,
166                      uintptr_t end);
167 void setup_paging(struct virtual_machine *vm);
168 void *setup_biostables(struct virtual_machine *vm,
169                        void *a, void *smbiostable);
170 void *populate_stack(uintptr_t *stack, int argc, char *argv[],
171                          int envc, char *envp[],
172                          int auxc, struct elf_aux auxv[]);
173 /* For vthreads */
174 struct guest_thread *create_guest_thread(struct virtual_machine *vm,
175                                          unsigned int gpcoreid,
176                                          struct vmm_gpcore_init *gpci);