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.


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