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.


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