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     
151
152     STGI();
153
154      
155     if (handle_svm_exit(info) != 0) {
156       PrintDebug("SVM ERROR!!\n");
157       break;
158     }
159   }
160   return 0;
161 }
162
163
164
165 vmcb_t * Allocate_VMCB() {
166   vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
167
168
169   memset(vmcb_page, 0, 4096);
170
171   return vmcb_page;
172 }
173
174
175
176 void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
177   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
178   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
179   uint_t i;
180
181
182   guest_state->rsp = vm_info.vm_regs.rsp;
183   guest_state->rip = vm_info.rip;
184
185
186   //ctrl_area->instrs.instrs.CR0 = 1;
187   ctrl_area->cr_reads.cr0 = 1;
188   ctrl_area->cr_writes.cr0 = 1;
189
190   guest_state->efer |= EFER_MSR_svm_enable;
191   guest_state->rflags = 0x00000002; // The reserved bit is always 1
192   ctrl_area->svm_instrs.VMRUN = 1;
193   // guest_state->cr0 = 0x00000001;    // PE 
194   ctrl_area->guest_ASID = 1;
195
196
197   ctrl_area->exceptions.de = 1;
198   ctrl_area->exceptions.df = 1;
199   ctrl_area->exceptions.pf = 1;
200   ctrl_area->exceptions.ts = 1;
201   ctrl_area->exceptions.ss = 1;
202   ctrl_area->exceptions.ac = 1;
203   ctrl_area->exceptions.mc = 1;
204   ctrl_area->exceptions.gp = 1;
205   ctrl_area->exceptions.ud = 1;
206   ctrl_area->exceptions.np = 1;
207   ctrl_area->exceptions.of = 1;
208   ctrl_area->exceptions.nmi = 1;
209
210   guest_state->cs.selector = 0x0000;
211   guest_state->cs.limit=~0u;
212   guest_state->cs.base = guest_state->cs.selector<<4;
213   guest_state->cs.attrib.raw = 0xf3;
214
215   
216   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
217   for ( i = 0; segregs[i] != NULL; i++) {
218     struct vmcb_selector * seg = segregs[i];
219     
220     seg->selector = 0x0000;
221     seg->base = seg->selector << 4;
222     seg->attrib.raw = 0xf3;
223     seg->limit = ~0u;
224   }
225   
226   if (vm_info.io_map.num_ports > 0) {
227     vmm_io_hook_t * iter;
228     addr_t io_port_bitmap;
229     
230     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
231     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
232     
233     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
234
235     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
236
237     FOREACH_IO_HOOK(vm_info.io_map, iter) {
238       ushort_t port = iter->port;
239       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
240
241       bitmap += (port / 8);
242       PrintDebug("Setting Bit in block %x\n", bitmap);
243       *bitmap |= 1 << (port % 8);
244     }
245
246
247     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
248
249     ctrl_area->instrs.IOIO_PROT = 1;
250   }
251
252   ctrl_area->instrs.INTR = 1;
253
254
255
256   if (vm_info.page_mode == SHADOW_PAGING) {
257     PrintDebug("Creating initial shadow page table\n");
258     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
259     PrintDebug("Created\n");
260
261     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
262
263     ctrl_area->cr_reads.cr3 = 1;
264     ctrl_area->cr_writes.cr3 = 1;
265
266
267     ctrl_area->instrs.INVLPG = 1;
268     ctrl_area->instrs.INVLPGA = 1;
269
270     guest_state->g_pat = 0x7040600070406ULL;
271
272     guest_state->cr0 |= 0x80000000;
273   } else if (vm_info.page_mode == NESTED_PAGING) {
274     // Flush the TLB on entries/exits
275     //ctrl_area->TLB_CONTROL = 1;
276
277     // Enable Nested Paging
278     //ctrl_area->NP_ENABLE = 1;
279
280     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
281
282         // Set the Nested Page Table pointer
283     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
284     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
285
286     //   ctrl_area->N_CR3 = Get_CR3();
287     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
288
289     //    guest_state->g_pat = 0x7040600070406ULL;
290   }
291
292
293
294 }
295
296
297
298 void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
299   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
300   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
301   uint_t i;
302
303
304   guest_state->rsp = vm_info.vm_regs.rsp;
305   // guest_state->rip = vm_info.rip;
306   guest_state->rip = 0xfff0;
307
308   //ctrl_area->instrs.instrs.CR0 = 1;
309   ctrl_area->cr_reads.cr0 = 1;
310   ctrl_area->cr_writes.cr0 = 1;
311
312   guest_state->efer |= EFER_MSR_svm_enable;
313   guest_state->rflags = 0x00000002; // The reserved bit is always 1
314   ctrl_area->svm_instrs.VMRUN = 1;
315   ctrl_area->instrs.HLT = 1;
316   // guest_state->cr0 = 0x00000001;    // PE 
317   ctrl_area->guest_ASID = 1;
318
319   ctrl_area->exceptions.de = 1;
320   ctrl_area->exceptions.df = 1;
321   ctrl_area->exceptions.pf = 1;
322   ctrl_area->exceptions.ts = 1;
323   ctrl_area->exceptions.ss = 1;
324   ctrl_area->exceptions.ac = 1;
325   ctrl_area->exceptions.mc = 1;
326   ctrl_area->exceptions.gp = 1;
327   ctrl_area->exceptions.ud = 1;
328   ctrl_area->exceptions.np = 1;
329   ctrl_area->exceptions.of = 1;
330   ctrl_area->exceptions.nmi = 1;
331
332   vm_info.vm_regs.rdx = 0x00000f00;
333
334   guest_state->cr0 = 0x60000010;
335
336   guest_state->cs.selector = 0xf000;
337   guest_state->cs.limit=0xffff;
338   guest_state->cs.base = 0x0000000f0000LL;
339   guest_state->cs.attrib.raw = 0xf3;
340
341   
342   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
343   for ( i = 0; segregs[i] != NULL; i++) {
344     struct vmcb_selector * seg = segregs[i];
345     
346     seg->selector = 0x0000;
347     //    seg->base = seg->selector << 4;
348     seg->base = 0x00000000;
349     seg->attrib.raw = 0xf3;
350     seg->limit = ~0u;
351   }
352   
353   guest_state->gdtr.limit = 0x0000ffff;
354   guest_state->gdtr.base = 0x0000000000000000LL;
355   guest_state->idtr.limit = 0x0000ffff;
356   guest_state->idtr.base = 0x0000000000000000LL;
357
358   guest_state->ldtr.selector = 0x0000;
359   guest_state->ldtr.limit = 0x0000ffff;
360   guest_state->ldtr.base = 0x0000000000000000LL;
361   guest_state->tr.selector = 0x0000;
362   guest_state->tr.limit = 0x0000ffff;
363   guest_state->tr.base = 0x0000000000000000LL;
364
365
366   guest_state->dr6 = 0x00000000ffff0ff0LL;
367   guest_state->dr7 = 0x0000000000000400LL;
368
369   if (vm_info.io_map.num_ports > 0) {
370     vmm_io_hook_t * iter;
371     addr_t io_port_bitmap;
372     
373     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
374     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
375     
376     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
377
378     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
379
380     FOREACH_IO_HOOK(vm_info.io_map, iter) {
381       ushort_t port = iter->port;
382       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
383
384       bitmap += (port / 8);
385       PrintDebug("Setting Bit for port 0x%x\n", port);
386       *bitmap |= 1 << (port % 8);
387     }
388
389
390     //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
391
392     ctrl_area->instrs.IOIO_PROT = 1;
393   }
394
395
396
397   PrintDebug("Exiting on interrupts\n");
398   ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
399   ctrl_area->instrs.INTR = 1;
400
401
402   if (vm_info.page_mode == SHADOW_PAGING) {
403     PrintDebug("Creating initial shadow page table\n");
404     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
405     PrintDebug("Created\n");
406
407     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
408
409     //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
410
411     ctrl_area->cr_reads.cr3 = 1;
412     ctrl_area->cr_writes.cr3 = 1;
413
414
415     ctrl_area->instrs.INVLPG = 1;
416     ctrl_area->instrs.INVLPGA = 1;
417
418     guest_state->g_pat = 0x7040600070406ULL;
419
420     guest_state->cr0 |= 0x80000000;
421   } else if (vm_info.page_mode == NESTED_PAGING) {
422     // Flush the TLB on entries/exits
423     //ctrl_area->TLB_CONTROL = 1;
424
425     // Enable Nested Paging
426     //ctrl_area->NP_ENABLE = 1;
427
428     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
429
430         // Set the Nested Page Table pointer
431     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
432     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
433
434     //   ctrl_area->N_CR3 = Get_CR3();
435     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
436
437     //    guest_state->g_pat = 0x7040600070406ULL;
438   }
439
440
441
442 }
443
444
445 #if 0
446 void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
447   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
448   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
449   uint_t i = 0;
450
451
452   guest_state->rsp = vm_info.vm_regs.rsp;
453   guest_state->rip = vm_info.rip;
454
455
456   /* I pretty much just gutted this from TVMM */
457   /* Note: That means its probably wrong */
458
459   // set the segment registers to mirror ours
460   guest_state->cs.selector = 1<<3;
461   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
462   guest_state->cs.attrib.fields.S = 1;
463   guest_state->cs.attrib.fields.P = 1;
464   guest_state->cs.attrib.fields.db = 1;
465   guest_state->cs.attrib.fields.G = 1;
466   guest_state->cs.limit = 0xfffff;
467   guest_state->cs.base = 0;
468   
469   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
470   for ( i = 0; segregs[i] != NULL; i++) {
471     struct vmcb_selector * seg = segregs[i];
472     
473     seg->selector = 2<<3;
474     seg->attrib.fields.type = 0x2; // Data Segment+read/write
475     seg->attrib.fields.S = 1;
476     seg->attrib.fields.P = 1;
477     seg->attrib.fields.db = 1;
478     seg->attrib.fields.G = 1;
479     seg->limit = 0xfffff;
480     seg->base = 0;
481   }
482
483
484   {
485     /* JRL THIS HAS TO GO */
486     
487     //    guest_state->tr.selector = GetTR_Selector();
488     guest_state->tr.attrib.fields.type = 0x9; 
489     guest_state->tr.attrib.fields.P = 1;
490     // guest_state->tr.limit = GetTR_Limit();
491     //guest_state->tr.base = GetTR_Base();// - 0x2000;
492     /* ** */
493   }
494
495
496   /* ** */
497
498
499   guest_state->efer |= EFER_MSR_svm_enable;
500   guest_state->rflags = 0x00000002; // The reserved bit is always 1
501   ctrl_area->svm_instrs.VMRUN = 1;
502   guest_state->cr0 = 0x00000001;    // PE 
503   ctrl_area->guest_ASID = 1;
504
505
506   //  guest_state->cpl = 0;
507
508
509
510   // Setup exits
511
512   ctrl_area->cr_writes.cr4 = 1;
513   
514   ctrl_area->exceptions.de = 1;
515   ctrl_area->exceptions.df = 1;
516   ctrl_area->exceptions.pf = 1;
517   ctrl_area->exceptions.ts = 1;
518   ctrl_area->exceptions.ss = 1;
519   ctrl_area->exceptions.ac = 1;
520   ctrl_area->exceptions.mc = 1;
521   ctrl_area->exceptions.gp = 1;
522   ctrl_area->exceptions.ud = 1;
523   ctrl_area->exceptions.np = 1;
524   ctrl_area->exceptions.of = 1;
525   ctrl_area->exceptions.nmi = 1;
526
527   
528
529   ctrl_area->instrs.IOIO_PROT = 1;
530   ctrl_area->IOPM_BASE_PA = (uint_t)os_hooks->allocate_pages(3);
531   
532   {
533     reg_ex_t tmp_reg;
534     tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA;
535     memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2);
536   }
537
538   ctrl_area->instrs.INTR = 1;
539
540   
541   {
542     char gdt_buf[6];
543     char idt_buf[6];
544
545     memset(gdt_buf, 0, 6);
546     memset(idt_buf, 0, 6);
547
548
549     uint_t gdt_base, idt_base;
550     ushort_t gdt_limit, idt_limit;
551     
552     GetGDTR(gdt_buf);
553     gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
554     gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
555     PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
556
557     GetIDTR(idt_buf);
558     idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
559     idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
560     PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
561
562
563     // gdt_base -= 0x2000;
564     //idt_base -= 0x2000;
565
566     guest_state->gdtr.base = gdt_base;
567     guest_state->gdtr.limit = gdt_limit;
568     guest_state->idtr.base = idt_base;
569     guest_state->idtr.limit = idt_limit;
570
571
572   }
573   
574   
575   // also determine if CPU supports nested paging
576   /*
577   if (vm_info.page_tables) {
578     //   if (0) {
579     // Flush the TLB on entries/exits
580     ctrl_area->TLB_CONTROL = 1;
581
582     // Enable Nested Paging
583     ctrl_area->NP_ENABLE = 1;
584
585     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
586
587         // Set the Nested Page Table pointer
588     ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
589
590
591     //   ctrl_area->N_CR3 = Get_CR3();
592     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
593
594     guest_state->g_pat = 0x7040600070406ULL;
595
596     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));
597     PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4));
598     // Enable Paging
599     //    guest_state->cr0 |= 0x80000000;
600   }
601   */
602
603 }
604
605
606
607
608
609 #endif
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624 /*
625
626
627 void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) {
628   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
629   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
630   uint_t i;
631
632
633   guest_state->rsp = vm_info.vm_regs.rsp;
634   guest_state->rip = vm_info.rip;
635
636
637   guest_state->efer |= EFER_MSR_svm_enable;
638   guest_state->rflags = 0x00000002; // The reserved bit is always 1
639   ctrl_area->svm_instrs.instrs.VMRUN = 1;
640   ctrl_area->guest_ASID = 1;
641   guest_state->cr0 = 0x60000010;
642
643
644   ctrl_area->exceptions.de = 1;
645   ctrl_area->exceptions.df = 1;
646   ctrl_area->exceptions.pf = 1;
647   ctrl_area->exceptions.ts = 1;
648   ctrl_area->exceptions.ss = 1;
649   ctrl_area->exceptions.ac = 1;
650   ctrl_area->exceptions.mc = 1;
651   ctrl_area->exceptions.gp = 1;
652   ctrl_area->exceptions.ud = 1;
653   ctrl_area->exceptions.np = 1;
654   ctrl_area->exceptions.of = 1;
655   ctrl_area->exceptions.nmi = 1;
656
657   guest_state->cs.selector = 0xf000;
658   guest_state->cs.limit=0xffff;
659   guest_state->cs.base =  0xffff0000;
660   guest_state->cs.attrib.raw = 0x9a;
661
662   
663   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
664   for ( i = 0; segregs[i] != NULL; i++) {
665     struct vmcb_selector * seg = segregs[i];
666     
667     seg->selector = 0x0000;
668     seg->base = 0xffff0000;
669     seg->attrib.raw = 0x9b;
670     seg->limit = 0xffff;
671   }
672   
673   // Set GPRs 
674   //
675   //  EDX == 0xfxx
676   //  EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0
677   //
678
679   guest_state->gdtr.base = 0;
680   guest_state->gdtr.limit = 0xffff;
681   guest_state->gdtr.attrib.raw = 0x0;
682
683   guest_state->idtr.base = 0;
684   guest_state->idtr.limit = 0xffff;
685   guest_state->idtr.attrib.raw = 0x0;
686
687   guest_state->ldtr.base = 0;
688   guest_state->ldtr.limit = 0xffff;
689   guest_state->ldtr.attrib.raw = 0x82;
690
691   guest_state->tr.base = 0;
692   guest_state->tr.limit = 0xffff;
693   guest_state->tr.attrib.raw = 0x83;
694
695
696
697
698   if (vm_info.io_map.num_ports > 0) {
699     vmm_io_hook_t * iter;
700     addr_t io_port_bitmap;
701     
702     io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
703     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
704     
705     ctrl_area->IOPM_BASE_PA = io_port_bitmap;
706
707     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
708
709     FOREACH_IO_HOOK(vm_info.io_map, iter) {
710       ushort_t port = iter->port;
711       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
712
713       bitmap += (port / 8);
714       PrintDebug("Setting Bit in block %x\n", bitmap);
715       *bitmap |= 1 << (port % 8);
716     }
717
718     ctrl_area->instrs.instrs.IOIO_PROT = 1;
719   }
720
721   ctrl_area->instrs.instrs.INTR = 1;
722
723   // also determine if CPU supports nested paging
724
725   if (vm_info.page_mode == SHADOW_PAGING) {
726     PrintDebug("Creating initial shadow page table\n");
727     vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
728     PrintDebug("Created\n");
729
730     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
731
732     ctrl_area->cr_reads.crs.cr3 = 1;
733     ctrl_area->cr_writes.crs.cr3 = 1;
734     ctrl_area->cr_reads.crs.cr0 = 1;
735     ctrl_area->cr_writes.crs.cr0 = 1;
736
737     ctrl_area->instrs.instrs.INVLPG = 1;
738     ctrl_area->instrs.instrs.INVLPGA = 1;
739
740         
741     guest_state->g_pat = 0x7040600070406ULL;
742
743     vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0;
744     guest_state->cr0 |= 0x80000000;
745   } else if (vm_info.page_mode == NESTED_PAGING) {
746     // Flush the TLB on entries/exits
747     //ctrl_area->TLB_CONTROL = 1;
748
749     // Enable Nested Paging
750     //ctrl_area->NP_ENABLE = 1;
751
752     //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
753
754         // Set the Nested Page Table pointer
755     //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
756     // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
757
758     //   ctrl_area->N_CR3 = Get_CR3();
759     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
760
761     //    guest_state->g_pat = 0x7040600070406ULL;
762   }
763
764 }
765 */