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