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.


moved over the a real linked list implementation
[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 uint_t Get_CR3();
24
25 extern void GetGDTR(void * gdt);
26 extern void GetIDTR(void * idt);
27
28 extern void DisableInts();
29
30 /* Checks machine SVM capability */
31 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
32 int is_svm_capable() {
33   uint_t ret =  cpuid_ecx(CPUID_FEATURE_IDS);
34   uint_t vm_cr_low = 0, vm_cr_high = 0;
35
36
37   if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
38     PrintDebug("SVM Not Available\n");
39     return 0;
40   } 
41
42   Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
43
44   if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
45     PrintDebug("Nested Paging not supported\n");
46   }
47
48   if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
49     return 1;
50   }
51
52   ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS);
53
54   if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
55     PrintDebug("SVM BIOS Disabled, not unlockable\n");
56   } else {
57     PrintDebug("SVM is locked with a key\n");
58   }
59
60   return 0;
61 }
62
63
64
65 void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
66   reg_ex_t msr;
67   void * host_state;
68
69
70   // Enable SVM on the CPU
71   Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
72   msr.e_reg.low |= EFER_MSR_svm_enable;
73   Set_MSR(EFER_MSR, 0, msr.e_reg.low);
74   
75   PrintDebug("SVM Enabled\n");
76
77
78   // Setup the host state save area
79   host_state = os_hooks->allocate_pages(4);
80   
81   msr.e_reg.high = 0;
82   msr.e_reg.low = (uint_t)host_state;
83
84
85   PrintDebug("Host State being saved at %x\n", (uint_t)host_state);
86   Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
87
88
89
90   // Setup the SVM specific vmm operations
91   vmm_ops->init_guest = &init_svm_guest;
92   vmm_ops->start_guest = &start_svm_guest;
93
94
95   return;
96 }
97
98
99 int init_svm_guest(struct guest_info *info) {
100  
101   PrintDebug("Allocating VMCB\n");
102   info->vmm_data = (void*)Allocate_VMCB();
103
104
105   //PrintDebug("Generating Guest nested page tables\n");
106   //  info->page_tables = NULL;
107   //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
108   //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
109   //  PrintDebugPageTables(info->page_tables);
110
111
112   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
113   Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), *info);
114   
115
116   //  info->rip = 0;
117
118   info->vm_regs.rdi = 0;
119   info->vm_regs.rsi = 0;
120   info->vm_regs.rbp = 0;
121   info->vm_regs.rsp = 0;
122   info->vm_regs.rbx = 0;
123   info->vm_regs.rdx = 0;
124   info->vm_regs.rcx = 0;
125   info->vm_regs.rax = 0;
126   
127   return 0;
128 }
129
130
131 // can we start a kernel thread here...
132 int start_svm_guest(struct guest_info *info) {
133
134
135
136   PrintDebug("Launching SVM VM (vmcb=%x)\n", info->vmm_data);
137   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
138
139   while (1) {
140
141     //PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data,  &(info->vm_regs));
142     //PrintDebug("Launching to RIP: %x\n", info->rip);
143     safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
144     //launch_svm((vmcb_t*)(info->vmm_data));
145     //PrintDebug("SVM Returned\n");
146
147     if (handle_svm_exit(info) != 0) {
148       // handle exit code....
149       break;
150     }
151   }
152   return 0;
153 }
154
155
156
157 vmcb_t * Allocate_VMCB() {
158   vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
159
160
161   memset(vmcb_page, 0, 4096);
162
163   return vmcb_page;
164 }
165
166
167
168 void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
169   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
170   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
171   uint_t i;
172
173
174   guest_state->rsp = vm_info.vm_regs.rsp;
175   guest_state->rip = vm_info.rip;
176
177
178   //ctrl_area->instrs.instrs.CR0 = 1;
179   ctrl_area->cr_reads.cr0 = 1;
180   ctrl_area->cr_writes.cr0 = 1;
181
182   guest_state->efer |= EFER_MSR_svm_enable;
183   guest_state->rflags = 0x00000002; // The reserved bit is always 1
184   ctrl_area->svm_instrs.VMRUN = 1;
185   // guest_state->cr0 = 0x00000001;    // PE 
186   ctrl_area->guest_ASID = 1;
187
188
189   ctrl_area->exceptions.de = 1;
190   ctrl_area->exceptions.df = 1;
191   ctrl_area->exceptions.pf = 1;
192   ctrl_area->exceptions.ts = 1;
193   ctrl_area->exceptions.ss = 1;
194   ctrl_area->exceptions.ac = 1;
195   ctrl_area->exceptions.mc = 1;
196   ctrl_area->exceptions.gp = 1;
197   ctrl_area->exceptions.ud = 1;
198   ctrl_area->exceptions.np = 1;
199   ctrl_area->exceptions.of = 1;
200   ctrl_area->exceptions.nmi = 1;
201
202   guest_state->cs.selector = 0x0000;
203   guest_state->cs.limit=~0u;
204   guest_state->cs.base = guest_state->cs.selector<<4;
205   guest_state->cs.attrib.raw = 0xf3;
206
207   
208   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
209   for ( i = 0; segregs[i] != NULL; i++) {
210     struct vmcb_selector * seg = segregs[i];
211     
212     seg->selector = 0x0000;
213     seg->base = seg->selector << 4;
214     seg->attrib.raw = 0xf3;
215     seg->limit = ~0u;
216   }
217   
218   if (vm_info.io_map.num_ports > 0) {
219     vmm_io_hook_t * iter;
220     addr_t io_port_bitmap;
221     
222     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
223     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
224     
225     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
226
227     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
228
229     FOREACH_IO_HOOK(vm_info.io_map, iter) {
230       ushort_t port = iter->port;
231       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
232
233       bitmap += (port / 8);
234       PrintDebug("Setting Bit in block %x\n", bitmap);
235       *bitmap |= 1 << (port % 8);
236     }
237
238
239     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
240
241     ctrl_area->instrs.IOIO_PROT = 1;
242   }
243
244   ctrl_area->instrs.INTR = 1;
245
246
247
248   if (vm_info.page_mode == SHADOW_PAGING) {
249     PrintDebug("Creating initial shadow page table\n");
250     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
251     PrintDebug("Created\n");
252
253     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
254
255     ctrl_area->cr_reads.cr3 = 1;
256     ctrl_area->cr_writes.cr3 = 1;
257
258
259     ctrl_area->instrs.INVLPG = 1;
260     ctrl_area->instrs.INVLPGA = 1;
261
262     guest_state->g_pat = 0x7040600070406ULL;
263
264     guest_state->cr0 |= 0x80000000;
265   } else if (vm_info.page_mode == NESTED_PAGING) {
266     // Flush the TLB on entries/exits
267     //ctrl_area->TLB_CONTROL = 1;
268
269     // Enable Nested Paging
270     //ctrl_area->NP_ENABLE = 1;
271
272     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
273
274         // Set the Nested Page Table pointer
275     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
276     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
277
278     //   ctrl_area->N_CR3 = Get_CR3();
279     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
280
281     //    guest_state->g_pat = 0x7040600070406ULL;
282   }
283
284
285
286 }
287
288
289
290 void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
291   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
292   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
293   uint_t i;
294
295
296   guest_state->rsp = vm_info.vm_regs.rsp;
297   // guest_state->rip = vm_info.rip;
298   guest_state->rip = 0xfff0;
299
300   //ctrl_area->instrs.instrs.CR0 = 1;
301   ctrl_area->cr_reads.cr0 = 1;
302   ctrl_area->cr_writes.cr0 = 1;
303
304   guest_state->efer |= EFER_MSR_svm_enable;
305   guest_state->rflags = 0x00000002; // The reserved bit is always 1
306   ctrl_area->svm_instrs.VMRUN = 1;
307   // guest_state->cr0 = 0x00000001;    // PE 
308   ctrl_area->guest_ASID = 1;
309
310   ctrl_area->exceptions.de = 1;
311   ctrl_area->exceptions.df = 1;
312   ctrl_area->exceptions.pf = 1;
313   ctrl_area->exceptions.ts = 1;
314   ctrl_area->exceptions.ss = 1;
315   ctrl_area->exceptions.ac = 1;
316   ctrl_area->exceptions.mc = 1;
317   ctrl_area->exceptions.gp = 1;
318   ctrl_area->exceptions.ud = 1;
319   ctrl_area->exceptions.np = 1;
320   ctrl_area->exceptions.of = 1;
321   ctrl_area->exceptions.nmi = 1;
322
323   vm_info.vm_regs.rdx = 0x00000f00;
324
325   guest_state->cr0 = 0x60000010;
326
327   guest_state->cs.selector = 0xf000;
328   guest_state->cs.limit=0xffff;
329   guest_state->cs.base = 0x0000000f0000LL;
330   guest_state->cs.attrib.raw = 0xf3;
331
332   
333   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
334   for ( i = 0; segregs[i] != NULL; i++) {
335     struct vmcb_selector * seg = segregs[i];
336     
337     seg->selector = 0x0000;
338     //    seg->base = seg->selector << 4;
339     seg->base = 0x00000000;
340     seg->attrib.raw = 0xf3;
341     seg->limit = ~0u;
342   }
343   
344   guest_state->gdtr.limit = 0x0000ffff;
345   guest_state->gdtr.base = 0x0000000000000000LL;
346   guest_state->idtr.limit = 0x0000ffff;
347   guest_state->idtr.base = 0x0000000000000000LL;
348
349   guest_state->ldtr.selector = 0x0000;
350   guest_state->ldtr.limit = 0x0000ffff;
351   guest_state->ldtr.base = 0x0000000000000000LL;
352   guest_state->tr.selector = 0x0000;
353   guest_state->tr.limit = 0x0000ffff;
354   guest_state->tr.base = 0x0000000000000000LL;
355
356
357   guest_state->dr6 = 0x00000000ffff0ff0LL;
358   guest_state->dr7 = 0x0000000000000400LL;
359
360   if (vm_info.io_map.num_ports > 0) {
361     vmm_io_hook_t * iter;
362     addr_t io_port_bitmap;
363     
364     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
365     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
366     
367     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
368
369     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
370
371     FOREACH_IO_HOOK(vm_info.io_map, iter) {
372       ushort_t port = iter->port;
373       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
374
375       bitmap += (port / 8);
376       PrintDebug("Setting Bit for port 0x%x\n", port);
377       *bitmap |= 1 << (port % 8);
378     }
379
380
381     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
382
383     ctrl_area->instrs.IOIO_PROT = 1;
384   }
385
386
387   if (vm_info.irq_map.num_hooks > 0) {
388     PrintDebug("Exiting on interrupts\n");
389     ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
390     ctrl_area->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 */