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 GS.BASE save/restore
[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%x\n", &(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=%x)\n", 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=%x)\n", 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
312       v3_get_msr(0xc0000101, &vm_cr_high, &vm_cr_low);
313
314       PrintDebug("GS.Base: %x:%x\n", vm_cr_high, vm_cr_low); 
315       /*
316       v3_get_msr(0xc0000102, &vm_cr_high, &vm_cr_low);
317
318       PrintDebug("KernelGSBase: %x:%x\n", vm_cr_high, vm_cr_low); 
319       */
320
321     }
322
323     PrintDebug("SVM Entry to rip=%x...\n", info->rip);
324
325     rdtscll(info->time_state.cached_host_tsc);
326     guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
327
328     v3_svm_launch((vmcb_t*)V3_PAddr(info->vmm_data), &(info->vm_regs));
329
330     rdtscll(tmp_tsc);
331     PrintDebug("SVM Returned\n");
332
333
334     {
335
336       v3_set_msr(0xc0000101, vm_cr_high, vm_cr_low);
337
338       PrintDebug("GS.Base: %x:%x\n", vm_cr_high, vm_cr_low); 
339
340       /*
341       v3_get_msr(0xc0000102, &vm_cr_high, &vm_cr_low);
342
343       PrintDebug("KernelGSBase: %x:%x\n", vm_cr_high, vm_cr_low); 
344       */
345
346     }
347     
348     {
349       uint_t x = 0;
350       PrintDebug("RSP=%p\n", &x);
351     }
352
353
354     v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
355     num_exits++;
356
357     PrintDebug("Turning on global interrupts\n");
358     v3_stgi();
359
360
361     PrintDebug("SVM Exit number %d\n", num_exits);
362
363
364      
365     if (v3_handle_svm_exit(info) != 0) {
366
367       addr_t host_addr;
368       addr_t linear_addr = 0;
369
370       info->run_state = VM_ERROR;
371
372       PrintDebug("SVM ERROR!!\n"); 
373       
374       PrintDebug("RIP: %x\n", guest_state->rip);
375
376
377       linear_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
378
379
380       PrintDebug("RIP Linear: %\n", linear_addr);
381       v3_print_segments(info);
382       v3_print_ctrl_regs(info);
383       v3_print_GPRs(info);
384       
385       if (info->mem_mode == PHYSICAL_MEM) {
386         guest_pa_to_host_va(info, linear_addr, &host_addr);
387       } else if (info->mem_mode == VIRTUAL_MEM) {
388         guest_va_to_host_va(info, linear_addr, &host_addr);
389       }
390
391
392       PrintDebug("Host Address of rip = 0x%x\n", host_addr);
393
394       PrintDebug("Instr (15 bytes) at %x:\n", host_addr);
395       PrintTraceMemDump((uchar_t *)host_addr, 15);
396
397       break;
398     }
399   }
400   return 0;
401 }
402
403
404
405
406
407 /* Checks machine SVM capability */
408 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
409 int v3_is_svm_capable() {
410
411 #if 1
412   // Dinda
413   uint_t vm_cr_low = 0, vm_cr_high = 0;
414   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
415
416   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
417   
418   PrintDebug("CPUID_FEATURE_IDS_ecx=0x%x\n", ecx);
419
420   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
421     PrintDebug("SVM Not Available\n");
422     return 0;
423   }  else {
424     v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
425     
426     PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
427     
428     if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 1) {
429       PrintDebug("SVM is available but is disabled.\n");
430
431       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
432       
433       PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
434       
435       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
436         PrintDebug("SVM BIOS Disabled, not unlockable\n");
437       } else {
438         PrintDebug("SVM is locked with a key\n");
439       }
440       return 0;
441
442     } else {
443       PrintDebug("SVM is available and  enabled.\n");
444
445       v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
446       
447       PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
448
449       if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
450         PrintDebug("SVM Nested Paging not supported\n");
451       } else {
452         PrintDebug("SVM Nested Paging supported\n");
453       }
454       
455       return 1;
456       
457     }
458   }
459
460 #else
461   uint_t eax = 0, ebx = 0, ecx = 0, edx = 0;
462   addr_t vm_cr_low = 0, vm_cr_high = 0;
463
464   v3_cpuid(CPUID_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
465
466   if ((ecx & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
467     PrintDebug("SVM Not Available\n");
468     return 0;
469   } 
470
471   v3_get_msr(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
472
473   PrintDebug("SVM_VM_CR_MSR = 0x%x 0x%x\n", vm_cr_high, vm_cr_low);
474
475
476   // this part is clearly wrong, since the np bit is in 
477   // edx, not ecx
478   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
479     PrintDebug("Nested Paging not supported\n");
480   } else {
481     PrintDebug("Nested Paging supported\n");
482   }
483
484   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
485     PrintDebug("SVM is disabled.\n");
486     return 1;
487   }
488
489   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
490
491   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
492     PrintDebug("SVM BIOS Disabled, not unlockable\n");
493   } else {
494     PrintDebug("SVM is locked with a key\n");
495   }
496
497   return 0;
498
499 #endif
500
501 }
502
503 static int has_svm_nested_paging() {
504   addr_t eax = 0, ebx = 0, ecx = 0, edx = 0;
505
506   v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx);
507       
508   //PrintDebug("CPUID_FEATURE_IDS_edx=0x%x\n", edx);
509   
510   if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
511     PrintDebug("SVM Nested Paging not supported\n");
512     return 0;
513   } else {
514     PrintDebug("SVM Nested Paging supported\n");
515     return 1;
516   }
517
518 }
519
520
521
522 void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) {
523   reg_ex_t msr;
524   void * host_state;
525
526
527   // Enable SVM on the CPU
528   v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
529   msr.e_reg.low |= EFER_MSR_svm_enable;
530   v3_set_msr(EFER_MSR, 0, msr.e_reg.low);
531   
532   PrintDebug("SVM Enabled\n");
533
534
535   // Setup the host state save area
536   host_state = V3_AllocPages(4);
537   
538
539   /* 64-BIT-ISSUE */
540   //  msr.e_reg.high = 0;
541   //msr.e_reg.low = (uint_t)host_state;
542   msr.r_reg = (addr_t)host_state;
543
544   PrintDebug("Host State being saved at %x\n", (addr_t)host_state);
545   v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
546
547
548
549   // Setup the SVM specific vmm operations
550   vmm_ops->init_guest = &init_svm_guest;
551   vmm_ops->start_guest = &start_svm_guest;
552   vmm_ops->has_nested_paging = &has_svm_nested_paging;
553
554   return;
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
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608 /*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
609   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
610   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
611   uint_t i;
612
613
614   guest_state->rsp = vm_info.vm_regs.rsp;
615   guest_state->rip = vm_info.rip;
616
617
618   //ctrl_area->instrs.instrs.CR0 = 1;
619   ctrl_area->cr_reads.cr0 = 1;
620   ctrl_area->cr_writes.cr0 = 1;
621
622   guest_state->efer |= EFER_MSR_svm_enable;
623   guest_state->rflags = 0x00000002; // The reserved bit is always 1
624   ctrl_area->svm_instrs.VMRUN = 1;
625   // guest_state->cr0 = 0x00000001;    // PE 
626   ctrl_area->guest_ASID = 1;
627
628
629   ctrl_area->exceptions.de = 1;
630   ctrl_area->exceptions.df = 1;
631   ctrl_area->exceptions.pf = 1;
632   ctrl_area->exceptions.ts = 1;
633   ctrl_area->exceptions.ss = 1;
634   ctrl_area->exceptions.ac = 1;
635   ctrl_area->exceptions.mc = 1;
636   ctrl_area->exceptions.gp = 1;
637   ctrl_area->exceptions.ud = 1;
638   ctrl_area->exceptions.np = 1;
639   ctrl_area->exceptions.of = 1;
640   ctrl_area->exceptions.nmi = 1;
641
642   guest_state->cs.selector = 0x0000;
643   guest_state->cs.limit=~0u;
644   guest_state->cs.base = guest_state->cs.selector<<4;
645   guest_state->cs.attrib.raw = 0xf3;
646
647   
648   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
649   for ( i = 0; segregs[i] != NULL; i++) {
650     struct vmcb_selector * seg = segregs[i];
651     
652     seg->selector = 0x0000;
653     seg->base = seg->selector << 4;
654     seg->attrib.raw = 0xf3;
655     seg->limit = ~0u;
656   }
657   
658   if (vm_info.io_map.num_ports > 0) {
659     struct vmm_io_hook * iter;
660     addr_t io_port_bitmap;
661     
662     io_port_bitmap = (addr_t)V3_AllocPages(3);
663     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
664     
665     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
666
667     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
668
669     FOREACH_IO_HOOK(vm_info.io_map, iter) {
670       ushort_t port = iter->port;
671       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
672
673       bitmap += (port / 8);
674       PrintDebug("Setting Bit in block %x\n", bitmap);
675       *bitmap |= 1 << (port % 8);
676     }
677
678
679     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
680
681     ctrl_area->instrs.IOIO_PROT = 1;
682   }
683
684   ctrl_area->instrs.INTR = 1;
685
686
687
688   if (vm_info.page_mode == SHADOW_PAGING) {
689     PrintDebug("Creating initial shadow page table\n");
690     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
691     PrintDebug("Created\n");
692
693     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
694
695     ctrl_area->cr_reads.cr3 = 1;
696     ctrl_area->cr_writes.cr3 = 1;
697
698
699     ctrl_area->instrs.INVLPG = 1;
700     ctrl_area->instrs.INVLPGA = 1;
701
702     guest_state->g_pat = 0x7040600070406ULL;
703
704     guest_state->cr0 |= 0x80000000;
705   } else if (vm_info.page_mode == NESTED_PAGING) {
706     // Flush the TLB on entries/exits
707     //ctrl_area->TLB_CONTROL = 1;
708
709     // Enable Nested Paging
710     //ctrl_area->NP_ENABLE = 1;
711
712     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
713
714         // Set the Nested Page Table pointer
715     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
716     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
717
718     //   ctrl_area->N_CR3 = Get_CR3();
719     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
720
721     //    guest_state->g_pat = 0x7040600070406ULL;
722   }
723
724
725
726 }
727 */
728
729
730
731
732
733
734
735 #if 0
736 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
737   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
738   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
739   uint_t i = 0;
740
741
742   guest_state->rsp = vm_info.vm_regs.rsp;
743   guest_state->rip = vm_info.rip;
744
745
746   /* I pretty much just gutted this from TVMM */
747   /* Note: That means its probably wrong */
748
749   // set the segment registers to mirror ours
750   guest_state->cs.selector = 1<<3;
751   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
752   guest_state->cs.attrib.fields.S = 1;
753   guest_state->cs.attrib.fields.P = 1;
754   guest_state->cs.attrib.fields.db = 1;
755   guest_state->cs.attrib.fields.G = 1;
756   guest_state->cs.limit = 0xfffff;
757   guest_state->cs.base = 0;
758   
759   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
760   for ( i = 0; segregs[i] != NULL; i++) {
761     struct vmcb_selector * seg = segregs[i];
762     
763     seg->selector = 2<<3;
764     seg->attrib.fields.type = 0x2; // Data Segment+read/write
765     seg->attrib.fields.S = 1;
766     seg->attrib.fields.P = 1;
767     seg->attrib.fields.db = 1;
768     seg->attrib.fields.G = 1;
769     seg->limit = 0xfffff;
770     seg->base = 0;
771   }
772
773
774   {
775     /* JRL THIS HAS TO GO */
776     
777     //    guest_state->tr.selector = GetTR_Selector();
778     guest_state->tr.attrib.fields.type = 0x9; 
779     guest_state->tr.attrib.fields.P = 1;
780     // guest_state->tr.limit = GetTR_Limit();
781     //guest_state->tr.base = GetTR_Base();// - 0x2000;
782     /* ** */
783   }
784
785
786   /* ** */
787
788
789   guest_state->efer |= EFER_MSR_svm_enable;
790   guest_state->rflags = 0x00000002; // The reserved bit is always 1
791   ctrl_area->svm_instrs.VMRUN = 1;
792   guest_state->cr0 = 0x00000001;    // PE 
793   ctrl_area->guest_ASID = 1;
794
795
796   //  guest_state->cpl = 0;
797
798
799
800   // Setup exits
801
802   ctrl_area->cr_writes.cr4 = 1;
803   
804   ctrl_area->exceptions.de = 1;
805   ctrl_area->exceptions.df = 1;
806   ctrl_area->exceptions.pf = 1;
807   ctrl_area->exceptions.ts = 1;
808   ctrl_area->exceptions.ss = 1;
809   ctrl_area->exceptions.ac = 1;
810   ctrl_area->exceptions.mc = 1;
811   ctrl_area->exceptions.gp = 1;
812   ctrl_area->exceptions.ud = 1;
813   ctrl_area->exceptions.np = 1;
814   ctrl_area->exceptions.of = 1;
815   ctrl_area->exceptions.nmi = 1;
816
817   
818
819   ctrl_area->instrs.IOIO_PROT = 1;
820   ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
821   
822   {
823     reg_ex_t tmp_reg;
824     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
825     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
826   }
827
828   ctrl_area->instrs.INTR = 1;
829
830   
831   {
832     char gdt_buf[6];
833     char idt_buf[6];
834
835     memset(gdt_buf, 0, 6);
836     memset(idt_buf, 0, 6);
837
838
839     uint_t gdt_base, idt_base;
840     ushort_t gdt_limit, idt_limit;
841     
842     GetGDTR(gdt_buf);
843     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
844     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
845     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
846
847     GetIDTR(idt_buf);
848     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
849     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
850     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
851
852
853     // gdt_base -= 0x2000;
854     //idt_base -= 0x2000;
855
856     guest_state->gdtr.base = gdt_base;
857     guest_state->gdtr.limit = gdt_limit;
858     guest_state->idtr.base = idt_base;
859     guest_state->idtr.limit = idt_limit;
860
861
862   }
863   
864   
865   // also determine if CPU supports nested paging
866   /*
867   if (vm_info.page_tables) {
868     //   if (0) {
869     // Flush the TLB on entries/exits
870     ctrl_area->TLB_CONTROL = 1;
871
872     // Enable Nested Paging
873     ctrl_area->NP_ENABLE = 1;
874
875     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
876
877         // Set the Nested Page Table pointer
878     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
879
880
881     //   ctrl_area->N_CR3 = Get_CR3();
882     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
883
884     guest_state->g_pat = 0x7040600070406ULL;
885
886     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));
887     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
888     // Enable Paging
889     //    guest_state->cr0 |= 0x80000000;
890   }
891   */
892
893 }
894
895
896
897
898
899 #endif
900
901