977790051a9f6517cb25698fbad253608e52b050
[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 making
55          * startup vmcalls. For security's sake we might still want to lock in the
56          * future. TODO(ganshun)
57          * up_gpcs refers to the number of guest pcores that have
58          * been started 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 guest's
63          * 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 initial
68          * default page tables we use this range. Note that even if the "physical"
69          * memory has holes, we'll create PTEs for it. This seems enough for now but
70          * 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
75          * guest thread. We expect this to be the common case,
76          * where all guests share a page table. It's not required
77          * however. setup_paging now updates this to point to the initial set of
78          * page tables for the guest. */
79         void                                            *root;
80
81         /* Default value for whether guest threads halt on an exit. */
82         bool                                            halt_exit;
83         /* Override for vmcall (vthreads) */
84         bool (*vmcall)(struct guest_thread *gth, struct vm_trapframe *);
85 };
86
87 struct elf_aux {
88         unsigned long v[2];
89 };
90
91 char *regname(uint8_t reg);
92 int decode(struct guest_thread *vm_thread, uint64_t *gpa, uint8_t *destreg,
93            uint64_t **regp, int *store, int *size, int *advance);
94 int io(struct guest_thread *vm_thread);
95 void showstatus(FILE *f, struct guest_thread *vm_thread);
96 int gvatogpa(struct guest_thread *vm_thread, uint64_t va, uint64_t *pa);
97 int rippa(struct guest_thread *vm_thread, uint64_t *pa);
98 int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
99           uint32_t opcode);
100 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa,
101               int destreg, uint64_t *regp, int store);
102 bool handle_vmexit(struct guest_thread *gth);
103 int __apic_access(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
104                   uint64_t *regp, int store);
105 int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
106                         unsigned int vector);
107 uintptr_t load_elf(char *filename, uint64_t offset, uint64_t *highest,
108                    Elf64_Ehdr *ehdr_out);
109 ssize_t setup_initrd(char *filename, void *membase, size_t memsize);
110
111 /* Lookup helpers */
112
113 static struct virtual_machine *gth_to_vm(struct guest_thread *gth)
114 {
115         return ((struct vmm_thread*)gth)->vm;
116 }
117
118 static struct vm_trapframe *gth_to_vmtf(struct guest_thread *gth)
119 {
120         return &gth->uthread.u_ctx.tf.vm_tf;
121 }
122
123 static struct vmm_gpcore_init *gth_to_gpci(struct guest_thread *gth)
124 {
125         return &gth->gpci;
126 }
127
128 static struct guest_thread *gpcid_to_gth(struct virtual_machine *vm,
129                                          unsigned int gpc_id)
130 {
131         struct guest_thread **array;
132         struct guest_thread *gth;
133
134         /* Syncing with any dynamic growth of __gths */
135         do {
136                 array = ACCESS_ONCE(vm->__gths);
137                 gth = array[gpc_id];
138                 rmb();  /* read ret before rereading array pointer */
139         } while (array != ACCESS_ONCE(vm->__gths));
140         return gth;
141 }
142
143 static struct vm_trapframe *gpcid_to_vmtf(struct virtual_machine *vm,
144                                           unsigned int gpc_id)
145 {
146         return gth_to_vmtf(gpcid_to_gth(vm, gpc_id));
147 }
148
149 static struct virtual_machine *get_my_vm(void)
150 {
151         return ((struct vmm_thread*)current_uthread)->vm;
152 }
153
154 /* memory helpers */
155 void *init_e820map(struct virtual_machine *vm, struct boot_params *bp);
156 void checkmemaligned(uintptr_t memstart, size_t memsize);
157 void mmap_memory(struct virtual_machine *vm, uintptr_t memstart,
158                  size_t memsize);
159 bool mmap_file(const char *path, uintptr_t memstart, uintptr_t memsize,
160                uint64_t protections, uint64_t offset);
161 void add_pte_entries(struct virtual_machine *vm, uintptr_t start,
162                      uintptr_t end);
163 void setup_paging(struct virtual_machine *vm);
164 void *setup_biostables(struct virtual_machine *vm,
165                        void *a, void *smbiostable);
166 void *populate_stack(uintptr_t *stack, int argc, char *argv[],
167                          int envc, char *envp[],
168                          int auxc, struct elf_aux auxv[]);
169 /* For vthreads */
170 struct guest_thread *create_guest_thread(struct virtual_machine *vm,
171                                          unsigned int gpcoreid,
172                                          struct vmm_gpcore_init *gpci);