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