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.


some fixes
[palacios.git] / palacios / src / palacios / svm.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, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21
22
23
24 #include <palacios/svm.h>
25 #include <palacios/vmm.h>
26
27 #include <palacios/vmcb.h>
28 #include <palacios/vmm_mem.h>
29 #include <palacios/vmm_paging.h>
30 #include <palacios/svm_handler.h>
31
32 #include <palacios/vmm_debug.h>
33 #include <palacios/vm_guest_mem.h>
34
35 #include <palacios/vmm_decoder.h>
36 #include <palacios/vmm_string.h>
37 #include <palacios/vmm_lowlevel.h>
38 #include <palacios/svm_msr.h>
39
40 #include <palacios/vmm_rbtree.h>
41
42 #include <palacios/vmm_profiler.h>
43
44
45 extern void v3_stgi();
46 extern void v3_clgi();
47 extern int v3_svm_launch(vmcb_t * vmcb, struct v3_gprs * vm_regs);
48
49
50
51
52 static vmcb_t * Allocate_VMCB() {
53   vmcb_t * vmcb_page = (vmcb_t *)V3_VAddr(V3_AllocPages(1));
54
55   memset(vmcb_page, 0, 4096);
56
57   return vmcb_page;
58 }
59
60
61
62 #include <palacios/vmm_ctrl_regs.h>
63
64 static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
65   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
66   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
67   uint_t i;
68
69
70   guest_state->rsp = vm_info->vm_regs.rsp;
71   // guest_state->rip = vm_info->rip;
72   guest_state->rip = 0xfff0;
73
74   guest_state->cpl = 0;
75
76   //ctrl_area->instrs.instrs.CR0 = 1;
77   ctrl_area->cr_reads.cr0 = 1;
78   ctrl_area->cr_writes.cr0 = 1;
79   //ctrl_area->cr_reads.cr4 = 1;
80   ctrl_area->cr_writes.cr4 = 1;
81
82
83   /* Set up the efer to enable 64 bit page tables */
84   /*
85   {
86     struct efer_64 * efer = (struct efer_64 *)&(guest_state->efer);
87     struct cr4_32 * cr4 = (struct cr4_32 *)&(guest_state->cr4);
88     efer->lma = 1;
89     efer->lme = 1;
90
91     cr4->pae = 1;
92   }
93   */
94
95   guest_state->efer |= EFER_MSR_svm_enable;
96   vm_info->guest_efer.value = 0x0LL;
97
98   v3_hook_msr(vm_info, EFER_MSR, 
99               &v3_handle_efer_read,
100               &v3_handle_efer_write, 
101               vm_info);
102
103
104
105   guest_state->rflags = 0x00000002; // The reserved bit is always 1
106   ctrl_area->svm_instrs.VMRUN = 1;
107   ctrl_area->svm_instrs.VMMCALL = 1;
108   ctrl_area->svm_instrs.VMLOAD = 1;
109   ctrl_area->svm_instrs.VMSAVE = 1;
110   ctrl_area->svm_instrs.STGI = 1;
111   ctrl_area->svm_instrs.CLGI = 1;
112   ctrl_area->svm_instrs.SKINIT = 1;
113   ctrl_area->svm_instrs.RDTSCP = 1;
114   ctrl_area->svm_instrs.ICEBP = 1;
115   ctrl_area->svm_instrs.WBINVD = 1;
116   ctrl_area->svm_instrs.MONITOR = 1;
117   ctrl_area->svm_instrs.MWAIT_always = 1;
118   ctrl_area->svm_instrs.MWAIT_if_armed = 1;
119
120
121   ctrl_area->instrs.HLT = 1;
122   // guest_state->cr0 = 0x00000001;    // PE 
123   ctrl_area->guest_ASID = 1;
124
125   
126   /*
127     ctrl_area->exceptions.de = 1;
128     ctrl_area->exceptions.df = 1;
129     
130     ctrl_area->exceptions.ts = 1;
131     ctrl_area->exceptions.ss = 1;
132     ctrl_area->exceptions.ac = 1;
133     ctrl_area->exceptions.mc = 1;
134     ctrl_area->exceptions.gp = 1;
135     ctrl_area->exceptions.ud = 1;
136     ctrl_area->exceptions.np = 1;
137     ctrl_area->exceptions.of = 1;
138   
139     ctrl_area->exceptions.nmi = 1;
140   */
141
142
143   // Debug of boot on physical machines - 7/14/08
144   ctrl_area->instrs.NMI=1;
145   ctrl_area->instrs.SMI=1;
146   ctrl_area->instrs.INIT=1;
147   ctrl_area->instrs.PAUSE=1;
148   ctrl_area->instrs.shutdown_evts=1;
149
150   vm_info->vm_regs.rdx = 0x00000f00;
151
152   guest_state->cr0 = 0x60000010;
153
154
155   guest_state->cs.selector = 0xf000;
156   guest_state->cs.limit=0xffff;
157   guest_state->cs.base = 0x0000000f0000LL;
158   guest_state->cs.attrib.raw = 0xf3;
159
160   
161   /* DEBUG FOR RETURN CODE */
162   ctrl_area->exit_code = 1;
163
164
165   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
166   for ( i = 0; segregs[i] != NULL; i++) {
167     struct vmcb_selector * seg = segregs[i];
168     
169     seg->selector = 0x0000;
170     //    seg->base = seg->selector << 4;
171     seg->base = 0x00000000;
172     seg->attrib.raw = 0xf3;
173     seg->limit = ~0u;
174   }
175   
176   guest_state->gdtr.limit = 0x0000ffff;
177   guest_state->gdtr.base = 0x0000000000000000LL;
178   guest_state->idtr.limit = 0x0000ffff;
179   guest_state->idtr.base = 0x0000000000000000LL;
180
181   guest_state->ldtr.selector = 0x0000;
182   guest_state->ldtr.limit = 0x0000ffff;
183   guest_state->ldtr.base = 0x0000000000000000LL;
184   guest_state->tr.selector = 0x0000;
185   guest_state->tr.limit = 0x0000ffff;
186   guest_state->tr.base = 0x0000000000000000LL;
187
188
189   guest_state->dr6 = 0x00000000ffff0ff0LL;
190   guest_state->dr7 = 0x0000000000000400LL;
191
192   
193   
194
195
196
197   if ( !RB_EMPTY_ROOT(&(vm_info->io_map)) ) {
198     struct v3_io_hook * iter;
199     struct rb_node * io_node = v3_rb_first(&(vm_info->io_map));
200     addr_t io_port_bitmap;
201     int i = 0;
202
203     io_port_bitmap = (addr_t)V3_VAddr(V3_AllocPages(3));
204     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
205     
206     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr((void *)io_port_bitmap);
207
208     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
209
210     do {
211       iter = rb_entry(io_node, struct v3_io_hook, tree_node);
212
213       ushort_t port = iter->port;
214       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
215       PrintDebug("%d: Hooking Port %d\n", i, port);
216
217       bitmap += (port / 8);
218       //      PrintDebug("Setting Bit for port 0x%x\n", port);
219       *bitmap |= 1 << (port % 8);
220
221       i++;
222     } while ((io_node = v3_rb_next(io_node)));
223
224
225     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
226
227     ctrl_area->instrs.IOIO_PROT = 1;
228   }
229   
230
231   PrintDebug("Exiting on interrupts\n");
232   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
233   ctrl_area->instrs.INTR = 1;
234
235
236   if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
237     PrintDebug("Creating initial shadow page table\n");
238
239
240
241     /* Testing 64 bit page tables for long paged real mode guests */
242     //    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(vm_info));
243     vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32(vm_info));
244     /* End Test */
245
246     vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
247     PrintDebug("Created\n");
248
249
250     guest_state->cr3 = vm_info->direct_map_pt;
251
252
253     //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low));
254
255     ctrl_area->cr_reads.cr3 = 1;
256     ctrl_area->cr_writes.cr3 = 1;
257
258
259     ctrl_area->instrs.INVLPG = 1;
260     ctrl_area->instrs.INVLPGA = 1;
261
262     ctrl_area->exceptions.pf = 1;
263
264     /* JRL: This is a performance killer, and a simplistic solution */
265     /* We need to fix this */
266     ctrl_area->TLB_CONTROL = 1;
267     
268
269     guest_state->g_pat = 0x7040600070406ULL;
270
271     guest_state->cr0 |= 0x80000000;
272
273   } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
274     // Flush the TLB on entries/exits
275     ctrl_area->TLB_CONTROL = 1;
276
277     // Enable Nested Paging
278     ctrl_area->NP_ENABLE = 1;
279
280     PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE));
281
282     // Set the Nested Page Table pointer
283     vm_info->direct_map_pt = ((addr_t)create_passthrough_pts_32(vm_info) & ~0xfff);
284     ctrl_area->N_CR3 = vm_info->direct_map_pt;
285
286     //   ctrl_area->N_CR3 = Get_CR3();
287     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
288
289     guest_state->g_pat = 0x7040600070406ULL;
290   }
291
292
293   if (vm_info->msr_map.num_hooks > 0) {
294     PrintDebug("Hooking %d msrs\n", vm_info->msr_map.num_hooks);
295     ctrl_area->MSRPM_BASE_PA = v3_init_svm_msr_map(vm_info);
296     ctrl_area->instrs.MSR_PROT = 1;
297
298   }
299
300
301
302 }
303
304
305 static int init_svm_guest(struct guest_info *info) {
306  
307   PrintDebug("Allocating VMCB\n");
308   info->vmm_data = (void*)Allocate_VMCB();
309
310
311   //PrintDebug("Generating Guest nested page tables\n");
312   //  info->page_tables = NULL;
313   //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
314   //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
315   //  PrintDebugPageTables(info->page_tables);
316
317
318   PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data);
319   Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
320   
321
322   info->run_state = VM_STOPPED;
323
324   //  info->rip = 0;
325
326   info->vm_regs.rdi = 0;
327   info->vm_regs.rsi = 0;
328   info->vm_regs.rbp = 0;
329   info->vm_regs.rsp = 0;
330   info->vm_regs.rbx = 0;
331   info->vm_regs.rdx = 0;
332   info->vm_regs.rcx = 0;
333   info->vm_regs.rax = 0;
334   
335   return 0;
336 }
337
338
339
340 // can we start a kernel thread here...
341 static int start_svm_guest(struct guest_info *info) {
342   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
343   vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
344   uint_t num_exits = 0;
345
346
347
348   PrintDebug("Launching SVM VM (vmcb=%p)\n", (void *)info->vmm_data);
349   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
350
351   info->run_state = VM_RUNNING;
352
353   while (1) {
354     ullong_t tmp_tsc;
355     uint_t vm_cr_low = 0, vm_cr_high = 0;
356
357     v3_enable_ints();
358     v3_clgi();
359
360
361     /*
362     PrintDebug("SVM Entry to CS=%p  rip=%p...\n", 
363                (void *)(addr_t)info->segments.cs.base, 
364                (void *)(addr_t)info->rip);
365     */
366
367     v3_get_msr(0xc0000101, &vm_cr_high, &vm_cr_low);
368
369     rdtscll(info->time_state.cached_host_tsc);
370
371     guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
372
373     v3_svm_launch((vmcb_t*)V3_PAddr(info->vmm_data), &(info->vm_regs));
374     rdtscll(tmp_tsc);
375
376     v3_set_msr(0xc0000101, vm_cr_high, vm_cr_low);
377     //PrintDebug("SVM Returned\n");
378
379
380
381     v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
382     num_exits++;
383
384     //PrintDebug("Turning on global interrupts\n");
385     v3_stgi();
386
387
388     if ((num_exits % 5000) == 0) {
389       PrintDebug("SVM Exit number %d\n", num_exits);
390       if (info->enable_profiler) 
391         v3_print_profile(info);
392     }
393
394
395      
396     if (v3_handle_svm_exit(info) != 0) {
397       vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
398       addr_t host_addr;
399       addr_t linear_addr = 0;
400
401       info->run_state = VM_ERROR;
402
403       PrintDebug("SVM ERROR!!\n"); 
404       
405       PrintDebug("RIP: %p\n", (void *)(addr_t)(guest_state->rip));
406
407
408       linear_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
409
410
411       PrintDebug("RIP Linear: %p\n", (void *)linear_addr);
412       v3_print_segments(info);
413       v3_print_ctrl_regs(info);
414       if (info->shdw_pg_mode == SHADOW_PAGING) {
415         PrintDebug("Shadow Paging Guest Registers:\n");
416         PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
417         PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
418         // efer
419         // CR4
420       }
421       v3_print_GPRs(info);
422
423       PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); 
424       
425       PrintDebug("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
426       PrintDebug("exit_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
427       
428       PrintDebug("exit_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
429       PrintDebug("exit_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
430       
431       if (info->mem_mode == PHYSICAL_MEM) {
432         guest_pa_to_host_va(info, linear_addr, &host_addr);
433       } else if (info->mem_mode == VIRTUAL_MEM) {
434         guest_va_to_host_va(info, linear_addr, &host_addr);
435       }
436
437
438       PrintDebug("Host Address of rip = 0x%p\n", (void *)host_addr);
439
440       PrintDebug("Instr (15 bytes) at %p:\n", (void *)host_addr);
441       PrintTraceMemDump((uchar_t *)host_addr, 15);
442
443       break;
444     }
445
446   }
447   return 0;
448 }
449
450
451
452
453
454 /* Checks machine SVM capability */
455 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
456 int v3_is_svm_capable() {
457
458 #if 1
459   // Dinda
460   uint_t vm_cr_low = 0, vm_cr_high = 0;
461   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
462
463   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
464   
465   PrintDebug("CPUID_FEATURE_IDS_ecx=0x%p\n", (void *)ecx);
466
467   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
468     PrintDebug("SVM Not Available\n");
469     return 0;
470   }  else {
471     v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
472     
473     PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
474     
475     if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 1) {
476       PrintDebug("SVM is available but is disabled.\n");
477
478       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
479       
480       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
481       
482       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
483         PrintDebug("SVM BIOS Disabled, not unlockable\n");
484       } else {
485         PrintDebug("SVM is locked with a key\n");
486       }
487       return 0;
488
489     } else {
490       PrintDebug("SVM is available and  enabled.\n");
491
492       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
493       
494       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
495
496       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
497         PrintDebug("SVM Nested Paging not supported\n");
498       } else {
499         PrintDebug("SVM Nested Paging supported\n");
500       }
501       
502       return 1;
503       
504     }
505   }
506
507 #else
508   uint_t eax = 0, ebx = 0, ecx = 0, edx = 0;
509   addr_t vm_cr_low = 0, vm_cr_high = 0;
510
511   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
512
513   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
514     PrintDebug("SVM Not Available\n");
515     return 0;
516   } 
517
518   v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
519
520   PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
521
522
523   // this part is clearly wrong, since the np bit is in 
524   // edx, not ecx
525   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
526     PrintDebug("Nested Paging not supported\n");
527   } else {
528     PrintDebug("Nested Paging supported\n");
529   }
530
531   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
532     PrintDebug("SVM is disabled.\n");
533     return 1;
534   }
535
536   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
537
538   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
539     PrintDebug("SVM BIOS Disabled, not unlockable\n");
540   } else {
541     PrintDebug("SVM is locked with a key\n");
542   }
543
544   return 0;
545
546 #endif
547
548 }
549
550 static int has_svm_nested_paging() {
551   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
552
553   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
554       
555   //PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
556   
557   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
558     PrintDebug("SVM Nested Paging not supported\n");
559     return 0;
560   } else {
561     PrintDebug("SVM Nested Paging supported\n");
562     return 1;
563   }
564
565 }
566
567
568
569 void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) {
570   reg_ex_t msr;
571   void * host_state;
572
573
574   // Enable SVM on the CPU
575   v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
576   msr.e_reg.low |= EFER_MSR_svm_enable;
577   v3_set_msr(EFER_MSR, 0, msr.e_reg.low);
578   
579   PrintDebug("SVM Enabled\n");
580
581
582   // Setup the host state save area
583   host_state = V3_AllocPages(4);
584   
585
586   /* 64-BIT-ISSUE */
587   //  msr.e_reg.high = 0;
588   //msr.e_reg.low = (uint_t)host_state;
589   msr.r_reg = (addr_t)host_state;
590
591   PrintDebug("Host State being saved at %p\n", (void *)(addr_t)host_state);
592   v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
593
594
595
596   // Setup the SVM specific vmm operations
597   vmm_ops->init_guest = &init_svm_guest;
598   vmm_ops->start_guest = &start_svm_guest;
599   vmm_ops->has_nested_paging = &has_svm_nested_paging;
600
601   return;
602 }
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655 /*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
656   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
657   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
658   uint_t i;
659
660
661   guest_state->rsp = vm_info.vm_regs.rsp;
662   guest_state->rip = vm_info.rip;
663
664
665   //ctrl_area->instrs.instrs.CR0 = 1;
666   ctrl_area->cr_reads.cr0 = 1;
667   ctrl_area->cr_writes.cr0 = 1;
668
669   guest_state->efer |= EFER_MSR_svm_enable;
670   guest_state->rflags = 0x00000002; // The reserved bit is always 1
671   ctrl_area->svm_instrs.VMRUN = 1;
672   // guest_state->cr0 = 0x00000001;    // PE 
673   ctrl_area->guest_ASID = 1;
674
675
676   ctrl_area->exceptions.de = 1;
677   ctrl_area->exceptions.df = 1;
678   ctrl_area->exceptions.pf = 1;
679   ctrl_area->exceptions.ts = 1;
680   ctrl_area->exceptions.ss = 1;
681   ctrl_area->exceptions.ac = 1;
682   ctrl_area->exceptions.mc = 1;
683   ctrl_area->exceptions.gp = 1;
684   ctrl_area->exceptions.ud = 1;
685   ctrl_area->exceptions.np = 1;
686   ctrl_area->exceptions.of = 1;
687   ctrl_area->exceptions.nmi = 1;
688
689   guest_state->cs.selector = 0x0000;
690   guest_state->cs.limit=~0u;
691   guest_state->cs.base = guest_state->cs.selector<<4;
692   guest_state->cs.attrib.raw = 0xf3;
693
694   
695   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
696   for ( i = 0; segregs[i] != NULL; i++) {
697     struct vmcb_selector * seg = segregs[i];
698     
699     seg->selector = 0x0000;
700     seg->base = seg->selector << 4;
701     seg->attrib.raw = 0xf3;
702     seg->limit = ~0u;
703   }
704   
705   if (vm_info.io_map.num_ports > 0) {
706     struct vmm_io_hook * iter;
707     addr_t io_port_bitmap;
708     
709     io_port_bitmap = (addr_t)V3_AllocPages(3);
710     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
711     
712     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
713
714     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
715
716     FOREACH_IO_HOOK(vm_info.io_map, iter) {
717       ushort_t port = iter->port;
718       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
719
720       bitmap += (port / 8);
721       PrintDebug("Setting Bit in block %x\n", bitmap);
722       *bitmap |= 1 << (port % 8);
723     }
724
725
726     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
727
728     ctrl_area->instrs.IOIO_PROT = 1;
729   }
730
731   ctrl_area->instrs.INTR = 1;
732
733
734
735   if (vm_info.page_mode == SHADOW_PAGING) {
736     PrintDebug("Creating initial shadow page table\n");
737     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pts_32(&vm_info) & ~0xfff);
738     PrintDebug("Created\n");
739
740     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
741
742     ctrl_area->cr_reads.cr3 = 1;
743     ctrl_area->cr_writes.cr3 = 1;
744
745
746     ctrl_area->instrs.INVLPG = 1;
747     ctrl_area->instrs.INVLPGA = 1;
748
749     guest_state->g_pat = 0x7040600070406ULL;
750
751     guest_state->cr0 |= 0x80000000;
752   } else if (vm_info.page_mode == NESTED_PAGING) {
753     // Flush the TLB on entries/exits
754     //ctrl_area->TLB_CONTROL = 1;
755
756     // Enable Nested Paging
757     //ctrl_area->NP_ENABLE = 1;
758
759     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
760
761         // Set the Nested Page Table pointer
762     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
763     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
764
765     //   ctrl_area->N_CR3 = Get_CR3();
766     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
767
768     //    guest_state->g_pat = 0x7040600070406ULL;
769   }
770
771
772
773 }
774 */
775
776
777
778
779
780
781
782 #if 0
783 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
784   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
785   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
786   uint_t i = 0;
787
788
789   guest_state->rsp = vm_info.vm_regs.rsp;
790   guest_state->rip = vm_info.rip;
791
792
793   /* I pretty much just gutted this from TVMM */
794   /* Note: That means its probably wrong */
795
796   // set the segment registers to mirror ours
797   guest_state->cs.selector = 1<<3;
798   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
799   guest_state->cs.attrib.fields.S = 1;
800   guest_state->cs.attrib.fields.P = 1;
801   guest_state->cs.attrib.fields.db = 1;
802   guest_state->cs.attrib.fields.G = 1;
803   guest_state->cs.limit = 0xfffff;
804   guest_state->cs.base = 0;
805   
806   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
807   for ( i = 0; segregs[i] != NULL; i++) {
808     struct vmcb_selector * seg = segregs[i];
809     
810     seg->selector = 2<<3;
811     seg->attrib.fields.type = 0x2; // Data Segment+read/write
812     seg->attrib.fields.S = 1;
813     seg->attrib.fields.P = 1;
814     seg->attrib.fields.db = 1;
815     seg->attrib.fields.G = 1;
816     seg->limit = 0xfffff;
817     seg->base = 0;
818   }
819
820
821   {
822     /* JRL THIS HAS TO GO */
823     
824     //    guest_state->tr.selector = GetTR_Selector();
825     guest_state->tr.attrib.fields.type = 0x9; 
826     guest_state->tr.attrib.fields.P = 1;
827     // guest_state->tr.limit = GetTR_Limit();
828     //guest_state->tr.base = GetTR_Base();// - 0x2000;
829     /* ** */
830   }
831
832
833   /* ** */
834
835
836   guest_state->efer |= EFER_MSR_svm_enable;
837   guest_state->rflags = 0x00000002; // The reserved bit is always 1
838   ctrl_area->svm_instrs.VMRUN = 1;
839   guest_state->cr0 = 0x00000001;    // PE 
840   ctrl_area->guest_ASID = 1;
841
842
843   //  guest_state->cpl = 0;
844
845
846
847   // Setup exits
848
849   ctrl_area->cr_writes.cr4 = 1;
850   
851   ctrl_area->exceptions.de = 1;
852   ctrl_area->exceptions.df = 1;
853   ctrl_area->exceptions.pf = 1;
854   ctrl_area->exceptions.ts = 1;
855   ctrl_area->exceptions.ss = 1;
856   ctrl_area->exceptions.ac = 1;
857   ctrl_area->exceptions.mc = 1;
858   ctrl_area->exceptions.gp = 1;
859   ctrl_area->exceptions.ud = 1;
860   ctrl_area->exceptions.np = 1;
861   ctrl_area->exceptions.of = 1;
862   ctrl_area->exceptions.nmi = 1;
863
864   
865
866   ctrl_area->instrs.IOIO_PROT = 1;
867   ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
868   
869   {
870     reg_ex_t tmp_reg;
871     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
872     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
873   }
874
875   ctrl_area->instrs.INTR = 1;
876
877   
878   {
879     char gdt_buf[6];
880     char idt_buf[6];
881
882     memset(gdt_buf, 0, 6);
883     memset(idt_buf, 0, 6);
884
885
886     uint_t gdt_base, idt_base;
887     ushort_t gdt_limit, idt_limit;
888     
889     GetGDTR(gdt_buf);
890     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
891     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
892     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
893
894     GetIDTR(idt_buf);
895     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
896     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
897     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
898
899
900     // gdt_base -= 0x2000;
901     //idt_base -= 0x2000;
902
903     guest_state->gdtr.base = gdt_base;
904     guest_state->gdtr.limit = gdt_limit;
905     guest_state->idtr.base = idt_base;
906     guest_state->idtr.limit = idt_limit;
907
908
909   }
910   
911   
912   // also determine if CPU supports nested paging
913   /*
914   if (vm_info.page_tables) {
915     //   if (0) {
916     // Flush the TLB on entries/exits
917     ctrl_area->TLB_CONTROL = 1;
918
919     // Enable Nested Paging
920     ctrl_area->NP_ENABLE = 1;
921
922     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
923
924         // Set the Nested Page Table pointer
925     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
926
927
928     //   ctrl_area->N_CR3 = Get_CR3();
929     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
930
931     guest_state->g_pat = 0x7040600070406ULL;
932
933     PrintDebug("Set Nested CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(ctrl_area->N_CR3)), (uint_t)*((unsigned char *)&(ctrl_area->N_CR3) + 4));
934     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
935     // Enable Paging
936     //    guest_state->cr0 |= 0x80000000;
937   }
938   */
939
940 }
941
942
943
944
945
946 #endif
947
948