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