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.


*** empty log message ***
[palacios.git] / palacios / src / palacios / svm.c
1 #include <palacios/svm.h>
2 #include <palacios/vmm.h>
3
4 #include <palacios/vmcb.h>
5 #include <palacios/vmm_mem.h>
6 #include <palacios/vmm_paging.h>
7 #include <palacios/svm_handler.h>
8
9 #include <palacios/vmm_debug.h>
10 #include <palacios/vm_guest_mem.h>
11
12
13
14 extern struct vmm_os_hooks * os_hooks;
15
16 extern uint_t cpuid_ecx(uint_t op);
17 extern uint_t cpuid_edx(uint_t op);
18 extern void Get_MSR(uint_t MSR, uint_t * high_byte, uint_t * low_byte); 
19 extern void Set_MSR(uint_t MSR, uint_t high_byte, uint_t low_byte);
20 extern uint_t launch_svm(vmcb_t * vmcb_addr);
21 extern void safe_svm_launch(vmcb_t * vmcb_addr, struct guest_gprs * gprs);
22
23 extern void STGI();
24 extern void CLGI();
25
26 extern uint_t Get_CR3();
27
28
29 extern void DisableInts();
30
31 /* Checks machine SVM capability */
32 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
33 int is_svm_capable() {
34   uint_t ret =  cpuid_ecx(CPUID_FEATURE_IDS);
35   uint_t vm_cr_low = 0, vm_cr_high = 0;
36
37
38   if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
39     PrintDebug("SVM Not Available\n");
40     return 0;
41   } 
42
43   Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
44
45   if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
46     PrintDebug("Nested Paging not supported\n");
47   }
48
49   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
50     return 1;
51   }
52
53   ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS);
54
55   if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
56     PrintDebug("SVM BIOS Disabled, not unlockable\n");
57   } else {
58     PrintDebug("SVM is locked with a key\n");
59   }
60
61   return 0;
62 }
63
64
65
66 void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
67   reg_ex_t msr;
68   void * host_state;
69
70
71   // Enable SVM on the CPU
72   Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
73   msr.e_reg.low |= EFER_MSR_svm_enable;
74   Set_MSR(EFER_MSR, 0, msr.e_reg.low);
75   
76   PrintDebug("SVM Enabled\n");
77
78
79   // Setup the host state save area
80   host_state = os_hooks->allocate_pages(4);
81   
82   msr.e_reg.high = 0;
83   msr.e_reg.low = (uint_t)host_state;
84
85
86   PrintDebug("Host State being saved at %x\n", (uint_t)host_state);
87   Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
88
89
90
91   // Setup the SVM specific vmm operations
92   vmm_ops->init_guest = &init_svm_guest;
93   vmm_ops->start_guest = &start_svm_guest;
94
95
96   return;
97 }
98
99
100 int init_svm_guest(struct guest_info *info) {
101  
102   PrintDebug("Allocating VMCB\n");
103   info->vmm_data = (void*)Allocate_VMCB();
104
105
106   //PrintDebug("Generating Guest nested page tables\n");
107   //  info->page_tables = NULL;
108   //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
109   //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
110   //  PrintDebugPageTables(info->page_tables);
111
112
113   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
114   Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), *info);
115   
116
117   //  info->rip = 0;
118
119   info->vm_regs.rdi = 0;
120   info->vm_regs.rsi = 0;
121   info->vm_regs.rbp = 0;
122   info->vm_regs.rsp = 0;
123   info->vm_regs.rbx = 0;
124   info->vm_regs.rdx = 0;
125   info->vm_regs.rcx = 0;
126   info->vm_regs.rax = 0;
127   
128   return 0;
129 }
130
131
132 // can we start a kernel thread here...
133 int start_svm_guest(struct guest_info *info) {
134
135
136
137   PrintDebug("Launching SVM VM (vmcb=%x)\n", info->vmm_data);
138   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
139
140   while (1) {
141
142     CLGI();
143
144     //PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data,  &(info->vm_regs));
145     //PrintDebug("Launching to RIP: %x\n", info->rip);
146     safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
147     //launch_svm((vmcb_t*)(info->vmm_data));
148     //PrintDebug("SVM Returned\n");
149
150     STGI();
151     
152     if (handle_svm_exit(info) != 0) {
153       PrintDebug("SVM ERROR!!\n");
154       break;
155     }
156   }
157   return 0;
158 }
159
160
161
162 vmcb_t * Allocate_VMCB() {
163   vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
164
165
166   memset(vmcb_page, 0, 4096);
167
168   return vmcb_page;
169 }
170
171
172
173 void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
174   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
175   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
176   uint_t i;
177
178
179   guest_state->rsp = vm_info.vm_regs.rsp;
180   guest_state->rip = vm_info.rip;
181
182
183   //ctrl_area->instrs.instrs.CR0 = 1;
184   ctrl_area->cr_reads.cr0 = 1;
185   ctrl_area->cr_writes.cr0 = 1;
186
187   guest_state->efer |= EFER_MSR_svm_enable;
188   guest_state->rflags = 0x00000002; // The reserved bit is always 1
189   ctrl_area->svm_instrs.VMRUN = 1;
190   // guest_state->cr0 = 0x00000001;    // PE 
191   ctrl_area->guest_ASID = 1;
192
193
194   ctrl_area->exceptions.de = 1;
195   ctrl_area->exceptions.df = 1;
196   ctrl_area->exceptions.pf = 1;
197   ctrl_area->exceptions.ts = 1;
198   ctrl_area->exceptions.ss = 1;
199   ctrl_area->exceptions.ac = 1;
200   ctrl_area->exceptions.mc = 1;
201   ctrl_area->exceptions.gp = 1;
202   ctrl_area->exceptions.ud = 1;
203   ctrl_area->exceptions.np = 1;
204   ctrl_area->exceptions.of = 1;
205   ctrl_area->exceptions.nmi = 1;
206
207   guest_state->cs.selector = 0x0000;
208   guest_state->cs.limit=~0u;
209   guest_state->cs.base = guest_state->cs.selector<<4;
210   guest_state->cs.attrib.raw = 0xf3;
211
212   
213   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
214   for ( i = 0; segregs[i] != NULL; i++) {
215     struct vmcb_selector * seg = segregs[i];
216     
217     seg->selector = 0x0000;
218     seg->base = seg->selector << 4;
219     seg->attrib.raw = 0xf3;
220     seg->limit = ~0u;
221   }
222   
223   if (vm_info.io_map.num_ports > 0) {
224     vmm_io_hook_t * iter;
225     addr_t io_port_bitmap;
226     
227     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
228     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
229     
230     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
231
232     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
233
234     FOREACH_IO_HOOK(vm_info.io_map, iter) {
235       ushort_t port = iter->port;
236       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
237
238       bitmap += (port / 8);
239       PrintDebug("Setting Bit in block %x\n", bitmap);
240       *bitmap |= 1 << (port % 8);
241     }
242
243
244     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
245
246     ctrl_area->instrs.IOIO_PROT = 1;
247   }
248
249   ctrl_area->instrs.INTR = 1;
250
251
252
253   if (vm_info.page_mode == SHADOW_PAGING) {
254     PrintDebug("Creating initial shadow page table\n");
255     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
256     PrintDebug("Created\n");
257
258     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
259
260     ctrl_area->cr_reads.cr3 = 1;
261     ctrl_area->cr_writes.cr3 = 1;
262
263
264     ctrl_area->instrs.INVLPG = 1;
265     ctrl_area->instrs.INVLPGA = 1;
266
267     guest_state->g_pat = 0x7040600070406ULL;
268
269     guest_state->cr0 |= 0x80000000;
270   } else if (vm_info.page_mode == NESTED_PAGING) {
271     // Flush the TLB on entries/exits
272     //ctrl_area->TLB_CONTROL = 1;
273
274     // Enable Nested Paging
275     //ctrl_area->NP_ENABLE = 1;
276
277     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
278
279         // Set the Nested Page Table pointer
280     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
281     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
282
283     //   ctrl_area->N_CR3 = Get_CR3();
284     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
285
286     //    guest_state->g_pat = 0x7040600070406ULL;
287   }
288
289
290
291 }
292
293
294
295 void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
296   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
297   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
298   uint_t i;
299
300
301   guest_state->rsp = vm_info.vm_regs.rsp;
302   // guest_state->rip = vm_info.rip;
303   guest_state->rip = 0xfff0;
304
305   //ctrl_area->instrs.instrs.CR0 = 1;
306   ctrl_area->cr_reads.cr0 = 1;
307   ctrl_area->cr_writes.cr0 = 1;
308
309   guest_state->efer |= EFER_MSR_svm_enable;
310   guest_state->rflags = 0x00000002; // The reserved bit is always 1
311   ctrl_area->svm_instrs.VMRUN = 1;
312   ctrl_area->instrs.HLT = 1;
313   // guest_state->cr0 = 0x00000001;    // PE 
314   ctrl_area->guest_ASID = 1;
315
316   ctrl_area->exceptions.de = 1;
317   ctrl_area->exceptions.df = 1;
318   ctrl_area->exceptions.pf = 1;
319   ctrl_area->exceptions.ts = 1;
320   ctrl_area->exceptions.ss = 1;
321   ctrl_area->exceptions.ac = 1;
322   ctrl_area->exceptions.mc = 1;
323   ctrl_area->exceptions.gp = 1;
324   ctrl_area->exceptions.ud = 1;
325   ctrl_area->exceptions.np = 1;
326   ctrl_area->exceptions.of = 1;
327   ctrl_area->exceptions.nmi = 1;
328
329   vm_info.vm_regs.rdx = 0x00000f00;
330
331   guest_state->cr0 = 0x60000010;
332
333   guest_state->cs.selector = 0xf000;
334   guest_state->cs.limit=0xffff;
335   guest_state->cs.base = 0x0000000f0000LL;
336   guest_state->cs.attrib.raw = 0xf3;
337
338   
339   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
340   for ( i = 0; segregs[i] != NULL; i++) {
341     struct vmcb_selector * seg = segregs[i];
342     
343     seg->selector = 0x0000;
344     //    seg->base = seg->selector << 4;
345     seg->base = 0x00000000;
346     seg->attrib.raw = 0xf3;
347     seg->limit = ~0u;
348   }
349   
350   guest_state->gdtr.limit = 0x0000ffff;
351   guest_state->gdtr.base = 0x0000000000000000LL;
352   guest_state->idtr.limit = 0x0000ffff;
353   guest_state->idtr.base = 0x0000000000000000LL;
354
355   guest_state->ldtr.selector = 0x0000;
356   guest_state->ldtr.limit = 0x0000ffff;
357   guest_state->ldtr.base = 0x0000000000000000LL;
358   guest_state->tr.selector = 0x0000;
359   guest_state->tr.limit = 0x0000ffff;
360   guest_state->tr.base = 0x0000000000000000LL;
361
362
363   guest_state->dr6 = 0x00000000ffff0ff0LL;
364   guest_state->dr7 = 0x0000000000000400LL;
365
366   if (vm_info.io_map.num_ports > 0) {
367     vmm_io_hook_t * iter;
368     addr_t io_port_bitmap;
369     
370     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
371     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
372     
373     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
374
375     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
376
377     FOREACH_IO_HOOK(vm_info.io_map, iter) {
378       ushort_t port = iter->port;
379       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
380
381       bitmap += (port / 8);
382       PrintDebug("Setting Bit for port 0x%x\n", port);
383       *bitmap |= 1 << (port % 8);
384     }
385
386
387     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
388
389     ctrl_area->instrs.IOIO_PROT = 1;
390   }
391
392
393
394   PrintDebug("Exiting on interrupts\n");
395   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
396   ctrl_area->instrs.INTR = 1;
397
398
399   if (vm_info.page_mode == SHADOW_PAGING) {
400     PrintDebug("Creating initial shadow page table\n");
401     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
402     PrintDebug("Created\n");
403
404     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
405
406     //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
407
408     ctrl_area->cr_reads.cr3 = 1;
409     ctrl_area->cr_writes.cr3 = 1;
410
411
412     ctrl_area->instrs.INVLPG = 1;
413     ctrl_area->instrs.INVLPGA = 1;
414
415     guest_state->g_pat = 0x7040600070406ULL;
416
417     guest_state->cr0 |= 0x80000000;
418   } else if (vm_info.page_mode == NESTED_PAGING) {
419     // Flush the TLB on entries/exits
420     //ctrl_area->TLB_CONTROL = 1;
421
422     // Enable Nested Paging
423     //ctrl_area->NP_ENABLE = 1;
424
425     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
426
427         // Set the Nested Page Table pointer
428     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
429     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
430
431     //   ctrl_area->N_CR3 = Get_CR3();
432     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
433
434     //    guest_state->g_pat = 0x7040600070406ULL;
435   }
436
437
438
439 }
440
441
442 #if 0
443 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
444   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
445   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
446   uint_t i = 0;
447
448
449   guest_state->rsp = vm_info.vm_regs.rsp;
450   guest_state->rip = vm_info.rip;
451
452
453   /* I pretty much just gutted this from TVMM */
454   /* Note: That means its probably wrong */
455
456   // set the segment registers to mirror ours
457   guest_state->cs.selector = 1<<3;
458   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
459   guest_state->cs.attrib.fields.S = 1;
460   guest_state->cs.attrib.fields.P = 1;
461   guest_state->cs.attrib.fields.db = 1;
462   guest_state->cs.attrib.fields.G = 1;
463   guest_state->cs.limit = 0xfffff;
464   guest_state->cs.base = 0;
465   
466   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
467   for ( i = 0; segregs[i] != NULL; i++) {
468     struct vmcb_selector * seg = segregs[i];
469     
470     seg->selector = 2<<3;
471     seg->attrib.fields.type = 0x2; // Data Segment+read/write
472     seg->attrib.fields.S = 1;
473     seg->attrib.fields.P = 1;
474     seg->attrib.fields.db = 1;
475     seg->attrib.fields.G = 1;
476     seg->limit = 0xfffff;
477     seg->base = 0;
478   }
479
480
481   {
482     /* JRL THIS HAS TO GO */
483     
484     //    guest_state->tr.selector = GetTR_Selector();
485     guest_state->tr.attrib.fields.type = 0x9; 
486     guest_state->tr.attrib.fields.P = 1;
487     // guest_state->tr.limit = GetTR_Limit();
488     //guest_state->tr.base = GetTR_Base();// - 0x2000;
489     /* ** */
490   }
491
492
493   /* ** */
494
495
496   guest_state->efer |= EFER_MSR_svm_enable;
497   guest_state->rflags = 0x00000002; // The reserved bit is always 1
498   ctrl_area->svm_instrs.VMRUN = 1;
499   guest_state->cr0 = 0x00000001;    // PE 
500   ctrl_area->guest_ASID = 1;
501
502
503   //  guest_state->cpl = 0;
504
505
506
507   // Setup exits
508
509   ctrl_area->cr_writes.cr4 = 1;
510   
511   ctrl_area->exceptions.de = 1;
512   ctrl_area->exceptions.df = 1;
513   ctrl_area->exceptions.pf = 1;
514   ctrl_area->exceptions.ts = 1;
515   ctrl_area->exceptions.ss = 1;
516   ctrl_area->exceptions.ac = 1;
517   ctrl_area->exceptions.mc = 1;
518   ctrl_area->exceptions.gp = 1;
519   ctrl_area->exceptions.ud = 1;
520   ctrl_area->exceptions.np = 1;
521   ctrl_area->exceptions.of = 1;
522   ctrl_area->exceptions.nmi = 1;
523
524   
525
526   ctrl_area->instrs.IOIO_PROT = 1;
527   ctrl_area->IOPM_BASE_PA = (uint_t)os_hooks->allocate_pages(3);
528   
529   {
530     reg_ex_t tmp_reg;
531     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
532     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
533   }
534
535   ctrl_area->instrs.INTR = 1;
536
537   
538   {
539     char gdt_buf[6];
540     char idt_buf[6];
541
542     memset(gdt_buf, 0, 6);
543     memset(idt_buf, 0, 6);
544
545
546     uint_t gdt_base, idt_base;
547     ushort_t gdt_limit, idt_limit;
548     
549     GetGDTR(gdt_buf);
550     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
551     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
552     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
553
554     GetIDTR(idt_buf);
555     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
556     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
557     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
558
559
560     // gdt_base -= 0x2000;
561     //idt_base -= 0x2000;
562
563     guest_state->gdtr.base = gdt_base;
564     guest_state->gdtr.limit = gdt_limit;
565     guest_state->idtr.base = idt_base;
566     guest_state->idtr.limit = idt_limit;
567
568
569   }
570   
571   
572   // also determine if CPU supports nested paging
573   /*
574   if (vm_info.page_tables) {
575     //   if (0) {
576     // Flush the TLB on entries/exits
577     ctrl_area->TLB_CONTROL = 1;
578
579     // Enable Nested Paging
580     ctrl_area->NP_ENABLE = 1;
581
582     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
583
584         // Set the Nested Page Table pointer
585     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
586
587
588     //   ctrl_area->N_CR3 = Get_CR3();
589     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
590
591     guest_state->g_pat = 0x7040600070406ULL;
592
593     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));
594     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
595     // Enable Paging
596     //    guest_state->cr0 |= 0x80000000;
597   }
598   */
599
600 }
601
602
603
604
605
606 #endif
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621 /*
622
623
624 void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) {
625   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
626   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
627   uint_t i;
628
629
630   guest_state->rsp = vm_info.vm_regs.rsp;
631   guest_state->rip = vm_info.rip;
632
633
634   guest_state->efer |= EFER_MSR_svm_enable;
635   guest_state->rflags = 0x00000002; // The reserved bit is always 1
636   ctrl_area->svm_instrs.instrs.VMRUN = 1;
637   ctrl_area->guest_ASID = 1;
638   guest_state->cr0 = 0x60000010;
639
640
641   ctrl_area->exceptions.de = 1;
642   ctrl_area->exceptions.df = 1;
643   ctrl_area->exceptions.pf = 1;
644   ctrl_area->exceptions.ts = 1;
645   ctrl_area->exceptions.ss = 1;
646   ctrl_area->exceptions.ac = 1;
647   ctrl_area->exceptions.mc = 1;
648   ctrl_area->exceptions.gp = 1;
649   ctrl_area->exceptions.ud = 1;
650   ctrl_area->exceptions.np = 1;
651   ctrl_area->exceptions.of = 1;
652   ctrl_area->exceptions.nmi = 1;
653
654   guest_state->cs.selector = 0xf000;
655   guest_state->cs.limit=0xffff;
656   guest_state->cs.base =  0xffff0000;
657   guest_state->cs.attrib.raw = 0x9a;
658
659   
660   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
661   for ( i = 0; segregs[i] != NULL; i++) {
662     struct vmcb_selector * seg = segregs[i];
663     
664     seg->selector = 0x0000;
665     seg->base = 0xffff0000;
666     seg->attrib.raw = 0x9b;
667     seg->limit = 0xffff;
668   }
669   
670   // Set GPRs 
671   //
672   //  EDX == 0xfxx
673   //  EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0
674   //
675
676   guest_state->gdtr.base = 0;
677   guest_state->gdtr.limit = 0xffff;
678   guest_state->gdtr.attrib.raw = 0x0;
679
680   guest_state->idtr.base = 0;
681   guest_state->idtr.limit = 0xffff;
682   guest_state->idtr.attrib.raw = 0x0;
683
684   guest_state->ldtr.base = 0;
685   guest_state->ldtr.limit = 0xffff;
686   guest_state->ldtr.attrib.raw = 0x82;
687
688   guest_state->tr.base = 0;
689   guest_state->tr.limit = 0xffff;
690   guest_state->tr.attrib.raw = 0x83;
691
692
693
694
695   if (vm_info.io_map.num_ports > 0) {
696     vmm_io_hook_t * iter;
697     addr_t io_port_bitmap;
698     
699     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
700     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
701     
702     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
703
704     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
705
706     FOREACH_IO_HOOK(vm_info.io_map, iter) {
707       ushort_t port = iter->port;
708       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
709
710       bitmap += (port / 8);
711       PrintDebug("Setting Bit in block %x\n", bitmap);
712       *bitmap |= 1 << (port % 8);
713     }
714
715     ctrl_area->instrs.instrs.IOIO_PROT = 1;
716   }
717
718   ctrl_area->instrs.instrs.INTR = 1;
719
720   // also determine if CPU supports nested paging
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.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
725     PrintDebug("Created\n");
726
727     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
728
729     ctrl_area->cr_reads.crs.cr3 = 1;
730     ctrl_area->cr_writes.crs.cr3 = 1;
731     ctrl_area->cr_reads.crs.cr0 = 1;
732     ctrl_area->cr_writes.crs.cr0 = 1;
733
734     ctrl_area->instrs.instrs.INVLPG = 1;
735     ctrl_area->instrs.instrs.INVLPGA = 1;
736
737         
738     guest_state->g_pat = 0x7040600070406ULL;
739
740     vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0;
741     guest_state->cr0 |= 0x80000000;
742   } else if (vm_info.page_mode == NESTED_PAGING) {
743     // Flush the TLB on entries/exits
744     //ctrl_area->TLB_CONTROL = 1;
745
746     // Enable Nested Paging
747     //ctrl_area->NP_ENABLE = 1;
748
749     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
750
751         // Set the Nested Page Table pointer
752     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
753     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
754
755     //   ctrl_area->N_CR3 = Get_CR3();
756     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
757
758     //    guest_state->g_pat = 0x7040600070406ULL;
759   }
760
761 }
762 */