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