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.


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