No longer builds, but this is a good intermediate save point.
[akaros.git] / kern / arch / x86 / vm.h
1 #ifndef __LITEVM_H
2 #define __LITEVM_H
3 #include <page_alloc.h>
4 #include <sys/queue.h>
5 #include <pmap.h>
6 #include "vmx.h"
7
8 #define CR0_PE_MASK (1ULL << 0)
9 #define CR0_TS_MASK (1ULL << 3)
10 #define CR0_NE_MASK (1ULL << 5)
11 #define CR0_WP_MASK (1ULL << 16)
12 #define CR0_NW_MASK (1ULL << 29)
13 #define CR0_CD_MASK (1ULL << 30)
14 #define CR0_PG_MASK (1ULL << 31)
15
16 #define CR3_WPT_MASK (1ULL << 3)
17 #define CR3_PCD_MASK (1ULL << 4)
18
19 #define CR3_RESEVED_BITS 0x07ULL
20 #define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL)
21 #define CR3_FLAGS_MASK ((1ULL << 5) - 1)
22
23 #define CR4_VME_MASK (1ULL << 0)
24 #define CR4_PSE_MASK (1ULL << 4)
25 #define CR4_PAE_MASK (1ULL << 5)
26 #define CR4_PGE_MASK (1ULL << 7)
27 #define CR4_VMXE_MASK (1ULL << 13)
28
29 #define LITEVM_GUEST_CR0_MASK \
30         (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK)
31 #define LITEVM_VM_CR0_ALWAYS_ON LITEVM_GUEST_CR0_MASK
32
33 #define LITEVM_GUEST_CR4_MASK \
34         (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)
35 #define LITEVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
36 #define LITEVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK)
37
38 #define INVALID_PAGE (~(hpa_t)0)
39 #define UNMAPPED_GVA (~(gpa_t)0)
40
41 #define LITEVM_MAX_VCPUS 1
42 #define LITEVM_MEMORY_SLOTS 4
43 #define LITEVM_NUM_MMU_PAGES 256
44
45 #define FX_IMAGE_SIZE 512
46 #define FX_IMAGE_ALIGN 16
47 #define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
48
49 #define DE_VECTOR 0
50 #define DF_VECTOR 8
51 #define TS_VECTOR 10
52 #define NP_VECTOR 11
53 #define SS_VECTOR 12
54 #define GP_VECTOR 13
55 #define PF_VECTOR 14
56
57 #define SELECTOR_TI_MASK (1 << 2)
58 #define SELECTOR_RPL_MASK 0x03
59
60 #define IOPL_SHIFT 12
61
62 /*
63  * Address types:
64  *
65  *  gva - guest virtual address
66  *  gpa - guest physical address
67  *  gfn - guest frame number
68  *  hva - host virtual address
69  *  hpa - host physical address
70  *  hfn - host frame number
71  */
72
73 typedef unsigned long gva_t;
74 typedef uint64_t gpa_t;
75 typedef unsigned long gfn_t;
76
77 typedef unsigned long hva_t;
78 typedef uint64_t hpa_t;
79 typedef unsigned long hfn_t;
80
81 struct litevm_mmu_page {
82         LIST_ENTRY(litevm_mmu_page) link;
83         hpa_t page_hpa;
84         unsigned long slot_bitmap;      /* One bit set per slot which has memory
85                                                                  * in this shadow page.
86                                                                  */
87         int global;                                     /* Set if all ptes in this page are global */
88         uint64_t *parent_pte;
89 };
90
91 struct vmcs {
92         uint32_t revision_id;
93         uint32_t abort;
94         char data[0];
95 };
96
97 struct litevm_vcpu;
98
99 /*
100  * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
101  * 32-bit).  The litevm_mmu structure abstracts the details of the current mmu
102  * mode.
103  */
104 struct litevm_mmu {
105         void (*new_cr3) (struct litevm_vcpu * vcpu);
106         int (*page_fault) (struct litevm_vcpu * vcpu, gva_t gva, uint32_t err);
107         void (*inval_page) (struct litevm_vcpu * vcpu, gva_t gva);
108         void (*free) (struct litevm_vcpu * vcpu);
109          gpa_t(*gva_to_gpa) (struct litevm_vcpu * vcpu, gva_t gva);
110         hpa_t root_hpa;
111         int root_level;
112         int shadow_root_level;
113 };
114
115 struct litevm_guest_debug {
116         int enabled;
117         unsigned long bp[4];
118         int singlestep;
119 };
120
121 enum {
122         VCPU_REGS_RAX = 0,
123         VCPU_REGS_RCX = 1,
124         VCPU_REGS_RDX = 2,
125         VCPU_REGS_RBX = 3,
126         VCPU_REGS_RSP = 4,
127         VCPU_REGS_RBP = 5,
128         VCPU_REGS_RSI = 6,
129         VCPU_REGS_RDI = 7,
130 #ifdef __x86_64__
131         VCPU_REGS_R8 = 8,
132         VCPU_REGS_R9 = 9,
133         VCPU_REGS_R10 = 10,
134         VCPU_REGS_R11 = 11,
135         VCPU_REGS_R12 = 12,
136         VCPU_REGS_R13 = 13,
137         VCPU_REGS_R14 = 14,
138         VCPU_REGS_R15 = 15,
139 #endif
140         NR_VCPU_REGS
141 };
142
143 struct litevm_vcpu {
144         struct litevm *litevm;
145         struct vmcs *vmcs;
146         qlock_t mutex;
147         int cpu;
148         int launched;
149         unsigned long irq_summary;      /* bit vector: 1 per word in irq_pending */
150 #define NR_IRQ_WORDS (256 / BITS_PER_LONG)
151         unsigned long irq_pending[NR_IRQ_WORDS];
152         unsigned long regs[NR_VCPU_REGS];       /* for rsp: vcpu_load_rsp_rip() */
153         unsigned long rip;                      /* needs vcpu_load_rsp_rip() */
154
155         unsigned long cr2;
156         unsigned long cr3;
157         unsigned long cr8;
158         uint64_t shadow_efer;
159         uint64_t apic_base;
160         int nmsrs;
161         struct vmx_msr_entry *guest_msrs;
162         struct vmx_msr_entry *host_msrs;
163          LIST_HEAD(free_pages, litevm_mmu_page) link;
164         //struct list_head free_pages;
165         struct litevm_mmu_page page_header_buf[LITEVM_NUM_MMU_PAGES];
166         struct litevm_mmu mmu;
167
168         struct litevm_guest_debug guest_debug;
169
170         char fx_buf[FX_BUF_SIZE];
171         char *host_fx_image;
172         char *guest_fx_image;
173
174         int mmio_needed;
175         int mmio_read_completed;
176         int mmio_is_write;
177         int mmio_size;
178         unsigned char mmio_data[8];
179         gpa_t mmio_phys_addr;
180
181         struct {
182                 int active;
183                 uint8_t save_iopl;
184                 struct {
185                         unsigned long base;
186                         uint32_t limit;
187                         uint32_t ar;
188                 } tr;
189         } rmode;
190 };
191
192 struct litevm_memory_slot {
193         gfn_t base_gfn;
194         unsigned long npages;
195         unsigned long flags;
196         struct page **phys_mem;
197 //#warning "bitmap is u8. "
198         /*unsigned long */ uint8_t *dirty_bitmap;
199 };
200
201 struct litevm {
202         spinlock_t lock;                        /* protects everything except vcpus */
203         int nmemslots;
204         struct litevm_memory_slot memslots[LITEVM_MEMORY_SLOTS];
205          LIST_HEAD(active_mmu_pages, litevm_mmu_page) link;
206         //struct list_head active_mmu_pages;
207         struct litevm_vcpu vcpus[LITEVM_MAX_VCPUS];
208         int memory_config_version;
209         int busy;
210 };
211
212 struct litevm_stat {
213         uint32_t pf_fixed;
214         uint32_t pf_guest;
215         uint32_t tlb_flush;
216         uint32_t invlpg;
217
218         uint32_t exits;
219         uint32_t io_exits;
220         uint32_t mmio_exits;
221         uint32_t signal_exits;
222         uint32_t irq_exits;
223 };
224
225 extern struct litevm_stat litevm_stat;
226
227 #define litevm_printf(litevm, fmt ...) printd(fmt)
228 #define vcpu_printf(vcpu, fmt...) litevm_printf(vcpu->litevm, fmt)
229
230 void litevm_mmu_destroy(struct litevm_vcpu *vcpu);
231 int litevm_mmu_init(struct litevm_vcpu *vcpu);
232
233 int litevm_mmu_reset_context(struct litevm_vcpu *vcpu);
234 void litevm_mmu_slot_remove_write_access(struct litevm *litevm, int slot);
235
236 hpa_t gpa_to_hpa(struct litevm_vcpu *vcpu, gpa_t gpa);
237 #define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
238 #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
239 static inline int is_error_hpa(hpa_t hpa)
240 {
241         return hpa >> HPA_MSB;
242 }
243
244 hpa_t gva_to_hpa(struct litevm_vcpu * vcpu, gva_t gva);
245
246 extern hpa_t bad_page_address;
247
248 static inline struct page *gfn_to_page(struct litevm_memory_slot *slot,
249                                                                            gfn_t gfn)
250 {
251         return slot->phys_mem[gfn - slot->base_gfn];
252 }
253
254 struct litevm_memory_slot *gfn_to_memslot(struct litevm *litevm, gfn_t gfn);
255 void mark_page_dirty(struct litevm *litevm, gfn_t gfn);
256
257 void realmode_lgdt(struct litevm_vcpu *vcpu, uint16_t size,
258                                    unsigned long address);
259 void realmode_lidt(struct litevm_vcpu *vcpu, uint16_t size,
260                                    unsigned long address);
261 void realmode_lmsw(struct litevm_vcpu *vcpu, unsigned long msw,
262                                    unsigned long *rflags);
263
264 unsigned long realmode_get_cr(struct litevm_vcpu *vcpu, int cr);
265 void realmode_set_cr(struct litevm_vcpu *vcpu, int cr, unsigned long value,
266                                          unsigned long *rflags);
267
268 int litevm_read_guest(struct litevm_vcpu *vcpu,
269                                           gva_t addr, unsigned long size, void *dest);
270
271 int litevm_write_guest(struct litevm_vcpu *vcpu,
272                                            gva_t addr, unsigned long size, void *data);
273
274 void vmcs_writel(unsigned long field, unsigned long value);
275 unsigned long vmcs_readl(unsigned long field);
276
277 static inline uint16_t vmcs_read16(unsigned long field)
278 {
279         return vmcs_readl(field);
280 }
281
282 static inline uint32_t vmcs_read32(unsigned long field)
283 {
284         return vmcs_readl(field);
285 }
286
287 static inline uint64_t vmcs_read64(unsigned long field)
288 {
289 #ifdef __x86_64__
290         return vmcs_readl(field);
291 #else
292         return vmcs_readl(field) | ((uint64_t) vmcs_readl(field + 1) << 32);
293 #endif
294 }
295
296 static inline void vmcs_write32(unsigned long field, uint32_t value)
297 {
298         vmcs_writel(field, value);
299 }
300
301 static inline int is_long_mode(void)
302 {
303         return vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_CONTROLS_IA32E_MASK;
304 }
305
306 static inline unsigned long guest_cr4(void)
307 {
308         return (vmcs_readl(CR4_READ_SHADOW) & LITEVM_GUEST_CR4_MASK) |
309                 (vmcs_readl(GUEST_CR4) & ~LITEVM_GUEST_CR4_MASK);
310 }
311
312 static inline int is_pae(void)
313 {
314         return guest_cr4() & CR4_PAE_MASK;
315 }
316
317 static inline int is_pse(void)
318 {
319         return guest_cr4() & CR4_PSE_MASK;
320 }
321
322 static inline unsigned long guest_cr0(void)
323 {
324         return (vmcs_readl(CR0_READ_SHADOW) & LITEVM_GUEST_CR0_MASK) |
325                 (vmcs_readl(GUEST_CR0) & ~LITEVM_GUEST_CR0_MASK);
326 }
327
328 static inline unsigned guest_cpl(void)
329 {
330         return vmcs_read16(GUEST_CS_SELECTOR) & SELECTOR_RPL_MASK;
331 }
332
333 static inline int is_paging(void)
334 {
335         return guest_cr0() & CR0_PG_MASK;
336 }
337
338 static inline int is_page_fault(uint32_t intr_info)
339 {
340         return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
341                                                  INTR_INFO_VALID_MASK)) ==
342                 (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
343 }
344
345 static inline int is_external_interrupt(uint32_t intr_info)
346 {
347         return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
348                 == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
349 }
350
351 static inline void flush_guest_tlb(struct litevm_vcpu *vcpu)
352 {
353         vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3));
354 }
355
356 static inline int memslot_id(struct litevm *litevm,
357                                                          struct litevm_memory_slot *slot)
358 {
359         return slot - litevm->memslots;
360 }
361
362 static inline struct litevm_mmu_page *page_header(hpa_t shadow_page)
363 {
364         struct page *page = ppn2page(shadow_page >> PAGE_SHIFT);
365
366         return (struct litevm_mmu_page *)page->pg_private;
367 }
368
369 #ifdef __x86_64__
370
371 /*
372  * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.  Therefore
373  * we need to allocate shadow page tables in the first 4GB of memory, which
374  * happens to fit the DMA32 zone.
375  */
376 #define GFP_LITEVM_MMU (GFP_KERNEL | __GFP_DMA32)
377
378 #else
379
380 #define GFP_LITEVM_MMU GFP_KERNEL
381
382 #endif
383
384 /* just to get things to build ... include this stuff for now.
385  * at some point, this interface gets nuke to and made more plan 
386  * 9 like.
387  */
388
389 /* for LITEVM_CREATE_MEMORY_REGION */
390 struct litevm_memory_region {
391         uint32_t slot;
392         uint32_t flags;
393         uint64_t guest_phys_addr;
394         uint64_t memory_size;           /* bytes */
395         void *init_data;
396 };
397
398 /* for litevm_memory_region::flags */
399 #define LITEVM_MEM_LOG_DIRTY_PAGES  1UL
400
401 #define LITEVM_EXIT_TYPE_FAIL_ENTRY 1
402 #define LITEVM_EXIT_TYPE_VM_EXIT    2
403
404 enum litevm_exit_reason {
405         LITEVM_EXIT_UNKNOWN,
406         LITEVM_EXIT_EXCEPTION,
407         LITEVM_EXIT_IO,
408         LITEVM_EXIT_CPUID,
409         LITEVM_EXIT_DEBUG,
410         LITEVM_EXIT_HLT,
411         LITEVM_EXIT_MMIO,
412 };
413
414 /* for LITEVM_RUN */
415 struct litevm_run {
416         /* in */
417         uint32_t vcpu;
418         uint32_t emulated;                      /* skip current instruction */
419         uint32_t mmio_completed;        /* mmio request completed */
420
421         /* out */
422         uint32_t exit_type;
423         uint32_t exit_reason;
424         uint32_t instruction_length;
425         union {
426                 /* LITEVM_EXIT_UNKNOWN */
427                 struct {
428                         uint32_t hardware_exit_reason;
429                 } hw;
430                 /* LITEVM_EXIT_EXCEPTION */
431                 struct {
432                         uint32_t exception;
433                         uint32_t error_code;
434                 } ex;
435                 /* LITEVM_EXIT_IO */
436                 struct {
437 #define LITEVM_EXIT_IO_IN  0
438 #define LITEVM_EXIT_IO_OUT 1
439                         uint8_t direction;
440                         uint8_t size;           /* bytes */
441                         uint8_t string;
442                         uint8_t string_down;
443                         uint8_t rep;
444                         uint8_t pad;
445                         uint16_t port;
446                         uint64_t count;
447                         union {
448                                 uint64_t address;
449                                 uint32_t value;
450                         };
451                 } io;
452                 struct {
453                 } debug;
454                 /* LITEVM_EXIT_MMIO */
455                 struct {
456                         uint64_t phys_addr;
457                         uint8_t data[8];
458                         uint32_t len;
459                         uint8_t is_write;
460                 } mmio;
461         };
462 };
463
464 /* for LITEVM_GET_REGS and LITEVM_SET_REGS */
465 struct litevm_regs {
466         /* in */
467         uint32_t vcpu;
468         uint32_t padding;
469
470         /* out (LITEVM_GET_REGS) / in (LITEVM_SET_REGS) */
471         uint64_t rax, rbx, rcx, rdx;
472         uint64_t rsi, rdi, rsp, rbp;
473         uint64_t r8, r9, r10, r11;
474         uint64_t r12, r13, r14, r15;
475         uint64_t rip, rflags;
476 };
477
478 struct litevm_segment {
479         uint64_t base;
480         uint32_t limit;
481         uint16_t selector;
482         uint8_t type;
483         uint8_t present, dpl, db, s, l, g, avl;
484         uint8_t unusable;
485         uint8_t padding;
486 };
487
488 struct litevm_dtable {
489         uint64_t base;
490         uint16_t limit;
491         uint16_t padding[3];
492 };
493
494 /* for LITEVM_GET_SREGS and LITEVM_SET_SREGS */
495 struct litevm_sregs {
496         /* in */
497         uint32_t vcpu;
498         uint32_t padding;
499
500         /* out (LITEVM_GET_SREGS) / in (LITEVM_SET_SREGS) */
501         struct litevm_segment cs, ds, es, fs, gs, ss;
502         struct litevm_segment tr, ldt;
503         struct litevm_dtable gdt, idt;
504         uint64_t cr0, cr2, cr3, cr4, cr8;
505         uint64_t efer;
506         uint64_t apic_base;
507
508         /* out (LITEVM_GET_SREGS) */
509         uint32_t pending_int;
510         uint32_t padding2;
511 };
512
513 /* for LITEVM_TRANSLATE */
514 struct litevm_translation {
515         /* in */
516         uint64_t linear_address;
517         uint32_t vcpu;
518         uint32_t padding;
519
520         /* out */
521         uint64_t physical_address;
522         uint8_t valid;
523         uint8_t writeable;
524         uint8_t usermode;
525 };
526
527 /* for LITEVM_INTERRUPT */
528 struct litevm_interrupt {
529         /* in */
530         uint32_t vcpu;
531         uint32_t irq;
532 };
533
534 struct litevm_breakpoint {
535         uint32_t enabled;
536         uint32_t padding;
537         uint64_t address;
538 };
539
540 /* for LITEVM_DEBUG_GUEST */
541 struct litevm_debug_guest {
542         /* int */
543         uint32_t vcpu;
544         uint32_t enabled;
545         struct litevm_breakpoint breakpoints[4];
546         uint32_t singlestep;
547 };
548
549 /* for LITEVM_GET_DIRTY_LOG */
550 struct litevm_dirty_log {
551         uint32_t slot;
552         uint32_t padding;
553         union {
554                 void *dirty_bitmap;             /* one bit per page */
555                 uint64_t paddingw;
556         };
557 };
558
559 enum {
560         LITEVM_RUN = 1,
561         LITEVM_GET_REGS,
562         LITEVM_SET_REGS,
563         LITEVM_GET_SREGS,
564         LITEVM_SET_SREGS,
565         LITEVM_TRANSLATE,
566         LITEVM_INTERRUPT,
567         LITEVM_DEBUG_GUEST,
568         LITEVM_SET_MEMORY_REGION,
569         LITEVM_CREATE_VCPU,
570         LITEVM_GET_DIRTY_LOG,
571 };
572 #endif