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.


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