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 more 64 bit support,
[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               NULL, /*&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.shadow_cr3 |= (vm_info->direct_map_pt & ~0xfff);
237     vm_info->shdw_pg_state.shadow_cr3 = 0;
238     vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
239     PrintDebug("Created\n");
240
241     //guest_state->cr3 = vm_info->shdw_pg_state.shadow_cr3;
242
243     guest_state->cr3 = vm_info->direct_map_pt;
244
245
246     //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low));
247
248     ctrl_area->cr_reads.cr3 = 1;
249     ctrl_area->cr_writes.cr3 = 1;
250
251
252     ctrl_area->instrs.INVLPG = 1;
253     ctrl_area->instrs.INVLPGA = 1;
254
255     ctrl_area->exceptions.pf = 1;
256
257     /* JRL: This is a performance killer, and a simplistic solution */
258     /* We need to fix this */
259     ctrl_area->TLB_CONTROL = 1;
260     
261
262     guest_state->g_pat = 0x7040600070406ULL;
263
264     guest_state->cr0 |= 0x80000000;
265
266   } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
267     // Flush the TLB on entries/exits
268     ctrl_area->TLB_CONTROL = 1;
269
270     // Enable Nested Paging
271     ctrl_area->NP_ENABLE = 1;
272
273     PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE));
274
275     // Set the Nested Page Table pointer
276     vm_info->direct_map_pt = ((addr_t)create_passthrough_pts_32(vm_info) & ~0xfff);
277     ctrl_area->N_CR3 = vm_info->direct_map_pt;
278
279     //   ctrl_area->N_CR3 = Get_CR3();
280     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
281
282     guest_state->g_pat = 0x7040600070406ULL;
283   }
284
285
286   if (vm_info->msr_map.num_hooks > 0) {
287     PrintDebug("Hooking %d msrs\n", vm_info->msr_map.num_hooks);
288     ctrl_area->MSRPM_BASE_PA = v3_init_svm_msr_map(vm_info);
289     ctrl_area->instrs.MSR_PROT = 1;
290
291   }
292
293
294
295 }
296
297
298 static int init_svm_guest(struct guest_info *info) {
299  
300   PrintDebug("Allocating VMCB\n");
301   info->vmm_data = (void*)Allocate_VMCB();
302
303
304   //PrintDebug("Generating Guest nested page tables\n");
305   //  info->page_tables = NULL;
306   //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
307   //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
308   //  PrintDebugPageTables(info->page_tables);
309
310
311   PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data);
312   Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
313   
314
315   info->run_state = VM_STOPPED;
316
317   //  info->rip = 0;
318
319   info->vm_regs.rdi = 0;
320   info->vm_regs.rsi = 0;
321   info->vm_regs.rbp = 0;
322   info->vm_regs.rsp = 0;
323   info->vm_regs.rbx = 0;
324   info->vm_regs.rdx = 0;
325   info->vm_regs.rcx = 0;
326   info->vm_regs.rax = 0;
327   
328   return 0;
329 }
330
331
332
333 // can we start a kernel thread here...
334 static int start_svm_guest(struct guest_info *info) {
335   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
336   vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
337   uint_t num_exits = 0;
338
339
340
341   PrintDebug("Launching SVM VM (vmcb=%p)\n", (void *)info->vmm_data);
342   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
343
344   info->run_state = VM_RUNNING;
345
346   while (1) {
347     ullong_t tmp_tsc;
348     uint_t vm_cr_low = 0, vm_cr_high = 0;
349
350
351     v3_enable_ints();
352     v3_clgi();
353
354
355     //PrintDebug("SVM Entry to rip=%p...\n", (void *)info->rip);
356
357     v3_get_msr(0xc0000101, &vm_cr_high, &vm_cr_low);
358
359     rdtscll(info->time_state.cached_host_tsc);
360
361     guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
362
363     v3_svm_launch((vmcb_t*)V3_PAddr(info->vmm_data), &(info->vm_regs));
364     rdtscll(tmp_tsc);
365
366     v3_set_msr(0xc0000101, vm_cr_high, vm_cr_low);
367     //PrintDebug("SVM Returned\n");
368
369
370
371     v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
372     num_exits++;
373
374     //PrintDebug("Turning on global interrupts\n");
375     v3_stgi();
376
377
378     if (num_exits % 25 == 0) {
379       PrintDebug("SVM Exit number %d\n", num_exits);
380     }
381
382      
383     if (v3_handle_svm_exit(info) != 0) {
384       vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
385       addr_t host_addr;
386       addr_t linear_addr = 0;
387
388       info->run_state = VM_ERROR;
389
390       PrintDebug("SVM ERROR!!\n"); 
391       
392       PrintDebug("RIP: %p\n", (void *)(addr_t)(guest_state->rip));
393
394
395       linear_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
396
397
398       PrintDebug("RIP Linear: %p\n", (void *)linear_addr);
399       v3_print_segments(info);
400       v3_print_ctrl_regs(info);
401       v3_print_GPRs(info);
402
403
404
405       PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); 
406       
407       PrintDebug("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
408       PrintDebug("exit_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
409       
410       PrintDebug("exit_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
411       PrintDebug("exit_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
412       
413       if (info->mem_mode == PHYSICAL_MEM) {
414         guest_pa_to_host_va(info, linear_addr, &host_addr);
415       } else if (info->mem_mode == VIRTUAL_MEM) {
416         guest_va_to_host_va(info, linear_addr, &host_addr);
417       }
418
419
420       PrintDebug("Host Address of rip = 0x%p\n", (void *)host_addr);
421
422       PrintDebug("Instr (15 bytes) at %p:\n", (void *)host_addr);
423       PrintTraceMemDump((uchar_t *)host_addr, 15);
424
425       break;
426     }
427   }
428   return 0;
429 }
430
431
432
433
434
435 /* Checks machine SVM capability */
436 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
437 int v3_is_svm_capable() {
438
439 #if 1
440   // Dinda
441   uint_t vm_cr_low = 0, vm_cr_high = 0;
442   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
443
444   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
445   
446   PrintDebug("CPUID_FEATURE_IDS_ecx=0x%p\n", (void *)ecx);
447
448   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
449     PrintDebug("SVM Not Available\n");
450     return 0;
451   }  else {
452     v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
453     
454     PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
455     
456     if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 1) {
457       PrintDebug("SVM is available but is disabled.\n");
458
459       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
460       
461       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
462       
463       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
464         PrintDebug("SVM BIOS Disabled, not unlockable\n");
465       } else {
466         PrintDebug("SVM is locked with a key\n");
467       }
468       return 0;
469
470     } else {
471       PrintDebug("SVM is available and  enabled.\n");
472
473       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
474       
475       PrintDebug("CPUID_FEATURE_IDS_edx=0x%p\n", (void *)edx);
476
477       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
478         PrintDebug("SVM Nested Paging not supported\n");
479       } else {
480         PrintDebug("SVM Nested Paging supported\n");
481       }
482       
483       return 1;
484       
485     }
486   }
487
488 #else
489   uint_t eax = 0, ebx = 0, ecx = 0, edx = 0;
490   addr_t vm_cr_low = 0, vm_cr_high = 0;
491
492   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
493
494   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
495     PrintDebug("SVM Not Available\n");
496     return 0;
497   } 
498
499   v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
500
501   PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
502
503
504   // this part is clearly wrong, since the np bit is in 
505   // edx, not ecx
506   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
507     PrintDebug("Nested Paging not supported\n");
508   } else {
509     PrintDebug("Nested Paging supported\n");
510   }
511
512   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
513     PrintDebug("SVM is disabled.\n");
514     return 1;
515   }
516
517   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
518
519   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
520     PrintDebug("SVM BIOS Disabled, not unlockable\n");
521   } else {
522     PrintDebug("SVM is locked with a key\n");
523   }
524
525   return 0;
526
527 #endif
528
529 }
530
531 static int has_svm_nested_paging() {
532   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
533
534   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
535       
536   //PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
537   
538   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
539     PrintDebug("SVM Nested Paging not supported\n");
540     return 0;
541   } else {
542     PrintDebug("SVM Nested Paging supported\n");
543     return 1;
544   }
545
546 }
547
548
549
550 void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) {
551   reg_ex_t msr;
552   void * host_state;
553
554
555   // Enable SVM on the CPU
556   v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
557   msr.e_reg.low |= EFER_MSR_svm_enable;
558   v3_set_msr(EFER_MSR, 0, msr.e_reg.low);
559   
560   PrintDebug("SVM Enabled\n");
561
562
563   // Setup the host state save area
564   host_state = V3_AllocPages(4);
565   
566
567   /* 64-BIT-ISSUE */
568   //  msr.e_reg.high = 0;
569   //msr.e_reg.low = (uint_t)host_state;
570   msr.r_reg = (addr_t)host_state;
571
572   PrintDebug("Host State being saved at %p\n", (void *)(addr_t)host_state);
573   v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
574
575
576
577   // Setup the SVM specific vmm operations
578   vmm_ops->init_guest = &init_svm_guest;
579   vmm_ops->start_guest = &start_svm_guest;
580   vmm_ops->has_nested_paging = &has_svm_nested_paging;
581
582   return;
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
634
635
636 /*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
637   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
638   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
639   uint_t i;
640
641
642   guest_state->rsp = vm_info.vm_regs.rsp;
643   guest_state->rip = vm_info.rip;
644
645
646   //ctrl_area->instrs.instrs.CR0 = 1;
647   ctrl_area->cr_reads.cr0 = 1;
648   ctrl_area->cr_writes.cr0 = 1;
649
650   guest_state->efer |= EFER_MSR_svm_enable;
651   guest_state->rflags = 0x00000002; // The reserved bit is always 1
652   ctrl_area->svm_instrs.VMRUN = 1;
653   // guest_state->cr0 = 0x00000001;    // PE 
654   ctrl_area->guest_ASID = 1;
655
656
657   ctrl_area->exceptions.de = 1;
658   ctrl_area->exceptions.df = 1;
659   ctrl_area->exceptions.pf = 1;
660   ctrl_area->exceptions.ts = 1;
661   ctrl_area->exceptions.ss = 1;
662   ctrl_area->exceptions.ac = 1;
663   ctrl_area->exceptions.mc = 1;
664   ctrl_area->exceptions.gp = 1;
665   ctrl_area->exceptions.ud = 1;
666   ctrl_area->exceptions.np = 1;
667   ctrl_area->exceptions.of = 1;
668   ctrl_area->exceptions.nmi = 1;
669
670   guest_state->cs.selector = 0x0000;
671   guest_state->cs.limit=~0u;
672   guest_state->cs.base = guest_state->cs.selector<<4;
673   guest_state->cs.attrib.raw = 0xf3;
674
675   
676   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
677   for ( i = 0; segregs[i] != NULL; i++) {
678     struct vmcb_selector * seg = segregs[i];
679     
680     seg->selector = 0x0000;
681     seg->base = seg->selector << 4;
682     seg->attrib.raw = 0xf3;
683     seg->limit = ~0u;
684   }
685   
686   if (vm_info.io_map.num_ports > 0) {
687     struct vmm_io_hook * iter;
688     addr_t io_port_bitmap;
689     
690     io_port_bitmap = (addr_t)V3_AllocPages(3);
691     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
692     
693     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
694
695     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
696
697     FOREACH_IO_HOOK(vm_info.io_map, iter) {
698       ushort_t port = iter->port;
699       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
700
701       bitmap += (port / 8);
702       PrintDebug("Setting Bit in block %x\n", bitmap);
703       *bitmap |= 1 << (port % 8);
704     }
705
706
707     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
708
709     ctrl_area->instrs.IOIO_PROT = 1;
710   }
711
712   ctrl_area->instrs.INTR = 1;
713
714
715
716   if (vm_info.page_mode == SHADOW_PAGING) {
717     PrintDebug("Creating initial shadow page table\n");
718     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pts_32(&vm_info) & ~0xfff);
719     PrintDebug("Created\n");
720
721     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
722
723     ctrl_area->cr_reads.cr3 = 1;
724     ctrl_area->cr_writes.cr3 = 1;
725
726
727     ctrl_area->instrs.INVLPG = 1;
728     ctrl_area->instrs.INVLPGA = 1;
729
730     guest_state->g_pat = 0x7040600070406ULL;
731
732     guest_state->cr0 |= 0x80000000;
733   } else if (vm_info.page_mode == NESTED_PAGING) {
734     // Flush the TLB on entries/exits
735     //ctrl_area->TLB_CONTROL = 1;
736
737     // Enable Nested Paging
738     //ctrl_area->NP_ENABLE = 1;
739
740     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
741
742         // Set the Nested Page Table pointer
743     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
744     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
745
746     //   ctrl_area->N_CR3 = Get_CR3();
747     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
748
749     //    guest_state->g_pat = 0x7040600070406ULL;
750   }
751
752
753
754 }
755 */
756
757
758
759
760
761
762
763 #if 0
764 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
765   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
766   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
767   uint_t i = 0;
768
769
770   guest_state->rsp = vm_info.vm_regs.rsp;
771   guest_state->rip = vm_info.rip;
772
773
774   /* I pretty much just gutted this from TVMM */
775   /* Note: That means its probably wrong */
776
777   // set the segment registers to mirror ours
778   guest_state->cs.selector = 1<<3;
779   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
780   guest_state->cs.attrib.fields.S = 1;
781   guest_state->cs.attrib.fields.P = 1;
782   guest_state->cs.attrib.fields.db = 1;
783   guest_state->cs.attrib.fields.G = 1;
784   guest_state->cs.limit = 0xfffff;
785   guest_state->cs.base = 0;
786   
787   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
788   for ( i = 0; segregs[i] != NULL; i++) {
789     struct vmcb_selector * seg = segregs[i];
790     
791     seg->selector = 2<<3;
792     seg->attrib.fields.type = 0x2; // Data Segment+read/write
793     seg->attrib.fields.S = 1;
794     seg->attrib.fields.P = 1;
795     seg->attrib.fields.db = 1;
796     seg->attrib.fields.G = 1;
797     seg->limit = 0xfffff;
798     seg->base = 0;
799   }
800
801
802   {
803     /* JRL THIS HAS TO GO */
804     
805     //    guest_state->tr.selector = GetTR_Selector();
806     guest_state->tr.attrib.fields.type = 0x9; 
807     guest_state->tr.attrib.fields.P = 1;
808     // guest_state->tr.limit = GetTR_Limit();
809     //guest_state->tr.base = GetTR_Base();// - 0x2000;
810     /* ** */
811   }
812
813
814   /* ** */
815
816
817   guest_state->efer |= EFER_MSR_svm_enable;
818   guest_state->rflags = 0x00000002; // The reserved bit is always 1
819   ctrl_area->svm_instrs.VMRUN = 1;
820   guest_state->cr0 = 0x00000001;    // PE 
821   ctrl_area->guest_ASID = 1;
822
823
824   //  guest_state->cpl = 0;
825
826
827
828   // Setup exits
829
830   ctrl_area->cr_writes.cr4 = 1;
831   
832   ctrl_area->exceptions.de = 1;
833   ctrl_area->exceptions.df = 1;
834   ctrl_area->exceptions.pf = 1;
835   ctrl_area->exceptions.ts = 1;
836   ctrl_area->exceptions.ss = 1;
837   ctrl_area->exceptions.ac = 1;
838   ctrl_area->exceptions.mc = 1;
839   ctrl_area->exceptions.gp = 1;
840   ctrl_area->exceptions.ud = 1;
841   ctrl_area->exceptions.np = 1;
842   ctrl_area->exceptions.of = 1;
843   ctrl_area->exceptions.nmi = 1;
844
845   
846
847   ctrl_area->instrs.IOIO_PROT = 1;
848   ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
849   
850   {
851     reg_ex_t tmp_reg;
852     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
853     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
854   }
855
856   ctrl_area->instrs.INTR = 1;
857
858   
859   {
860     char gdt_buf[6];
861     char idt_buf[6];
862
863     memset(gdt_buf, 0, 6);
864     memset(idt_buf, 0, 6);
865
866
867     uint_t gdt_base, idt_base;
868     ushort_t gdt_limit, idt_limit;
869     
870     GetGDTR(gdt_buf);
871     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
872     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
873     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
874
875     GetIDTR(idt_buf);
876     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
877     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
878     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
879
880
881     // gdt_base -= 0x2000;
882     //idt_base -= 0x2000;
883
884     guest_state->gdtr.base = gdt_base;
885     guest_state->gdtr.limit = gdt_limit;
886     guest_state->idtr.base = idt_base;
887     guest_state->idtr.limit = idt_limit;
888
889
890   }
891   
892   
893   // also determine if CPU supports nested paging
894   /*
895   if (vm_info.page_tables) {
896     //   if (0) {
897     // Flush the TLB on entries/exits
898     ctrl_area->TLB_CONTROL = 1;
899
900     // Enable Nested Paging
901     ctrl_area->NP_ENABLE = 1;
902
903     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
904
905         // Set the Nested Page Table pointer
906     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
907
908
909     //   ctrl_area->N_CR3 = Get_CR3();
910     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
911
912     guest_state->g_pat = 0x7040600070406ULL;
913
914     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));
915     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
916     // Enable Paging
917     //    guest_state->cr0 |= 0x80000000;
918   }
919   */
920
921 }
922
923
924
925
926
927 #endif
928
929