vmm: Rename root_mtx
[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                            nr_gpcs;
53         /* up_gpcs should not need synchronization. only the BSP should be making
54          * startup vmcalls. For security's sake we might still want to lock in the
55          * future. TODO(ganshun)
56          * up_gpcs refers to the number of guest pcores that have
57          * been started so far. */
58         unsigned int                            up_gpcs;
59
60         /* TODO: put these in appropriate structures.  e.g., virtio things in
61          * something related to virtio.  low4k in something related to the guest's
62          * memory. */
63         uint8_t                                         *low4k;
64         struct virtio_mmio_dev          *virtio_mmio_devices[VIRTIO_MMIO_MAX_NUM_DEV];
65
66         /* minimum and maximum physical memory addresses. When we set up the initial
67          * default page tables we use this range. Note that even if the "physical"
68          * memory has holes, we'll create PTEs for it. This seems enough for now but
69          * we shall see. */
70         uintptr_t                                       minphys;
71         uintptr_t                                       maxphys;
72
73         /* Default root pointer to use if one is not set in a
74          * guest thread. We expect this to be the common case,
75          * where all guests share a page table. It's not required
76          * however. setup_paging now updates this to point to the initial set of
77          * 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 char *regname(uint8_t reg);
91 int decode(struct guest_thread *vm_thread, uint64_t *gpa, uint8_t *destreg,
92            uint64_t **regp, int *store, int *size, int *advance);
93 int io(struct guest_thread *vm_thread);
94 void showstatus(FILE *f, struct guest_thread *vm_thread);
95 int gvatogpa(struct guest_thread *vm_thread, uint64_t va, uint64_t *pa);
96 int rippa(struct guest_thread *vm_thread, uint64_t *pa);
97 int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
98           uint32_t opcode);
99 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa,
100               int destreg, uint64_t *regp, int store);
101 bool handle_vmexit(struct guest_thread *gth);
102 int __apic_access(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
103                   uint64_t *regp, int store);
104 int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
105                         unsigned int vector);
106 uintptr_t load_elf(char *filename, uint64_t offset, uint64_t *highest,
107                    Elf64_Ehdr *ehdr_out);
108 ssize_t setup_initrd(char *filename, void *membase, size_t memsize);
109
110 /* Lookup helpers */
111
112 static struct virtual_machine *gth_to_vm(struct guest_thread *gth)
113 {
114         return ((struct vmm_thread*)gth)->vm;
115 }
116
117 static struct vm_trapframe *gth_to_vmtf(struct guest_thread *gth)
118 {
119         return &gth->uthread.u_ctx.tf.vm_tf;
120 }
121
122 static struct vmm_gpcore_init *gth_to_gpci(struct guest_thread *gth)
123 {
124         return &gth->gpci;
125 }
126
127 static struct guest_thread *gpcid_to_gth(struct virtual_machine *vm,
128                                          unsigned int gpc_id)
129 {
130         struct guest_thread **array;
131         struct guest_thread *gth;
132
133         /* Syncing with any dynamic growth of __gths */
134         do {
135                 array = ACCESS_ONCE(vm->__gths);
136                 gth = array[gpc_id];
137                 rmb();  /* read ret before rereading array pointer */
138         } while (array != ACCESS_ONCE(vm->__gths));
139         return gth;
140 }
141
142 static struct vm_trapframe *gpcid_to_vmtf(struct virtual_machine *vm,
143                                           unsigned int gpc_id)
144 {
145         return gth_to_vmtf(gpcid_to_gth(vm, gpc_id));
146 }
147
148 static struct virtual_machine *get_my_vm(void)
149 {
150         return ((struct vmm_thread*)current_uthread)->vm;
151 }
152
153 /* memory helpers */
154 void *init_e820map(struct virtual_machine *vm, struct boot_params *bp);
155 void checkmemaligned(uintptr_t memstart, size_t memsize);
156 void mmap_memory(struct virtual_machine *vm, uintptr_t memstart,
157                  size_t memsize);
158 bool mmap_file(const char *path, uintptr_t memstart, uintptr_t memsize,
159                uint64_t protections, uint64_t offset);
160 void add_pte_entries(struct virtual_machine *vm, uintptr_t start,
161                      uintptr_t end);
162 void setup_paging(struct virtual_machine *vm);
163 void *setup_biostables(struct virtual_machine *vm,
164                        void *a, void *smbiostable);
165 void *populate_stack(uintptr_t *stack, int argc, char *argv[],
166                          int envc, char *envp[],
167                          int auxc, struct elf_aux auxv[]);