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.


something that sort of works more than it did previously....
[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   // guest_state->cr0 = 0x00000001;    // PE 
313   ctrl_area->guest_ASID = 1;
314
315   ctrl_area->exceptions.de = 1;
316   ctrl_area->exceptions.df = 1;
317   ctrl_area->exceptions.pf = 1;
318   ctrl_area->exceptions.ts = 1;
319   ctrl_area->exceptions.ss = 1;
320   ctrl_area->exceptions.ac = 1;
321   ctrl_area->exceptions.mc = 1;
322   ctrl_area->exceptions.gp = 1;
323   ctrl_area->exceptions.ud = 1;
324   ctrl_area->exceptions.np = 1;
325   ctrl_area->exceptions.of = 1;
326   ctrl_area->exceptions.nmi = 1;
327
328   vm_info.vm_regs.rdx = 0x00000f00;
329
330   guest_state->cr0 = 0x60000010;
331
332   guest_state->cs.selector = 0xf000;
333   guest_state->cs.limit=0xffff;
334   guest_state->cs.base = 0x0000000f0000LL;
335   guest_state->cs.attrib.raw = 0xf3;
336
337   
338   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
339   for ( i = 0; segregs[i] != NULL; i++) {
340     struct vmcb_selector * seg = segregs[i];
341     
342     seg->selector = 0x0000;
343     //    seg->base = seg->selector << 4;
344     seg->base = 0x00000000;
345     seg->attrib.raw = 0xf3;
346     seg->limit = ~0u;
347   }
348   
349   guest_state->gdtr.limit = 0x0000ffff;
350   guest_state->gdtr.base = 0x0000000000000000LL;
351   guest_state->idtr.limit = 0x0000ffff;
352   guest_state->idtr.base = 0x0000000000000000LL;
353
354   guest_state->ldtr.selector = 0x0000;
355   guest_state->ldtr.limit = 0x0000ffff;
356   guest_state->ldtr.base = 0x0000000000000000LL;
357   guest_state->tr.selector = 0x0000;
358   guest_state->tr.limit = 0x0000ffff;
359   guest_state->tr.base = 0x0000000000000000LL;
360
361
362   guest_state->dr6 = 0x00000000ffff0ff0LL;
363   guest_state->dr7 = 0x0000000000000400LL;
364
365   if (vm_info.io_map.num_ports > 0) {
366     vmm_io_hook_t * iter;
367     addr_t io_port_bitmap;
368     
369     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
370     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
371     
372     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
373
374     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
375
376     FOREACH_IO_HOOK(vm_info.io_map, iter) {
377       ushort_t port = iter->port;
378       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
379
380       bitmap += (port / 8);
381       PrintDebug("Setting Bit for port 0x%x\n", port);
382       *bitmap |= 1 << (port % 8);
383     }
384
385
386     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
387
388     ctrl_area->instrs.IOIO_PROT = 1;
389   }
390
391
392
393   PrintDebug("Exiting on interrupts\n");
394   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
395   ctrl_area->instrs.INTR = 1;
396
397
398   if (vm_info.page_mode == SHADOW_PAGING) {
399     PrintDebug("Creating initial shadow page table\n");
400     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
401     PrintDebug("Created\n");
402
403     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
404
405     //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
406
407     ctrl_area->cr_reads.cr3 = 1;
408     ctrl_area->cr_writes.cr3 = 1;
409
410
411     ctrl_area->instrs.INVLPG = 1;
412     ctrl_area->instrs.INVLPGA = 1;
413
414     guest_state->g_pat = 0x7040600070406ULL;
415
416     guest_state->cr0 |= 0x80000000;
417   } else if (vm_info.page_mode == NESTED_PAGING) {
418     // Flush the TLB on entries/exits
419     //ctrl_area->TLB_CONTROL = 1;
420
421     // Enable Nested Paging
422     //ctrl_area->NP_ENABLE = 1;
423
424     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
425
426         // Set the Nested Page Table pointer
427     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
428     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
429
430     //   ctrl_area->N_CR3 = Get_CR3();
431     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
432
433     //    guest_state->g_pat = 0x7040600070406ULL;
434   }
435
436
437
438 }
439
440
441 #if 0
442 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
443   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
444   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
445   uint_t i = 0;
446
447
448   guest_state->rsp = vm_info.vm_regs.rsp;
449   guest_state->rip = vm_info.rip;
450
451
452   /* I pretty much just gutted this from TVMM */
453   /* Note: That means its probably wrong */
454
455   // set the segment registers to mirror ours
456   guest_state->cs.selector = 1<<3;
457   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
458   guest_state->cs.attrib.fields.S = 1;
459   guest_state->cs.attrib.fields.P = 1;
460   guest_state->cs.attrib.fields.db = 1;
461   guest_state->cs.attrib.fields.G = 1;
462   guest_state->cs.limit = 0xfffff;
463   guest_state->cs.base = 0;
464   
465   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
466   for ( i = 0; segregs[i] != NULL; i++) {
467     struct vmcb_selector * seg = segregs[i];
468     
469     seg->selector = 2<<3;
470     seg->attrib.fields.type = 0x2; // Data Segment+read/write
471     seg->attrib.fields.S = 1;
472     seg->attrib.fields.P = 1;
473     seg->attrib.fields.db = 1;
474     seg->attrib.fields.G = 1;
475     seg->limit = 0xfffff;
476     seg->base = 0;
477   }
478
479
480   {
481     /* JRL THIS HAS TO GO */
482     
483     //    guest_state->tr.selector = GetTR_Selector();
484     guest_state->tr.attrib.fields.type = 0x9; 
485     guest_state->tr.attrib.fields.P = 1;
486     // guest_state->tr.limit = GetTR_Limit();
487     //guest_state->tr.base = GetTR_Base();// - 0x2000;
488     /* ** */
489   }
490
491
492   /* ** */
493
494
495   guest_state->efer |= EFER_MSR_svm_enable;
496   guest_state->rflags = 0x00000002; // The reserved bit is always 1
497   ctrl_area->svm_instrs.VMRUN = 1;
498   guest_state->cr0 = 0x00000001;    // PE 
499   ctrl_area->guest_ASID = 1;
500
501
502   //  guest_state->cpl = 0;
503
504
505
506   // Setup exits
507
508   ctrl_area->cr_writes.cr4 = 1;
509   
510   ctrl_area->exceptions.de = 1;
511   ctrl_area->exceptions.df = 1;
512   ctrl_area->exceptions.pf = 1;
513   ctrl_area->exceptions.ts = 1;
514   ctrl_area->exceptions.ss = 1;
515   ctrl_area->exceptions.ac = 1;
516   ctrl_area->exceptions.mc = 1;
517   ctrl_area->exceptions.gp = 1;
518   ctrl_area->exceptions.ud = 1;
519   ctrl_area->exceptions.np = 1;
520   ctrl_area->exceptions.of = 1;
521   ctrl_area->exceptions.nmi = 1;
522
523   
524
525   ctrl_area->instrs.IOIO_PROT = 1;
526   ctrl_area->IOPM_BASE_PA = (uint_t)os_hooks->allocate_pages(3);
527   
528   {
529     reg_ex_t tmp_reg;
530     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
531     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
532   }
533
534   ctrl_area->instrs.INTR = 1;
535
536   
537   {
538     char gdt_buf[6];
539     char idt_buf[6];
540
541     memset(gdt_buf, 0, 6);
542     memset(idt_buf, 0, 6);
543
544
545     uint_t gdt_base, idt_base;
546     ushort_t gdt_limit, idt_limit;
547     
548     GetGDTR(gdt_buf);
549     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
550     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
551     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
552
553     GetIDTR(idt_buf);
554     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
555     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
556     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
557
558
559     // gdt_base -= 0x2000;
560     //idt_base -= 0x2000;
561
562     guest_state->gdtr.base = gdt_base;
563     guest_state->gdtr.limit = gdt_limit;
564     guest_state->idtr.base = idt_base;
565     guest_state->idtr.limit = idt_limit;
566
567
568   }
569   
570   
571   // also determine if CPU supports nested paging
572   /*
573   if (vm_info.page_tables) {
574     //   if (0) {
575     // Flush the TLB on entries/exits
576     ctrl_area->TLB_CONTROL = 1;
577
578     // Enable Nested Paging
579     ctrl_area->NP_ENABLE = 1;
580
581     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
582
583         // Set the Nested Page Table pointer
584     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
585
586
587     //   ctrl_area->N_CR3 = Get_CR3();
588     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
589
590     guest_state->g_pat = 0x7040600070406ULL;
591
592     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));
593     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
594     // Enable Paging
595     //    guest_state->cr0 |= 0x80000000;
596   }
597   */
598
599 }
600
601
602
603
604
605 #endif
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620 /*
621
622
623 void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) {
624   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
625   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
626   uint_t i;
627
628
629   guest_state->rsp = vm_info.vm_regs.rsp;
630   guest_state->rip = vm_info.rip;
631
632
633   guest_state->efer |= EFER_MSR_svm_enable;
634   guest_state->rflags = 0x00000002; // The reserved bit is always 1
635   ctrl_area->svm_instrs.instrs.VMRUN = 1;
636   ctrl_area->guest_ASID = 1;
637   guest_state->cr0 = 0x60000010;
638
639
640   ctrl_area->exceptions.de = 1;
641   ctrl_area->exceptions.df = 1;
642   ctrl_area->exceptions.pf = 1;
643   ctrl_area->exceptions.ts = 1;
644   ctrl_area->exceptions.ss = 1;
645   ctrl_area->exceptions.ac = 1;
646   ctrl_area->exceptions.mc = 1;
647   ctrl_area->exceptions.gp = 1;
648   ctrl_area->exceptions.ud = 1;
649   ctrl_area->exceptions.np = 1;
650   ctrl_area->exceptions.of = 1;
651   ctrl_area->exceptions.nmi = 1;
652
653   guest_state->cs.selector = 0xf000;
654   guest_state->cs.limit=0xffff;
655   guest_state->cs.base =  0xffff0000;
656   guest_state->cs.attrib.raw = 0x9a;
657
658   
659   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
660   for ( i = 0; segregs[i] != NULL; i++) {
661     struct vmcb_selector * seg = segregs[i];
662     
663     seg->selector = 0x0000;
664     seg->base = 0xffff0000;
665     seg->attrib.raw = 0x9b;
666     seg->limit = 0xffff;
667   }
668   
669   // Set GPRs 
670   //
671   //  EDX == 0xfxx
672   //  EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0
673   //
674
675   guest_state->gdtr.base = 0;
676   guest_state->gdtr.limit = 0xffff;
677   guest_state->gdtr.attrib.raw = 0x0;
678
679   guest_state->idtr.base = 0;
680   guest_state->idtr.limit = 0xffff;
681   guest_state->idtr.attrib.raw = 0x0;
682
683   guest_state->ldtr.base = 0;
684   guest_state->ldtr.limit = 0xffff;
685   guest_state->ldtr.attrib.raw = 0x82;
686
687   guest_state->tr.base = 0;
688   guest_state->tr.limit = 0xffff;
689   guest_state->tr.attrib.raw = 0x83;
690
691
692
693
694   if (vm_info.io_map.num_ports > 0) {
695     vmm_io_hook_t * iter;
696     addr_t io_port_bitmap;
697     
698     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
699     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
700     
701     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
702
703     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
704
705     FOREACH_IO_HOOK(vm_info.io_map, iter) {
706       ushort_t port = iter->port;
707       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
708
709       bitmap += (port / 8);
710       PrintDebug("Setting Bit in block %x\n", bitmap);
711       *bitmap |= 1 << (port % 8);
712     }
713
714     ctrl_area->instrs.instrs.IOIO_PROT = 1;
715   }
716
717   ctrl_area->instrs.instrs.INTR = 1;
718
719   // also determine if CPU supports nested paging
720
721   if (vm_info.page_mode == SHADOW_PAGING) {
722     PrintDebug("Creating initial shadow page table\n");
723     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
724     PrintDebug("Created\n");
725
726     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
727
728     ctrl_area->cr_reads.crs.cr3 = 1;
729     ctrl_area->cr_writes.crs.cr3 = 1;
730     ctrl_area->cr_reads.crs.cr0 = 1;
731     ctrl_area->cr_writes.crs.cr0 = 1;
732
733     ctrl_area->instrs.instrs.INVLPG = 1;
734     ctrl_area->instrs.instrs.INVLPGA = 1;
735
736         
737     guest_state->g_pat = 0x7040600070406ULL;
738
739     vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0;
740     guest_state->cr0 |= 0x80000000;
741   } else if (vm_info.page_mode == NESTED_PAGING) {
742     // Flush the TLB on entries/exits
743     //ctrl_area->TLB_CONTROL = 1;
744
745     // Enable Nested Paging
746     //ctrl_area->NP_ENABLE = 1;
747
748     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
749
750         // Set the Nested Page Table pointer
751     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
752     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
753
754     //   ctrl_area->N_CR3 = Get_CR3();
755     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
756
757     //    guest_state->g_pat = 0x7040600070406ULL;
758   }
759
760 }
761 */