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.


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