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.


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