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 shadow memory map to use Red Black Tree
[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
43 extern void v3_stgi();
44 extern void v3_clgi();
45 extern int v3_svm_launch(vmcb_t * vmcb, struct v3_gprs * vm_regs);
46
47
48
49
50 static vmcb_t * Allocate_VMCB() {
51   vmcb_t * vmcb_page = (vmcb_t *)V3_VAddr(V3_AllocPages(1));
52
53   memset(vmcb_page, 0, 4096);
54
55   return vmcb_page;
56 }
57
58
59
60 #include <palacios/vmm_ctrl_regs.h>
61
62 static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
63   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
64   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
65   uint_t i;
66
67
68   guest_state->rsp = vm_info->vm_regs.rsp;
69   // guest_state->rip = vm_info->rip;
70   guest_state->rip = 0xfff0;
71
72   guest_state->cpl = 0;
73
74   //ctrl_area->instrs.instrs.CR0 = 1;
75   ctrl_area->cr_reads.cr0 = 1;
76   ctrl_area->cr_writes.cr0 = 1;
77   //ctrl_area->cr_reads.cr4 = 1;
78   ctrl_area->cr_writes.cr4 = 1;
79
80
81   /* Set up the efer to enable 64 bit page tables */
82   /*
83   {
84     struct efer_64 * efer = (struct efer_64 *)&(guest_state->efer);
85     struct cr4_32 * cr4 = (struct cr4_32 *)&(guest_state->cr4);
86     efer->lma = 1;
87     efer->lme = 1;
88
89     cr4->pae = 1;
90   }
91   */
92
93   guest_state->efer |= EFER_MSR_svm_enable;
94   vm_info->guest_efer.value = 0x0LL;
95
96   v3_hook_msr(vm_info, EFER_MSR, 
97               &v3_handle_efer_read,
98               &v3_handle_efer_write, 
99               vm_info);
100
101
102
103   guest_state->rflags = 0x00000002; // The reserved bit is always 1
104   ctrl_area->svm_instrs.VMRUN = 1;
105   ctrl_area->svm_instrs.VMMCALL = 1;
106   ctrl_area->svm_instrs.VMLOAD = 1;
107   ctrl_area->svm_instrs.VMSAVE = 1;
108   ctrl_area->svm_instrs.STGI = 1;
109   ctrl_area->svm_instrs.CLGI = 1;
110   ctrl_area->svm_instrs.SKINIT = 1;
111   ctrl_area->svm_instrs.RDTSCP = 1;
112   ctrl_area->svm_instrs.ICEBP = 1;
113   ctrl_area->svm_instrs.WBINVD = 1;
114   ctrl_area->svm_instrs.MONITOR = 1;
115   ctrl_area->svm_instrs.MWAIT_always = 1;
116   ctrl_area->svm_instrs.MWAIT_if_armed = 1;
117
118
119   ctrl_area->instrs.HLT = 1;
120   // guest_state->cr0 = 0x00000001;    // PE 
121   ctrl_area->guest_ASID = 1;
122
123   
124   /*
125     ctrl_area->exceptions.de = 1;
126     ctrl_area->exceptions.df = 1;
127     
128     ctrl_area->exceptions.ts = 1;
129     ctrl_area->exceptions.ss = 1;
130     ctrl_area->exceptions.ac = 1;
131     ctrl_area->exceptions.mc = 1;
132     ctrl_area->exceptions.gp = 1;
133     ctrl_area->exceptions.ud = 1;
134     ctrl_area->exceptions.np = 1;
135     ctrl_area->exceptions.of = 1;
136   
137     ctrl_area->exceptions.nmi = 1;
138   */
139
140
141   // Debug of boot on physical machines - 7/14/08
142   ctrl_area->instrs.NMI=1;
143   ctrl_area->instrs.SMI=1;
144   ctrl_area->instrs.INIT=1;
145   ctrl_area->instrs.PAUSE=1;
146   ctrl_area->instrs.shutdown_evts=1;
147
148   vm_info->vm_regs.rdx = 0x00000f00;
149
150   guest_state->cr0 = 0x60000010;
151
152
153   guest_state->cs.selector = 0xf000;
154   guest_state->cs.limit=0xffff;
155   guest_state->cs.base = 0x0000000f0000LL;
156   guest_state->cs.attrib.raw = 0xf3;
157
158   
159   /* DEBUG FOR RETURN CODE */
160   ctrl_area->exit_code = 1;
161
162
163   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
164   for ( i = 0; segregs[i] != NULL; i++) {
165     struct vmcb_selector * seg = segregs[i];
166     
167     seg->selector = 0x0000;
168     //    seg->base = seg->selector << 4;
169     seg->base = 0x00000000;
170     seg->attrib.raw = 0xf3;
171     seg->limit = ~0u;
172   }
173   
174   guest_state->gdtr.limit = 0x0000ffff;
175   guest_state->gdtr.base = 0x0000000000000000LL;
176   guest_state->idtr.limit = 0x0000ffff;
177   guest_state->idtr.base = 0x0000000000000000LL;
178
179   guest_state->ldtr.selector = 0x0000;
180   guest_state->ldtr.limit = 0x0000ffff;
181   guest_state->ldtr.base = 0x0000000000000000LL;
182   guest_state->tr.selector = 0x0000;
183   guest_state->tr.limit = 0x0000ffff;
184   guest_state->tr.base = 0x0000000000000000LL;
185
186
187   guest_state->dr6 = 0x00000000ffff0ff0LL;
188   guest_state->dr7 = 0x0000000000000400LL;
189
190   
191   
192
193
194
195   if ( !RB_EMPTY_ROOT(&(vm_info->io_map)) ) {
196     struct v3_io_hook * iter;
197     struct rb_node * io_node = v3_rb_first(&(vm_info->io_map));
198     addr_t io_port_bitmap;
199     int i = 0;
200
201     io_port_bitmap = (addr_t)V3_VAddr(V3_AllocPages(3));
202     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
203     
204     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr((void *)io_port_bitmap);
205
206     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
207
208     do {
209       iter = rb_entry(io_node, struct v3_io_hook, tree_node);
210
211       ushort_t port = iter->port;
212       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
213       PrintDebug("%d: Hooking Port %d\n", i, port);
214
215       bitmap += (port / 8);
216       //      PrintDebug("Setting Bit for port 0x%x\n", port);
217       *bitmap |= 1 << (port % 8);
218
219       i++;
220     } while ((io_node = v3_rb_next(io_node)));
221
222
223     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
224
225     ctrl_area->instrs.IOIO_PROT = 1;
226   }
227   
228
229   PrintDebug("Exiting on interrupts\n");
230   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
231   ctrl_area->instrs.INTR = 1;
232
233
234   if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
235     PrintDebug("Creating initial shadow page table\n");
236
237
238
239     /* Testing 64 bit page tables for long paged real mode guests */
240     //    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(vm_info));
241     vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32(vm_info));
242     /* End Test */
243
244     vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
245     PrintDebug("Created\n");
246
247
248     guest_state->cr3 = vm_info->direct_map_pt;
249
250
251     //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low));
252
253     ctrl_area->cr_reads.cr3 = 1;
254     ctrl_area->cr_writes.cr3 = 1;
255
256
257     ctrl_area->instrs.INVLPG = 1;
258     ctrl_area->instrs.INVLPGA = 1;
259
260     ctrl_area->exceptions.pf = 1;
261
262     /* JRL: This is a performance killer, and a simplistic solution */
263     /* We need to fix this */
264     ctrl_area->TLB_CONTROL = 1;
265     
266
267     guest_state->g_pat = 0x7040600070406ULL;
268
269     guest_state->cr0 |= 0x80000000;
270
271   } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
272     // Flush the TLB on entries/exits
273     ctrl_area->TLB_CONTROL = 1;
274
275     // Enable Nested Paging
276     ctrl_area->NP_ENABLE = 1;
277
278     PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE));
279
280     // Set the Nested Page Table pointer
281     vm_info->direct_map_pt = ((addr_t)create_passthrough_pts_32(vm_info) & ~0xfff);
282     ctrl_area->N_CR3 = vm_info->direct_map_pt;
283
284     //   ctrl_area->N_CR3 = Get_CR3();
285     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
286
287     guest_state->g_pat = 0x7040600070406ULL;
288   }
289
290
291   if (vm_info->msr_map.num_hooks > 0) {
292     PrintDebug("Hooking %d msrs\n", vm_info->msr_map.num_hooks);
293     ctrl_area->MSRPM_BASE_PA = v3_init_svm_msr_map(vm_info);
294     ctrl_area->instrs.MSR_PROT = 1;
295
296   }
297
298
299
300 }
301
302
303 static int init_svm_guest(struct guest_info *info) {
304  
305   PrintDebug("Allocating VMCB\n");
306   info->vmm_data = (void*)Allocate_VMCB();
307
308
309   //PrintDebug("Generating Guest nested page tables\n");
310   //  info->page_tables = NULL;
311   //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
312   //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
313   //  PrintDebugPageTables(info->page_tables);
314
315
316   PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data);
317   Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
318   
319
320   info->run_state = VM_STOPPED;
321
322   //  info->rip = 0;
323
324   info->vm_regs.rdi = 0;
325   info->vm_regs.rsi = 0;
326   info->vm_regs.rbp = 0;
327   info->vm_regs.rsp = 0;
328   info->vm_regs.rbx = 0;
329   info->vm_regs.rdx = 0;
330   info->vm_regs.rcx = 0;
331   info->vm_regs.rax = 0;
332   
333   return 0;
334 }
335
336
337
338 // can we start a kernel thread here...
339 static int start_svm_guest(struct guest_info *info) {
340   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
341   vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
342   uint_t num_exits = 0;
343
344
345
346   PrintDebug("Launching SVM VM (vmcb=%p)\n", (void *)info->vmm_data);
347   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
348
349   info->run_state = VM_RUNNING;
350
351   while (1) {
352     ullong_t tmp_tsc;
353     uint_t vm_cr_low = 0, vm_cr_high = 0;
354
355
356     v3_enable_ints();
357     v3_clgi();
358
359
360     /*
361     PrintDebug("SVM Entry to CS=%p  rip=%p...\n", 
362                (void *)(addr_t)info->segments.cs.base, 
363                (void *)(addr_t)info->rip);
364     */
365
366     v3_get_msr(0xc0000101, &vm_cr_high, &vm_cr_low);
367
368     rdtscll(info->time_state.cached_host_tsc);
369
370     guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
371
372     v3_svm_launch((vmcb_t*)V3_PAddr(info->vmm_data), &(info->vm_regs));
373     rdtscll(tmp_tsc);
374
375     v3_set_msr(0xc0000101, vm_cr_high, vm_cr_low);
376     //PrintDebug("SVM Returned\n");
377
378
379
380     v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
381     num_exits++;
382
383     //PrintDebug("Turning on global interrupts\n");
384     v3_stgi();
385
386
387     if (num_exits % 25 == 0) {
388       PrintDebug("SVM Exit number %d\n", num_exits);
389     }
390
391      
392     if (v3_handle_svm_exit(info) != 0) {
393       vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
394       addr_t host_addr;
395       addr_t linear_addr = 0;
396
397       info->run_state = VM_ERROR;
398
399       PrintDebug("SVM ERROR!!\n"); 
400       
401       PrintDebug("RIP: %p\n", (void *)(addr_t)(guest_state->rip));
402
403
404       linear_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
405
406
407       PrintDebug("RIP Linear: %p\n", (void *)linear_addr);
408       v3_print_segments(info);
409       v3_print_ctrl_regs(info);
410       if (info->shdw_pg_mode == SHADOW_PAGING) {
411         PrintDebug("Shadow Paging Guest Registers:\n");
412         PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
413         PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
414         // efer
415         // CR4
416       }
417       v3_print_GPRs(info);
418
419
420       
421
422
423       PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); 
424       
425       PrintDebug("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
426       PrintDebug("exit_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
427       
428       PrintDebug("exit_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
429       PrintDebug("exit_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
430       
431       if (info->mem_mode == PHYSICAL_MEM) {
432         guest_pa_to_host_va(info, linear_addr, &host_addr);
433       } else if (info->mem_mode == VIRTUAL_MEM) {
434         guest_va_to_host_va(info, linear_addr, &host_addr);
435       }
436
437
438       PrintDebug("Host Address of rip = 0x%p\n", (void *)host_addr);
439
440       PrintDebug("Instr (15 bytes) at %p:\n", (void *)host_addr);
441       PrintTraceMemDump((uchar_t *)host_addr, 15);
442
443       break;
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