Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added shadow page handling, IO and MSR bitmap allocation, and started
[palacios.git] / palacios / src / palacios / vmx.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
12  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Peter Dinda <pdinda@northwestern.edu>
16  *         Jack Lange <jarusl@cs.northwestern.edu>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22
23 #include <palacios/vmx.h>
24 #include <palacios/vmcs.h>
25 #include <palacios/vmm.h>
26 #include <palacios/vmx_lowlevel.h>
27 #include <palacios/vmm_lowlevel.h>
28 #include <palacios/vmm_config.h>
29 #include <palacios/vmm_ctrl_regs.h>
30 #include <palacios/vm_guest_mem.h>
31 #include <palacios/vmm_direct_paging.h>
32 #include <palacios/vmx_io.h>
33 #include <palacios/vmx_msr.h>
34
35 static addr_t vmxon_ptr_phys;
36 extern int v3_vmx_exit_handler();
37 extern int v3_vmx_vmlaunch(struct v3_gprs * vm_regs, struct guest_info * info);
38
39 static int inline check_vmcs_write(vmcs_field_t field, addr_t val)
40 {
41     int ret = 0;
42     ret = vmcs_write(field,val);
43
44     if (ret != VMX_SUCCESS) {
45         PrintError("VMWRITE error on %s!: %d\n", v3_vmcs_field_to_str(field), ret);
46         return 1;
47     }
48
49     return 0;
50 }
51
52 static void inline translate_segment_access(struct v3_segment * v3_seg,  
53                                             struct vmcs_segment_access * access)
54 {
55     access->type = v3_seg->type;
56     access->desc_type = v3_seg->system;
57     access->dpl = v3_seg->dpl;
58     access->present = v3_seg->present;
59     access->avail = v3_seg->avail;
60     access->long_mode = v3_seg->long_mode;
61     access->db = v3_seg->db;
62     access->granularity = v3_seg->granularity;
63 }
64
65 static int update_vmcs_ctrl_fields(struct guest_info * info) {
66     int vmx_ret = 0;
67     struct vmx_data * arch_data = (struct vmx_data *)(info->vmm_data);
68
69     vmx_ret |= check_vmcs_write(VMCS_PIN_CTRLS, arch_data->pinbased_ctrls);
70     vmx_ret |= check_vmcs_write(VMCS_PROC_CTRLS, arch_data->pri_procbased_ctrls);
71
72     if(arch_data->pri_procbased_ctrls & ACTIVE_SEC_CTRLS) {
73         vmx_ret |= check_vmcs_write(VMCS_SEC_PROC_CTRLS, arch_data->sec_procbased_ctrls);
74     }
75
76     vmx_ret |= check_vmcs_write(VMCS_EXIT_CTRLS, arch_data->exit_ctrls);
77     vmx_ret |= check_vmcs_write(VMCS_ENTRY_CTRLS, arch_data->entry_ctrls);
78     vmx_ret |= check_vmcs_write(VMCS_EXCP_BITMAP, arch_data->excp_bitmap);
79
80     return vmx_ret;
81 }
82
83 static int update_vmcs_host_state(struct guest_info * info) {
84     int vmx_ret = 0;
85     addr_t tmp;
86     struct vmx_data * arch_data = (struct vmx_data *)(info->vmm_data);
87     struct v3_msr tmp_msr;
88
89     __asm__ __volatile__ ( "movq    %%cr0, %0; "                
90                            : "=q"(tmp)
91                            :
92     );
93     vmx_ret |= check_vmcs_write(VMCS_HOST_CR0, tmp);
94
95
96     __asm__ __volatile__ ( "movq %%cr3, %0; "           
97                            : "=q"(tmp)
98                            :
99     );
100     vmx_ret |= check_vmcs_write(VMCS_HOST_CR3, tmp);
101
102
103     __asm__ __volatile__ ( "movq %%cr4, %0; "           
104                            : "=q"(tmp)
105                            :
106     );
107     vmx_ret |= check_vmcs_write(VMCS_HOST_CR4, tmp);
108
109
110
111     vmx_ret |= check_vmcs_write(VMCS_HOST_GDTR_BASE, arch_data->host_state.gdtr.base);
112     vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, arch_data->host_state.idtr.base);
113     vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, arch_data->host_state.tr.base);
114
115 #define FS_BASE_MSR 0xc0000100
116 #define GS_BASE_MSR 0xc0000101
117
118     // FS.BASE MSR
119     v3_get_msr(FS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
120     vmx_ret |= check_vmcs_write(VMCS_HOST_FS_BASE, tmp_msr.value);    
121
122     // GS.BASE MSR
123     v3_get_msr(GS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
124     vmx_ret |= check_vmcs_write(VMCS_HOST_GS_BASE, tmp_msr.value);    
125
126
127
128     __asm__ __volatile__ ( "movq %%cs, %0; "            
129                            : "=q"(tmp)
130                            :
131     );
132     vmx_ret |= check_vmcs_write(VMCS_HOST_CS_SELECTOR, tmp);
133
134     __asm__ __volatile__ ( "movq %%ss, %0; "            
135                            : "=q"(tmp)
136                            :
137     );
138     vmx_ret |= check_vmcs_write(VMCS_HOST_SS_SELECTOR, tmp);
139
140     __asm__ __volatile__ ( "movq %%ds, %0; "            
141                            : "=q"(tmp)
142                            :
143     );
144     vmx_ret |= check_vmcs_write(VMCS_HOST_DS_SELECTOR, tmp);
145
146     __asm__ __volatile__ ( "movq %%es, %0; "            
147                            : "=q"(tmp)
148                            :
149     );
150     vmx_ret |= check_vmcs_write(VMCS_HOST_ES_SELECTOR, tmp);
151
152     __asm__ __volatile__ ( "movq %%fs, %0; "            
153                            : "=q"(tmp)
154                            :
155     );
156     vmx_ret |= check_vmcs_write(VMCS_HOST_FS_SELECTOR, tmp);
157
158     __asm__ __volatile__ ( "movq %%gs, %0; "            
159                            : "=q"(tmp)
160                            :
161     );
162     vmx_ret |= check_vmcs_write(VMCS_HOST_GS_SELECTOR, tmp);
163
164     vmx_ret |= check_vmcs_write(VMCS_HOST_TR_SELECTOR, arch_data->host_state.tr.selector);
165
166
167 #define SYSENTER_CS_MSR 0x00000174
168 #define SYSENTER_ESP_MSR 0x00000175
169 #define SYSENTER_EIP_MSR 0x00000176
170
171    // SYSENTER CS MSR
172     v3_get_msr(SYSENTER_CS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
173     vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_CS, tmp_msr.lo);
174
175     // SYSENTER_ESP MSR
176     v3_get_msr(SYSENTER_ESP_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
177     vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_ESP, tmp_msr.value);
178
179     // SYSENTER_EIP MSR
180     v3_get_msr(SYSENTER_EIP_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
181     vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_EIP, tmp_msr.value);
182
183     return vmx_ret;
184 }
185
186
187 static int inline update_vmcs_guest_state(struct guest_info * info)
188 {
189     struct v3_msr tmp_msr;
190     int vmx_ret = 0;
191
192     vmx_ret |= check_vmcs_write(VMCS_GUEST_RIP, info->rip);
193     vmx_ret |= check_vmcs_write(VMCS_GUEST_RSP, info->vm_regs.rsp);
194     
195
196     vmx_ret |= check_vmcs_write(VMCS_GUEST_CR0, info->ctrl_regs.cr0);
197     vmx_ret |= check_vmcs_write(VMCS_GUEST_CR3, info->ctrl_regs.cr3);
198     vmx_ret |= check_vmcs_write(VMCS_GUEST_CR4, info->ctrl_regs.cr4);
199
200     vmx_ret |= check_vmcs_write(VMCS_GUEST_RFLAGS, info->ctrl_regs.rflags);
201 #define DEBUGCTL_MSR 0x1d9
202
203     v3_get_msr(DEBUGCTL_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
204     vmx_ret |= check_vmcs_write(VMCS_GUEST_DBG_CTL, tmp_msr.value);
205
206     vmx_ret |= check_vmcs_write(VMCS_GUEST_DR7, 0x400);
207
208     vmx_ret |= check_vmcs_write(VMCS_LINK_PTR, 0xffffffffffffffff);
209
210
211     /*** Write VMCS Segments ***/
212     struct vmcs_segment_access access;
213
214     memset(&access, 0, sizeof(access));
215
216     /* CS Segment */
217     translate_segment_access(&(info->segments.cs), &access);
218
219     vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_BASE, info->segments.cs.base);
220     vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_SELECTOR, info->segments.cs.selector);
221     vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_LIMIT, info->segments.cs.limit);
222     vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_ACCESS, access.value);
223
224     /* SS Segment */
225     translate_segment_access(&(info->segments.ss), &access);
226
227     vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_BASE, info->segments.ss.base);
228     vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_SELECTOR, info->segments.ss.selector);
229     vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_LIMIT, info->segments.ss.limit);
230     vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_ACCESS, access.value);
231
232     /* DS Segment */
233     translate_segment_access(&(info->segments.ds), &access);
234
235     vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_BASE, info->segments.ds.base);
236     vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_SELECTOR, info->segments.ds.selector);
237     vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_LIMIT, info->segments.ds.limit);
238     vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_ACCESS, access.value);
239
240
241     /* ES Segment */
242     translate_segment_access(&(info->segments.es), &access);
243
244     vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_BASE, info->segments.es.base);
245     vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_SELECTOR, info->segments.es.selector);
246     vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_LIMIT, info->segments.es.limit);
247     vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_ACCESS, access.value);
248
249     /* FS Segment */
250     translate_segment_access(&(info->segments.fs), &access);
251
252     vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_BASE, info->segments.fs.base);
253     vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_SELECTOR, info->segments.fs.selector);
254     vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_LIMIT, info->segments.fs.limit);
255     vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_ACCESS, access.value);
256
257     /* GS Segment */
258     translate_segment_access(&(info->segments.gs), &access);
259
260     vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_BASE, info->segments.gs.base);
261     vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_SELECTOR, info->segments.gs.selector);
262     vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_LIMIT, info->segments.gs.limit);
263     vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_ACCESS, access.value);
264
265     /* LDTR segment */
266     translate_segment_access(&(info->segments.ldtr), &access);
267
268     vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_BASE, info->segments.ldtr.base);
269     vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_SELECTOR, info->segments.ldtr.selector);
270     vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_LIMIT, info->segments.ldtr.limit);
271     vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_ACCESS, access.value);
272
273     /* TR Segment */
274     translate_segment_access(&(info->segments.tr), &access);
275
276     vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_BASE, info->segments.tr.base);
277     vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_SELECTOR, info->segments.tr.selector);
278     vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_LIMIT, info->segments.tr.limit);
279     vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_ACCESS, access.value);
280
281     /* GDTR Segment */
282
283     vmx_ret |= check_vmcs_write(VMCS_GUEST_GDTR_BASE, info->segments.gdtr.base);
284     vmx_ret |= check_vmcs_write(VMCS_GUEST_GDTR_LIMIT, info->segments.gdtr.limit);
285
286     /* IDTR Segment*/
287     vmx_ret |= check_vmcs_write(VMCS_GUEST_IDTR_BASE, info->segments.idtr.base);
288     vmx_ret |= check_vmcs_write(VMCS_GUEST_IDTR_LIMIT, info->segments.idtr.limit);
289
290     return vmx_ret;
291
292 }
293
294
295
296
297 #if 0
298 // For the 32 bit reserved bit fields 
299 // MB1s are in the low 32 bits, MBZs are in the high 32 bits of the MSR
300 static uint32_t sanitize_bits1(uint32_t msr_num, uint32_t val) {
301     v3_msr_t mask_msr;
302
303     PrintDebug("sanitize_bits1 (MSR:%x)\n", msr_num);
304
305     v3_get_msr(msr_num, &mask_msr.hi, &mask_msr.lo);
306
307     PrintDebug("MSR %x = %x : %x \n", msr_num, mask_msr.hi, mask_msr.lo);
308
309     val |= mask_msr.lo;
310     val |= mask_msr.hi;
311   
312     return val;
313 }
314
315
316
317 static addr_t sanitize_bits2(uint32_t msr_num0, uint32_t msr_num1, addr_t val) {
318     v3_msr_t msr0, msr1;
319     addr_t msr0_val, msr1_val;
320
321     PrintDebug("sanitize_bits2 (MSR0=%x, MSR1=%x)\n", msr_num0, msr_num1);
322
323     v3_get_msr(msr_num0, &msr0.hi, &msr0.lo);
324     v3_get_msr(msr_num1, &msr1.hi, &msr1.lo);
325   
326     // This generates a mask that is the natural bit width of the CPU
327     msr0_val = msr0.value;
328     msr1_val = msr1.value;
329
330     PrintDebug("MSR %x = %p, %x = %p \n", msr_num0, (void*)msr0_val, msr_num1, (void*)msr1_val);
331
332     val |= msr0_val;
333     val |= msr1_val;
334
335     return val;
336 }
337
338
339
340 #endif
341
342
343 static addr_t allocate_vmcs() 
344 {
345     reg_ex_t msr;
346     PrintDebug("Allocating page\n");
347     struct vmcs_data * vmcs_page = (struct vmcs_data *)V3_VAddr(V3_AllocPages(1));
348
349
350     memset(vmcs_page, 0, 4096);
351
352     v3_get_msr(VMX_BASIC_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
353     
354     vmcs_page->revision = ((struct vmx_basic_msr*)&msr)->revision;
355     PrintDebug("VMX Revision: 0x%x\n",vmcs_page->revision);
356
357     return (addr_t)V3_PAddr((void *)vmcs_page);
358 }
359
360 #if 0
361 static void setup_v8086_mode_for_boot(struct guest_info * vm_info)
362 {
363
364     ((struct vmx_data *)vm_info->vmm_data)->state = VMXASSIST_V8086_BIOS;
365     struct rflags * flags = (struct rflags *)&(vm_info->ctrl_regs.rflags);
366     flags->rsvd1 = 1;
367     flags->vm = 1;
368     flags->iopl = 3;
369
370 #define GUEST_CR0_MASK 0x80000021
371 #define GUEST_CR4_MASK 0x00002000
372     vm_info->ctrl_regs.cr0 = GUEST_CR0_MASK;
373     vm_info->ctrl_regs.cr4 = GUEST_CR4_MASK;
374    
375     vm_info->rip = 0xd0000;
376     vm_info->vm_regs.rsp = 0x80000;
377
378     vm_info->segments.cs.selector = 0xf000;
379     vm_info->segments.cs.base = 0xf000 << 4;
380     vm_info->segments.cs.limit = 0xffff;
381     vm_info->segments.cs.type = 3;
382     vm_info->segments.cs.system = 1;
383     vm_info->segments.cs.dpl = 3;
384     vm_info->segments.cs.present = 1;
385     vm_info->segments.cs.granularity = 0;
386
387     int i = 0;
388     struct v3_segment * seg_ptr = (struct v3_segment *)&(vm_info->segments);
389
390     /* Set values for selectors ds through ss */
391     for(i = 1; i < 6 ; i++) {
392         seg_ptr[i].selector = 0x0000;
393         seg_ptr[i].base = 0x00000;
394         seg_ptr[i].limit = 0xffff;
395            }
396
397     for(i = 6; i < 10; i++) {
398         seg_ptr[i].base = 0x0;
399         seg_ptr[i].limit = 0xffff;
400     }
401
402     vm_info->segments.ldtr.selector = 0x0;
403     vm_info->segments.ldtr.type = 2;
404     vm_info->segments.ldtr.system = 0;
405     vm_info->segments.ldtr.present = 1;
406     vm_info->segments.ldtr.granularity = 0;
407
408     vm_info->segments.tr.selector = 0x0;
409     vm_info->segments.tr.type = 3;
410     vm_info->segments.tr.system = 0;
411     vm_info->segments.tr.present = 1;
412     vm_info->segments.tr.granularity = 0;
413 }
414 #endif
415
416 #if 0
417 static int init_vmcs_bios(struct guest_info * vm_info) 
418 {
419 #if 0
420
421     setup_v8086_mode_for_boot(vm_info);
422
423
424     // Setup guest state 
425     // TODO: This is not 32-bit safe!
426     vmx_ret |= check_vmcs_write(VMCS_GUEST_RIP, vm_info->rip);
427     vmx_ret |= check_vmcs_write(VMCS_GUEST_RSP, vm_info->vm_regs.rsp);
428     
429
430     vmx_ret |= check_vmcs_write(VMCS_GUEST_CR0, vm_info->ctrl_regs.cr0);
431     vmx_ret |= check_vmcs_write(VMCS_GUEST_CR4, vm_info->ctrl_regs.cr4);
432
433     vmx_ret |= vmcs_write_guest_segments(vm_info);
434
435     vmx_ret |= check_vmcs_write(VMCS_GUEST_RFLAGS, vm_info->ctrl_regs.rflags);
436 #define DEBUGCTL_MSR 0x1d9
437
438     v3_get_msr(DEBUGCTL_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
439     vmx_ret |= check_vmcs_write(VMCS_GUEST_DBG_CTL, tmp_msr.value);
440
441     vmx_ret |= check_vmcs_write(VMCS_GUEST_DR7, 0x400);
442
443     vmx_ret |= check_vmcs_write(VMCS_LINK_PTR, 0xffffffffffffffff);
444
445     if (vmx_ret != 0) {
446         PrintError("Could not initialize VMCS segments\n");
447         return -1;
448     }
449
450 #endif
451     return 0;
452 }
453 #endif
454
455 static int init_vmx_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
456     v3_pre_config_guest(info, config_ptr);
457
458     struct vmx_data * vmx_data = NULL;
459
460     vmx_data = (struct vmx_data *)V3_Malloc(sizeof(struct vmx_data));
461
462     PrintDebug("vmx_data pointer: %p\n", (void *)vmx_data);
463
464     PrintDebug("Allocating VMCS\n");
465     vmx_data->vmcs_ptr_phys = allocate_vmcs();
466
467     PrintDebug("VMCS pointer: %p\n", (void *)(vmx_data->vmcs_ptr_phys));
468
469     info->vmm_data = vmx_data;
470
471     PrintDebug("Initializing VMCS (addr=%p)\n", info->vmm_data);
472     
473     // TODO: Fix vmcs fields so they're 32-bit
474     int vmx_ret = 0;
475
476     PrintDebug("Clearing VMCS: %p\n",(void*)vmx_data->vmcs_ptr_phys);
477     vmx_ret = vmcs_clear(vmx_data->vmcs_ptr_phys);
478
479     if (vmx_ret != VMX_SUCCESS) {
480         PrintError("VMCLEAR failed\n");
481         return -1;
482     }
483
484     PrintDebug("Loading VMCS\n");
485     vmx_ret = vmcs_load(vmx_data->vmcs_ptr_phys);
486
487     if (vmx_ret != VMX_SUCCESS) {
488         PrintError("VMPTRLD failed\n");
489         return -1;
490     }
491
492
493
494     /******* Setup Host State **********/
495
496     /* Cache GDTR, IDTR, and TR in host struct */
497     addr_t gdtr_base;
498     struct {
499         uint16_t selector;
500         addr_t   base;
501     } __attribute__((packed)) tmp_seg;
502     
503
504     __asm__ __volatile__(
505                          "sgdt (%0);"
506                          :
507                          : "q"(&tmp_seg)
508                          : "memory"
509                          );
510     gdtr_base = tmp_seg.base;
511     vmx_data->host_state.gdtr.base = gdtr_base;
512
513     __asm__ __volatile__(
514                          "sidt (%0);"
515                          :
516                          : "q"(&tmp_seg)
517                          : "memory"
518                          );
519     vmx_data->host_state.idtr.base = tmp_seg.base;
520
521     __asm__ __volatile__(
522                          "str (%0);"
523                          :
524                          : "q"(&tmp_seg)
525                          : "memory"
526                          );
527     vmx_data->host_state.tr.selector = tmp_seg.selector;
528
529     /* The GDTR *index* is bits 3-15 of the selector. */
530     struct tss_descriptor * desc = (struct tss_descriptor *)
531                         (gdtr_base + 8*(tmp_seg.selector>>3));
532
533     tmp_seg.base = (
534                     (desc->base1) |
535                     (desc->base2 << 16) |
536                     (desc->base3 << 24) |
537 #ifdef __V3_64BIT__
538                     ((uint64_t)desc->base4 << 32)
539 #else 
540                     (0)
541 #endif
542                 );
543
544     vmx_data->host_state.tr.base = tmp_seg.base;
545
546   
547
548     /********** Setup and VMX Control Fields from MSR ***********/
549     struct v3_msr tmp_msr;
550
551     v3_get_msr(VMX_PINBASED_CTLS_MSR,&(tmp_msr.hi),&(tmp_msr.lo));
552     /* Add NMI exiting */
553     vmx_data->pinbased_ctrls =  tmp_msr.lo | NMI_EXIT;
554
555     v3_get_msr(VMX_PROCBASED_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
556     vmx_data->pri_procbased_ctrls = tmp_msr.lo;
557
558     v3_get_msr(VMX_EXIT_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
559     vmx_data->exit_ctrls = tmp_msr.lo | HOST_ADDR_SPACE_SIZE;
560
561     v3_get_msr(VMX_ENTRY_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
562     vmx_data->entry_ctrls = tmp_msr.lo;
563
564     vmx_data->excp_bitmap = 0xffffffff;
565
566
567
568     /******* Setup VMXAssist guest state ***********/
569
570     info->rip = 0xd0000;
571     info->vm_regs.rsp = 0x80000;
572
573     struct rflags * flags = (struct rflags *)&(info->ctrl_regs.rflags);
574     flags->rsvd1 = 1;
575
576     /* Print Control MSRs */
577     v3_get_msr(VMX_CR0_FIXED0_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
578     PrintDebug("CR0 MSR: %p\n", (void*)tmp_msr.value);
579     v3_get_msr(VMX_CR4_FIXED0_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
580     PrintDebug("CR4 MSR: %p\n", (void*)tmp_msr.value);
581
582
583 #define GUEST_CR0 0x80000031
584 #define GUEST_CR4 0x00002000
585     info->ctrl_regs.cr0 = GUEST_CR0;
586     info->ctrl_regs.cr4 = GUEST_CR4;
587    
588     /* Setup paging */
589     if(info->shdw_pg_mode == SHADOW_PAGING) {
590         PrintDebug("Creating initial shadow page table\n");
591
592         if(v3_init_passthrough_pts(info) == -1) {
593             PrintError("Could not initialize passthrough page tables\n");
594             return -1;
595         }
596
597         info->shdw_pg_state.guest_cr0 = 0x10LL;
598         PrintDebug("Created\n");
599
600         vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, 0xffffffffffffffffLL);
601         vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, 0xffffffffffffffffLL);
602
603         info->ctrl_regs.cr3 = info->direct_map_pt;
604
605         /* Add unconditional I/O and CR exits */
606         vmx_data->pri_procbased_ctrls |= UNCOND_IO_EXIT  |
607                                          CR3_LOAD_EXIT   |
608                                          CR3_STORE_EXIT;  
609  
610     }
611
612     struct v3_segment * seg_reg = (struct v3_segment *)&(info->segments);
613
614     int i;
615     for(i=0; i < 10; i++)
616     {
617         seg_reg[i].selector = 3<<3;
618         seg_reg[i].limit = 0xffff;
619         seg_reg[i].base = 0x0;
620     }
621     info->segments.cs.selector = 2<<3;
622
623     /* Set only the segment registers */
624     for(i=0; i < 6; i++) {
625         seg_reg[i].limit = 0xfffff;
626         seg_reg[i].granularity = 1;
627         seg_reg[i].type = 3;
628         seg_reg[i].system = 1;
629         seg_reg[i].dpl = 0;
630         seg_reg[i].present = 1;
631         seg_reg[i].db = 1;
632     }
633     info->segments.cs.type = 0xb;
634
635     info->segments.ldtr.selector = 0x20;
636     info->segments.ldtr.type = 2;
637     info->segments.ldtr.system = 0;
638     info->segments.ldtr.present = 1;
639     info->segments.ldtr.granularity = 0;
640     
641     /* Setup IO map */
642     (void) v3_init_vmx_io_map(info);
643     (void) v3_init_vmx_msr_map(info);
644
645     /************* Map in GDT and vmxassist *************/
646
647     uint64_t  gdt[] __attribute__ ((aligned(32))) = {
648         0x0000000000000000ULL,          /* 0x00: reserved */
649         0x0000830000000000ULL,          /* 0x08: 32-bit TSS */
650         //      0x0000890000000000ULL,          /* 0x08: 32-bit TSS */
651         0x00CF9b000000FFFFULL,          /* 0x10: CS 32-bit */
652         0x00CF93000000FFFFULL,          /* 0x18: DS 32-bit */
653         0x000082000000FFFFULL,          /* 0x20: LDTR 32-bit */
654     };
655
656 #define VMXASSIST_GDT   0x10000
657     addr_t vmxassist_gdt = 0;
658     if(guest_pa_to_host_va(info, VMXASSIST_GDT, &vmxassist_gdt) == -1) {
659         PrintError("Could not find VMXASSIST GDT destination\n");
660         return -1;
661     }
662     memcpy((void*)vmxassist_gdt, gdt, sizeof(uint64_t) * 5);
663         
664     info->segments.gdtr.base = VMXASSIST_GDT;
665
666 #define VMXASSIST_TSS   0x40000
667     addr_t vmxassist_tss = VMXASSIST_TSS;
668     gdt[0x08 / sizeof(gdt[0])] |=
669         ((vmxassist_tss & 0xFF000000) << (56-24)) |
670         ((vmxassist_tss & 0x00FF0000) << (32-16)) |
671         ((vmxassist_tss & 0x0000FFFF) << (16)) |
672         (8392 - 1);
673
674     info->segments.tr.selector = 0x08;
675     info->segments.tr.base = vmxassist_tss;
676
677     // info->segments.tr.type = 0x9; 
678     info->segments.tr.type = 0x3;
679     info->segments.tr.system = 0;
680     info->segments.tr.present = 1;
681     info->segments.tr.granularity = 0;
682
683  
684 #define VMXASSIST_START 0x000d0000
685     extern uint8_t vmxassist_start[];
686     extern uint8_t vmxassist_end[];
687
688     addr_t vmxassist_dst = 0;
689     if(guest_pa_to_host_va(info, VMXASSIST_START, &vmxassist_dst) == -1) {
690         PrintError("Could not find VMXASSIST destination\n");
691         return -1;
692     }
693     memcpy((void*)vmxassist_dst, vmxassist_start, vmxassist_end-vmxassist_start);
694     
695     /*** Write all the info to the VMCS ***/
696     if(update_vmcs_ctrl_fields(info)) {
697         PrintError("Could not write control fields!\n");
698         return -1;
699     }
700     
701     if(update_vmcs_host_state(info)) {
702         PrintError("Could not write host state\n");
703         return -1;
704     }
705
706
707     if(update_vmcs_guest_state(info) != VMX_SUCCESS) {
708         PrintError("Writing guest state failed!\n");
709         return -1;
710     }
711
712     v3_print_vmcs();
713
714
715     v3_post_config_guest(info, config_ptr);
716
717     return 0;
718 }
719
720
721 static int start_vmx_guest(struct guest_info* info) {
722     uint32_t error = 0;
723     int ret = 0;
724
725     PrintDebug("Attempting VMLAUNCH\n");
726
727     ret = v3_vmx_vmlaunch(&(info->vm_regs), info);
728     if (ret != VMX_SUCCESS) {
729         vmcs_read(VMCS_INSTR_ERR, &error);
730         PrintError("VMLAUNCH failed: %d\n", error);
731
732         v3_print_vmcs();
733
734     }
735     PrintDebug("Returned from VMLAUNCH ret=%d(0x%x)\n", ret, ret);
736
737     return -1;
738 }
739
740
741 int v3_is_vmx_capable() {
742     v3_msr_t feature_msr;
743     addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
744
745     v3_cpuid(0x1, &eax, &ebx, &ecx, &edx);
746
747     PrintDebug("ECX: %p\n", (void*)ecx);
748
749     if (ecx & CPUID_1_ECX_VTXFLAG) {
750         v3_get_msr(VMX_FEATURE_CONTROL_MSR, &(feature_msr.hi), &(feature_msr.lo));
751         
752         PrintTrace("MSRREGlow: 0x%.8x\n", feature_msr.lo);
753
754         if ((feature_msr.lo & FEATURE_CONTROL_VALID) != FEATURE_CONTROL_VALID) {
755             PrintDebug("VMX is locked -- enable in the BIOS\n");
756             return 0;
757         }
758
759     } else {
760         PrintDebug("VMX not supported on this cpu\n");
761         return 0;
762     }
763
764     return 1;
765 }
766
767 static int has_vmx_nested_paging() {
768     return 0;
769 }
770
771
772
773 void v3_init_vmx(struct v3_ctrl_ops * vm_ops) {
774     extern v3_cpu_arch_t v3_cpu_type;
775
776     struct v3_msr tmp_msr;
777     uint64_t ret=0;
778
779     v3_get_msr(VMX_CR4_FIXED0_MSR,&(tmp_msr.hi),&(tmp_msr.lo));
780     
781     __asm__ __volatile__ (
782                           "movq %%cr4, %%rbx;"
783                           "orq  $0x00002000, %%rbx;"
784                           "movq %%rbx, %0;"
785                           : "=m"(ret) 
786                           :
787                           : "%rbx"
788                           );
789
790     if((~ret & tmp_msr.value) == 0) {
791         __asm__ __volatile__ (
792                               "movq %0, %%cr4;"
793                               :
794                               : "q"(ret)
795                               );
796     } else {
797         PrintError("Invalid CR4 Settings!\n");
798         return;
799     }
800       __asm__ __volatile__ (
801                             "movq %%cr0, %%rbx; "
802                             "orq  $0x00000020,%%rbx; "
803                             "movq %%rbx, %%cr0;"
804                             :
805                             :
806                             : "%rbx"
807                             );
808       //
809     // Should check and return Error here.... 
810
811
812     // Setup VMXON Region
813     vmxon_ptr_phys = allocate_vmcs();
814     PrintDebug("VMXON pointer: 0x%p\n", (void*)vmxon_ptr_phys);
815
816     if (v3_enable_vmx(vmxon_ptr_phys) == VMX_SUCCESS) {
817         PrintDebug("VMX Enabled\n");
818     } else {
819         PrintError("VMX initialization failure\n");
820         return;
821     }
822         
823
824     if (has_vmx_nested_paging() == 1) {
825         v3_cpu_type = V3_VMX_EPT_CPU;
826     } else {
827         v3_cpu_type = V3_VMX_CPU;
828     }
829
830     // Setup the VMX specific vmm operations
831     vm_ops->init_guest = &init_vmx_guest;
832     vm_ops->start_guest = &start_vmx_guest;
833     vm_ops->has_nested_paging = &has_vmx_nested_paging;
834
835 }
836