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.


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