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.


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