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