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.


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