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.


changed to error output
[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=%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=%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       PrintDebug("CPUID_FEATURE_IDS_eax=%p\n", (void *)eax);
494       PrintDebug("CPUID_FEATURE_IDS_ebx=%p\n", (void *)ebx);
495       PrintDebug("CPUID_FEATURE_IDS_ecx=%p\n", (void *)ecx);      
496       PrintDebug("CPUID_FEATURE_IDS_edx=%p\n", (void *)edx);
497
498
499       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
500         PrintDebug("SVM Nested Paging not supported\n");
501       } else {
502         PrintDebug("SVM Nested Paging supported\n");
503       }
504       
505       return 1;
506       
507     }
508   }
509
510 #else
511   uint_t eax = 0, ebx = 0, ecx = 0, edx = 0;
512   addr_t vm_cr_low = 0, vm_cr_high = 0;
513
514   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
515
516   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
517     PrintDebug("SVM Not Available\n");
518     return 0;
519   } 
520
521   v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
522
523   PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
524
525
526   // this part is clearly wrong, since the np bit is in 
527   // edx, not ecx
528   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
529     PrintDebug("Nested Paging not supported\n");
530   } else {
531     PrintDebug("Nested Paging supported\n");
532   }
533
534   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
535     PrintDebug("SVM is disabled.\n");
536     return 1;
537   }
538
539   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
540
541   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
542     PrintDebug("SVM BIOS Disabled, not unlockable\n");
543   } else {
544     PrintDebug("SVM is locked with a key\n");
545   }
546
547   return 0;
548
549 #endif
550
551 }
552
553 static int has_svm_nested_paging() {
554   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
555
556   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
557       
558   //PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
559   
560   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
561     PrintDebug("SVM Nested Paging not supported\n");
562     return 0;
563   } else {
564     PrintDebug("SVM Nested Paging supported\n");
565     return 1;
566   }
567
568 }
569
570
571
572 void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) {
573   reg_ex_t msr;
574   void * host_state;
575
576
577   // Enable SVM on the CPU
578   v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
579   msr.e_reg.low |= EFER_MSR_svm_enable;
580   v3_set_msr(EFER_MSR, 0, msr.e_reg.low);
581   
582   PrintDebug("SVM Enabled\n");
583
584
585   // Setup the host state save area
586   host_state = V3_AllocPages(4);
587   
588
589   /* 64-BIT-ISSUE */
590   //  msr.e_reg.high = 0;
591   //msr.e_reg.low = (uint_t)host_state;
592   msr.r_reg = (addr_t)host_state;
593
594   PrintDebug("Host State being saved at %p\n", (void *)(addr_t)host_state);
595   v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
596
597
598
599   // Setup the SVM specific vmm operations
600   vmm_ops->init_guest = &init_svm_guest;
601   vmm_ops->start_guest = &start_svm_guest;
602   vmm_ops->has_nested_paging = &has_svm_nested_paging;
603
604   return;
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
656
657
658 /*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
659   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
660   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
661   uint_t i;
662
663
664   guest_state->rsp = vm_info.vm_regs.rsp;
665   guest_state->rip = vm_info.rip;
666
667
668   //ctrl_area->instrs.instrs.CR0 = 1;
669   ctrl_area->cr_reads.cr0 = 1;
670   ctrl_area->cr_writes.cr0 = 1;
671
672   guest_state->efer |= EFER_MSR_svm_enable;
673   guest_state->rflags = 0x00000002; // The reserved bit is always 1
674   ctrl_area->svm_instrs.VMRUN = 1;
675   // guest_state->cr0 = 0x00000001;    // PE 
676   ctrl_area->guest_ASID = 1;
677
678
679   ctrl_area->exceptions.de = 1;
680   ctrl_area->exceptions.df = 1;
681   ctrl_area->exceptions.pf = 1;
682   ctrl_area->exceptions.ts = 1;
683   ctrl_area->exceptions.ss = 1;
684   ctrl_area->exceptions.ac = 1;
685   ctrl_area->exceptions.mc = 1;
686   ctrl_area->exceptions.gp = 1;
687   ctrl_area->exceptions.ud = 1;
688   ctrl_area->exceptions.np = 1;
689   ctrl_area->exceptions.of = 1;
690   ctrl_area->exceptions.nmi = 1;
691
692   guest_state->cs.selector = 0x0000;
693   guest_state->cs.limit=~0u;
694   guest_state->cs.base = guest_state->cs.selector<<4;
695   guest_state->cs.attrib.raw = 0xf3;
696
697   
698   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
699   for ( i = 0; segregs[i] != NULL; i++) {
700     struct vmcb_selector * seg = segregs[i];
701     
702     seg->selector = 0x0000;
703     seg->base = seg->selector << 4;
704     seg->attrib.raw = 0xf3;
705     seg->limit = ~0u;
706   }
707   
708   if (vm_info.io_map.num_ports > 0) {
709     struct vmm_io_hook * iter;
710     addr_t io_port_bitmap;
711     
712     io_port_bitmap = (addr_t)V3_AllocPages(3);
713     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
714     
715     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
716
717     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
718
719     FOREACH_IO_HOOK(vm_info.io_map, iter) {
720       ushort_t port = iter->port;
721       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
722
723       bitmap += (port / 8);
724       PrintDebug("Setting Bit in block %x\n", bitmap);
725       *bitmap |= 1 << (port % 8);
726     }
727
728
729     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
730
731     ctrl_area->instrs.IOIO_PROT = 1;
732   }
733
734   ctrl_area->instrs.INTR = 1;
735
736
737
738   if (vm_info.page_mode == SHADOW_PAGING) {
739     PrintDebug("Creating initial shadow page table\n");
740     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pts_32(&vm_info) & ~0xfff);
741     PrintDebug("Created\n");
742
743     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
744
745     ctrl_area->cr_reads.cr3 = 1;
746     ctrl_area->cr_writes.cr3 = 1;
747
748
749     ctrl_area->instrs.INVLPG = 1;
750     ctrl_area->instrs.INVLPGA = 1;
751
752     guest_state->g_pat = 0x7040600070406ULL;
753
754     guest_state->cr0 |= 0x80000000;
755   } else if (vm_info.page_mode == NESTED_PAGING) {
756     // Flush the TLB on entries/exits
757     //ctrl_area->TLB_CONTROL = 1;
758
759     // Enable Nested Paging
760     //ctrl_area->NP_ENABLE = 1;
761
762     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
763
764         // Set the Nested Page Table pointer
765     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
766     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
767
768     //   ctrl_area->N_CR3 = Get_CR3();
769     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
770
771     //    guest_state->g_pat = 0x7040600070406ULL;
772   }
773
774
775
776 }
777 */
778
779
780
781
782
783
784
785 #if 0
786 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
787   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
788   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
789   uint_t i = 0;
790
791
792   guest_state->rsp = vm_info.vm_regs.rsp;
793   guest_state->rip = vm_info.rip;
794
795
796   /* I pretty much just gutted this from TVMM */
797   /* Note: That means its probably wrong */
798
799   // set the segment registers to mirror ours
800   guest_state->cs.selector = 1<<3;
801   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
802   guest_state->cs.attrib.fields.S = 1;
803   guest_state->cs.attrib.fields.P = 1;
804   guest_state->cs.attrib.fields.db = 1;
805   guest_state->cs.attrib.fields.G = 1;
806   guest_state->cs.limit = 0xfffff;
807   guest_state->cs.base = 0;
808   
809   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
810   for ( i = 0; segregs[i] != NULL; i++) {
811     struct vmcb_selector * seg = segregs[i];
812     
813     seg->selector = 2<<3;
814     seg->attrib.fields.type = 0x2; // Data Segment+read/write
815     seg->attrib.fields.S = 1;
816     seg->attrib.fields.P = 1;
817     seg->attrib.fields.db = 1;
818     seg->attrib.fields.G = 1;
819     seg->limit = 0xfffff;
820     seg->base = 0;
821   }
822
823
824   {
825     /* JRL THIS HAS TO GO */
826     
827     //    guest_state->tr.selector = GetTR_Selector();
828     guest_state->tr.attrib.fields.type = 0x9; 
829     guest_state->tr.attrib.fields.P = 1;
830     // guest_state->tr.limit = GetTR_Limit();
831     //guest_state->tr.base = GetTR_Base();// - 0x2000;
832     /* ** */
833   }
834
835
836   /* ** */
837
838
839   guest_state->efer |= EFER_MSR_svm_enable;
840   guest_state->rflags = 0x00000002; // The reserved bit is always 1
841   ctrl_area->svm_instrs.VMRUN = 1;
842   guest_state->cr0 = 0x00000001;    // PE 
843   ctrl_area->guest_ASID = 1;
844
845
846   //  guest_state->cpl = 0;
847
848
849
850   // Setup exits
851
852   ctrl_area->cr_writes.cr4 = 1;
853   
854   ctrl_area->exceptions.de = 1;
855   ctrl_area->exceptions.df = 1;
856   ctrl_area->exceptions.pf = 1;
857   ctrl_area->exceptions.ts = 1;
858   ctrl_area->exceptions.ss = 1;
859   ctrl_area->exceptions.ac = 1;
860   ctrl_area->exceptions.mc = 1;
861   ctrl_area->exceptions.gp = 1;
862   ctrl_area->exceptions.ud = 1;
863   ctrl_area->exceptions.np = 1;
864   ctrl_area->exceptions.of = 1;
865   ctrl_area->exceptions.nmi = 1;
866
867   
868
869   ctrl_area->instrs.IOIO_PROT = 1;
870   ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
871   
872   {
873     reg_ex_t tmp_reg;
874     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
875     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
876   }
877
878   ctrl_area->instrs.INTR = 1;
879
880   
881   {
882     char gdt_buf[6];
883     char idt_buf[6];
884
885     memset(gdt_buf, 0, 6);
886     memset(idt_buf, 0, 6);
887
888
889     uint_t gdt_base, idt_base;
890     ushort_t gdt_limit, idt_limit;
891     
892     GetGDTR(gdt_buf);
893     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
894     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
895     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
896
897     GetIDTR(idt_buf);
898     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
899     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
900     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
901
902
903     // gdt_base -= 0x2000;
904     //idt_base -= 0x2000;
905
906     guest_state->gdtr.base = gdt_base;
907     guest_state->gdtr.limit = gdt_limit;
908     guest_state->idtr.base = idt_base;
909     guest_state->idtr.limit = idt_limit;
910
911
912   }
913   
914   
915   // also determine if CPU supports nested paging
916   /*
917   if (vm_info.page_tables) {
918     //   if (0) {
919     // Flush the TLB on entries/exits
920     ctrl_area->TLB_CONTROL = 1;
921
922     // Enable Nested Paging
923     ctrl_area->NP_ENABLE = 1;
924
925     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
926
927         // Set the Nested Page Table pointer
928     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
929
930
931     //   ctrl_area->N_CR3 = Get_CR3();
932     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
933
934     guest_state->g_pat = 0x7040600070406ULL;
935
936     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));
937     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
938     // Enable Paging
939     //    guest_state->cr0 |= 0x80000000;
940   }
941   */
942
943 }
944
945
946
947
948
949 #endif
950
951