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.


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