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.


reworked the paging functions
[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   vm_info->guest_efer.value = 0x0LL;
94
95   v3_hook_msr(vm_info, EFER_MSR, 
96               &v3_handle_efer_read,
97               &v3_handle_efer_write, 
98               vm_info);
99
100
101
102   guest_state->rflags = 0x00000002; // The reserved bit is always 1
103   ctrl_area->svm_instrs.VMRUN = 1;
104   ctrl_area->svm_instrs.VMMCALL = 1;
105   ctrl_area->svm_instrs.VMLOAD = 1;
106   ctrl_area->svm_instrs.VMSAVE = 1;
107   ctrl_area->svm_instrs.STGI = 1;
108   ctrl_area->svm_instrs.CLGI = 1;
109   ctrl_area->svm_instrs.SKINIT = 1;
110   ctrl_area->svm_instrs.RDTSCP = 1;
111   ctrl_area->svm_instrs.ICEBP = 1;
112   ctrl_area->svm_instrs.WBINVD = 1;
113   ctrl_area->svm_instrs.MONITOR = 1;
114   ctrl_area->svm_instrs.MWAIT_always = 1;
115   ctrl_area->svm_instrs.MWAIT_if_armed = 1;
116
117
118   ctrl_area->instrs.HLT = 1;
119   // guest_state->cr0 = 0x00000001;    // PE 
120   ctrl_area->guest_ASID = 1;
121
122   
123   /*
124     ctrl_area->exceptions.de = 1;
125     ctrl_area->exceptions.df = 1;
126     
127     ctrl_area->exceptions.ts = 1;
128     ctrl_area->exceptions.ss = 1;
129     ctrl_area->exceptions.ac = 1;
130     ctrl_area->exceptions.mc = 1;
131     ctrl_area->exceptions.gp = 1;
132     ctrl_area->exceptions.ud = 1;
133     ctrl_area->exceptions.np = 1;
134     ctrl_area->exceptions.of = 1;
135   
136     ctrl_area->exceptions.nmi = 1;
137   */
138
139
140   // Debug of boot on physical machines - 7/14/08
141   ctrl_area->instrs.NMI=1;
142   ctrl_area->instrs.SMI=1;
143   ctrl_area->instrs.INIT=1;
144   ctrl_area->instrs.PAUSE=1;
145   ctrl_area->instrs.shutdown_evts=1;
146
147   vm_info->vm_regs.rdx = 0x00000f00;
148
149   guest_state->cr0 = 0x60000010;
150
151
152   guest_state->cs.selector = 0xf000;
153   guest_state->cs.limit=0xffff;
154   guest_state->cs.base = 0x0000000f0000LL;
155   guest_state->cs.attrib.raw = 0xf3;
156
157   
158   /* DEBUG FOR RETURN CODE */
159   ctrl_area->exit_code = 1;
160
161
162   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
163   for ( i = 0; segregs[i] != NULL; i++) {
164     struct vmcb_selector * seg = segregs[i];
165     
166     seg->selector = 0x0000;
167     //    seg->base = seg->selector << 4;
168     seg->base = 0x00000000;
169     seg->attrib.raw = 0xf3;
170     seg->limit = ~0u;
171   }
172   
173   guest_state->gdtr.limit = 0x0000ffff;
174   guest_state->gdtr.base = 0x0000000000000000LL;
175   guest_state->idtr.limit = 0x0000ffff;
176   guest_state->idtr.base = 0x0000000000000000LL;
177
178   guest_state->ldtr.selector = 0x0000;
179   guest_state->ldtr.limit = 0x0000ffff;
180   guest_state->ldtr.base = 0x0000000000000000LL;
181   guest_state->tr.selector = 0x0000;
182   guest_state->tr.limit = 0x0000ffff;
183   guest_state->tr.base = 0x0000000000000000LL;
184
185
186   guest_state->dr6 = 0x00000000ffff0ff0LL;
187   guest_state->dr7 = 0x0000000000000400LL;
188
189   
190   
191
192
193
194   if (vm_info->io_map.num_ports > 0) {
195     struct vmm_io_hook * iter;
196     addr_t io_port_bitmap;
197     
198     io_port_bitmap = (addr_t)V3_VAddr(V3_AllocPages(3));
199     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
200     
201     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr((void *)io_port_bitmap);
202
203     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
204
205     FOREACH_IO_HOOK(vm_info->io_map, iter) {
206       ushort_t port = iter->port;
207       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
208
209       bitmap += (port / 8);
210       //      PrintDebug("Setting Bit for port 0x%x\n", port);
211       *bitmap |= 1 << (port % 8);
212     }
213
214
215     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
216
217     ctrl_area->instrs.IOIO_PROT = 1;
218   }
219   
220
221   PrintDebug("Exiting on interrupts\n");
222   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
223   ctrl_area->instrs.INTR = 1;
224
225
226   if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
227     PrintDebug("Creating initial shadow page table\n");
228
229
230
231     /* Testing 64 bit page tables for long paged real mode guests */
232     //    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(vm_info));
233     vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32(vm_info));
234     /* End Test */
235
236     vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
237     PrintDebug("Created\n");
238
239
240     guest_state->cr3 = vm_info->direct_map_pt;
241
242
243     //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low));
244
245     ctrl_area->cr_reads.cr3 = 1;
246     ctrl_area->cr_writes.cr3 = 1;
247
248
249     ctrl_area->instrs.INVLPG = 1;
250     ctrl_area->instrs.INVLPGA = 1;
251
252     ctrl_area->exceptions.pf = 1;
253
254     /* JRL: This is a performance killer, and a simplistic solution */
255     /* We need to fix this */
256     ctrl_area->TLB_CONTROL = 1;
257     
258
259     guest_state->g_pat = 0x7040600070406ULL;
260
261     guest_state->cr0 |= 0x80000000;
262
263   } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
264     // Flush the TLB on entries/exits
265     ctrl_area->TLB_CONTROL = 1;
266
267     // Enable Nested Paging
268     ctrl_area->NP_ENABLE = 1;
269
270     PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE));
271
272     // Set the Nested Page Table pointer
273     vm_info->direct_map_pt = ((addr_t)create_passthrough_pts_32(vm_info) & ~0xfff);
274     ctrl_area->N_CR3 = vm_info->direct_map_pt;
275
276     //   ctrl_area->N_CR3 = Get_CR3();
277     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
278
279     guest_state->g_pat = 0x7040600070406ULL;
280   }
281
282
283   if (vm_info->msr_map.num_hooks > 0) {
284     PrintDebug("Hooking %d msrs\n", vm_info->msr_map.num_hooks);
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       if (info->shdw_pg_mode == SHADOW_PAGING) {
399         PrintDebug("Shadow Paging Guest Registers:\n");
400         PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
401         PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
402         // efer
403         // CR4
404       }
405       v3_print_GPRs(info);
406
407
408       
409
410
411       PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); 
412       
413       PrintDebug("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
414       PrintDebug("exit_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
415       
416       PrintDebug("exit_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
417       PrintDebug("exit_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
418       
419       if (info->mem_mode == PHYSICAL_MEM) {
420         guest_pa_to_host_va(info, linear_addr, &host_addr);
421       } else if (info->mem_mode == VIRTUAL_MEM) {
422         guest_va_to_host_va(info, linear_addr, &host_addr);
423       }
424
425
426       PrintDebug("Host Address of rip = 0x%p\n", (void *)host_addr);
427
428       PrintDebug("Instr (15 bytes) at %p:\n", (void *)host_addr);
429       PrintTraceMemDump((uchar_t *)host_addr, 15);
430
431       break;
432     }
433   }
434   return 0;
435 }
436
437
438
439
440
441 /* Checks machine SVM capability */
442 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
443 int v3_is_svm_capable() {
444
445 #if 1
446   // Dinda
447   uint_t vm_cr_low = 0, vm_cr_high = 0;
448   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
449
450   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
451   
452   PrintDebug("CPUID_FEATURE_IDS_ecx=0x%p\n", (void *)ecx);
453
454   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
455     PrintDebug("SVM Not Available\n");
456     return 0;
457   }  else {
458     v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
459     
460     PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
461     
462     if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 1) {
463       PrintDebug("SVM is available but is disabled.\n");
464
465       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
466       
467       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
468       
469       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
470         PrintDebug("SVM BIOS Disabled, not unlockable\n");
471       } else {
472         PrintDebug("SVM is locked with a key\n");
473       }
474       return 0;
475
476     } else {
477       PrintDebug("SVM is available and  enabled.\n");
478
479       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
480       
481       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
482
483       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
484         PrintDebug("SVM Nested Paging not supported\n");
485       } else {
486         PrintDebug("SVM Nested Paging supported\n");
487       }
488       
489       return 1;
490       
491     }
492   }
493
494 #else
495   uint_t eax = 0, ebx = 0, ecx = 0, edx = 0;
496   addr_t vm_cr_low = 0, vm_cr_high = 0;
497
498   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
499
500   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
501     PrintDebug("SVM Not Available\n");
502     return 0;
503   } 
504
505   v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
506
507   PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
508
509
510   // this part is clearly wrong, since the np bit is in 
511   // edx, not ecx
512   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
513     PrintDebug("Nested Paging not supported\n");
514   } else {
515     PrintDebug("Nested Paging supported\n");
516   }
517
518   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
519     PrintDebug("SVM is disabled.\n");
520     return 1;
521   }
522
523   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
524
525   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
526     PrintDebug("SVM BIOS Disabled, not unlockable\n");
527   } else {
528     PrintDebug("SVM is locked with a key\n");
529   }
530
531   return 0;
532
533 #endif
534
535 }
536
537 static int has_svm_nested_paging() {
538   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
539
540   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
541       
542   //PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
543   
544   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
545     PrintDebug("SVM Nested Paging not supported\n");
546     return 0;
547   } else {
548     PrintDebug("SVM Nested Paging supported\n");
549     return 1;
550   }
551
552 }
553
554
555
556 void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) {
557   reg_ex_t msr;
558   void * host_state;
559
560
561   // Enable SVM on the CPU
562   v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
563   msr.e_reg.low |= EFER_MSR_svm_enable;
564   v3_set_msr(EFER_MSR, 0, msr.e_reg.low);
565   
566   PrintDebug("SVM Enabled\n");
567
568
569   // Setup the host state save area
570   host_state = V3_AllocPages(4);
571   
572
573   /* 64-BIT-ISSUE */
574   //  msr.e_reg.high = 0;
575   //msr.e_reg.low = (uint_t)host_state;
576   msr.r_reg = (addr_t)host_state;
577
578   PrintDebug("Host State being saved at %p\n", (void *)(addr_t)host_state);
579   v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
580
581
582
583   // Setup the SVM specific vmm operations
584   vmm_ops->init_guest = &init_svm_guest;
585   vmm_ops->start_guest = &start_svm_guest;
586   vmm_ops->has_nested_paging = &has_svm_nested_paging;
587
588   return;
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
634
635
636
637
638
639
640
641
642 /*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
643   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
644   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
645   uint_t i;
646
647
648   guest_state->rsp = vm_info.vm_regs.rsp;
649   guest_state->rip = vm_info.rip;
650
651
652   //ctrl_area->instrs.instrs.CR0 = 1;
653   ctrl_area->cr_reads.cr0 = 1;
654   ctrl_area->cr_writes.cr0 = 1;
655
656   guest_state->efer |= EFER_MSR_svm_enable;
657   guest_state->rflags = 0x00000002; // The reserved bit is always 1
658   ctrl_area->svm_instrs.VMRUN = 1;
659   // guest_state->cr0 = 0x00000001;    // PE 
660   ctrl_area->guest_ASID = 1;
661
662
663   ctrl_area->exceptions.de = 1;
664   ctrl_area->exceptions.df = 1;
665   ctrl_area->exceptions.pf = 1;
666   ctrl_area->exceptions.ts = 1;
667   ctrl_area->exceptions.ss = 1;
668   ctrl_area->exceptions.ac = 1;
669   ctrl_area->exceptions.mc = 1;
670   ctrl_area->exceptions.gp = 1;
671   ctrl_area->exceptions.ud = 1;
672   ctrl_area->exceptions.np = 1;
673   ctrl_area->exceptions.of = 1;
674   ctrl_area->exceptions.nmi = 1;
675
676   guest_state->cs.selector = 0x0000;
677   guest_state->cs.limit=~0u;
678   guest_state->cs.base = guest_state->cs.selector<<4;
679   guest_state->cs.attrib.raw = 0xf3;
680
681   
682   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
683   for ( i = 0; segregs[i] != NULL; i++) {
684     struct vmcb_selector * seg = segregs[i];
685     
686     seg->selector = 0x0000;
687     seg->base = seg->selector << 4;
688     seg->attrib.raw = 0xf3;
689     seg->limit = ~0u;
690   }
691   
692   if (vm_info.io_map.num_ports > 0) {
693     struct vmm_io_hook * iter;
694     addr_t io_port_bitmap;
695     
696     io_port_bitmap = (addr_t)V3_AllocPages(3);
697     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
698     
699     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
700
701     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
702
703     FOREACH_IO_HOOK(vm_info.io_map, iter) {
704       ushort_t port = iter->port;
705       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
706
707       bitmap += (port / 8);
708       PrintDebug("Setting Bit in block %x\n", bitmap);
709       *bitmap |= 1 << (port % 8);
710     }
711
712
713     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
714
715     ctrl_area->instrs.IOIO_PROT = 1;
716   }
717
718   ctrl_area->instrs.INTR = 1;
719
720
721
722   if (vm_info.page_mode == SHADOW_PAGING) {
723     PrintDebug("Creating initial shadow page table\n");
724     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pts_32(&vm_info) & ~0xfff);
725     PrintDebug("Created\n");
726
727     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
728
729     ctrl_area->cr_reads.cr3 = 1;
730     ctrl_area->cr_writes.cr3 = 1;
731
732
733     ctrl_area->instrs.INVLPG = 1;
734     ctrl_area->instrs.INVLPGA = 1;
735
736     guest_state->g_pat = 0x7040600070406ULL;
737
738     guest_state->cr0 |= 0x80000000;
739   } else if (vm_info.page_mode == NESTED_PAGING) {
740     // Flush the TLB on entries/exits
741     //ctrl_area->TLB_CONTROL = 1;
742
743     // Enable Nested Paging
744     //ctrl_area->NP_ENABLE = 1;
745
746     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
747
748         // Set the Nested Page Table pointer
749     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
750     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
751
752     //   ctrl_area->N_CR3 = Get_CR3();
753     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
754
755     //    guest_state->g_pat = 0x7040600070406ULL;
756   }
757
758
759
760 }
761 */
762
763
764
765
766
767
768
769 #if 0
770 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
771   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
772   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
773   uint_t i = 0;
774
775
776   guest_state->rsp = vm_info.vm_regs.rsp;
777   guest_state->rip = vm_info.rip;
778
779
780   /* I pretty much just gutted this from TVMM */
781   /* Note: That means its probably wrong */
782
783   // set the segment registers to mirror ours
784   guest_state->cs.selector = 1<<3;
785   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
786   guest_state->cs.attrib.fields.S = 1;
787   guest_state->cs.attrib.fields.P = 1;
788   guest_state->cs.attrib.fields.db = 1;
789   guest_state->cs.attrib.fields.G = 1;
790   guest_state->cs.limit = 0xfffff;
791   guest_state->cs.base = 0;
792   
793   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
794   for ( i = 0; segregs[i] != NULL; i++) {
795     struct vmcb_selector * seg = segregs[i];
796     
797     seg->selector = 2<<3;
798     seg->attrib.fields.type = 0x2; // Data Segment+read/write
799     seg->attrib.fields.S = 1;
800     seg->attrib.fields.P = 1;
801     seg->attrib.fields.db = 1;
802     seg->attrib.fields.G = 1;
803     seg->limit = 0xfffff;
804     seg->base = 0;
805   }
806
807
808   {
809     /* JRL THIS HAS TO GO */
810     
811     //    guest_state->tr.selector = GetTR_Selector();
812     guest_state->tr.attrib.fields.type = 0x9; 
813     guest_state->tr.attrib.fields.P = 1;
814     // guest_state->tr.limit = GetTR_Limit();
815     //guest_state->tr.base = GetTR_Base();// - 0x2000;
816     /* ** */
817   }
818
819
820   /* ** */
821
822
823   guest_state->efer |= EFER_MSR_svm_enable;
824   guest_state->rflags = 0x00000002; // The reserved bit is always 1
825   ctrl_area->svm_instrs.VMRUN = 1;
826   guest_state->cr0 = 0x00000001;    // PE 
827   ctrl_area->guest_ASID = 1;
828
829
830   //  guest_state->cpl = 0;
831
832
833
834   // Setup exits
835
836   ctrl_area->cr_writes.cr4 = 1;
837   
838   ctrl_area->exceptions.de = 1;
839   ctrl_area->exceptions.df = 1;
840   ctrl_area->exceptions.pf = 1;
841   ctrl_area->exceptions.ts = 1;
842   ctrl_area->exceptions.ss = 1;
843   ctrl_area->exceptions.ac = 1;
844   ctrl_area->exceptions.mc = 1;
845   ctrl_area->exceptions.gp = 1;
846   ctrl_area->exceptions.ud = 1;
847   ctrl_area->exceptions.np = 1;
848   ctrl_area->exceptions.of = 1;
849   ctrl_area->exceptions.nmi = 1;
850
851   
852
853   ctrl_area->instrs.IOIO_PROT = 1;
854   ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
855   
856   {
857     reg_ex_t tmp_reg;
858     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
859     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
860   }
861
862   ctrl_area->instrs.INTR = 1;
863
864   
865   {
866     char gdt_buf[6];
867     char idt_buf[6];
868
869     memset(gdt_buf, 0, 6);
870     memset(idt_buf, 0, 6);
871
872
873     uint_t gdt_base, idt_base;
874     ushort_t gdt_limit, idt_limit;
875     
876     GetGDTR(gdt_buf);
877     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
878     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
879     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
880
881     GetIDTR(idt_buf);
882     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
883     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
884     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
885
886
887     // gdt_base -= 0x2000;
888     //idt_base -= 0x2000;
889
890     guest_state->gdtr.base = gdt_base;
891     guest_state->gdtr.limit = gdt_limit;
892     guest_state->idtr.base = idt_base;
893     guest_state->idtr.limit = idt_limit;
894
895
896   }
897   
898   
899   // also determine if CPU supports nested paging
900   /*
901   if (vm_info.page_tables) {
902     //   if (0) {
903     // Flush the TLB on entries/exits
904     ctrl_area->TLB_CONTROL = 1;
905
906     // Enable Nested Paging
907     ctrl_area->NP_ENABLE = 1;
908
909     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
910
911         // Set the Nested Page Table pointer
912     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
913
914
915     //   ctrl_area->N_CR3 = Get_CR3();
916     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
917
918     guest_state->g_pat = 0x7040600070406ULL;
919
920     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));
921     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
922     // Enable Paging
923     //    guest_state->cr0 |= 0x80000000;
924   }
925   */
926
927 }
928
929
930
931
932
933 #endif
934
935