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