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.


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