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