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.


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