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.


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