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.


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