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.


bug fixes for VMX
[palacios.git] / palacios / src / palacios / vm_guest.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21
22
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_ctrl_regs.h>
25 #include <palacios/vmm.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmcb.h>
28 #include <palacios/vm_guest_mem.h>
29 #include <palacios/vmm_lowlevel.h>
30 #include <palacios/vmm_sprintf.h>
31 #include <palacios/vmm_xed.h>
32 #include <palacios/vmm_direct_paging.h>
33 #include <palacios/vmm_barrier.h>
34
35
36 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
37     struct cr0_32 * cr0;
38     struct efer_64 * efer;
39     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
40     struct v3_segment * cs = &(info->segments.cs);
41
42
43     if (info->shdw_pg_mode == SHADOW_PAGING) {
44         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
45         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
46     } else if (info->shdw_pg_mode == NESTED_PAGING) {
47         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
48         efer = (struct efer_64 *)&(info->ctrl_regs.efer);
49     } else {
50         PrintError("Invalid Paging Mode...\n");
51         V3_ASSERT(0);
52         return -1;
53     }
54
55     if (cr0->pe == 0) {
56         return REAL;
57     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
58         return PROTECTED;
59     } else if (efer->lme == 0) {
60         return PROTECTED_PAE;
61     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
62         return LONG;
63     } else {
64         // What about LONG_16_COMPAT???
65         return LONG_32_COMPAT;
66     }
67 }
68
69 // Get address width in bytes
70 uint_t v3_get_addr_width(struct guest_info * info) {
71     struct cr0_32 * cr0;
72     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
73     struct efer_64 * efer;
74     struct v3_segment * cs = &(info->segments.cs);
75
76
77     if (info->shdw_pg_mode == SHADOW_PAGING) {
78         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
79         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
80     } else if (info->shdw_pg_mode == NESTED_PAGING) {
81         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
82         efer = (struct efer_64 *)&(info->ctrl_regs.efer);
83     } else {
84         PrintError("Invalid Paging Mode...\n");
85         V3_ASSERT(0);
86         return -1;
87     }
88
89     if (cr0->pe == 0) {
90         return 2;
91     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
92         return 4;
93     } else if (efer->lme == 0) {
94         return 4;
95     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
96         return 8;
97     } else {
98         // What about LONG_16_COMPAT???
99         return 4;
100     }
101 }
102
103
104 static const uchar_t REAL_STR[] = "Real";
105 static const uchar_t PROTECTED_STR[] = "Protected";
106 static const uchar_t PROTECTED_PAE_STR[] = "Protected+PAE";
107 static const uchar_t LONG_STR[] = "Long";
108 static const uchar_t LONG_32_COMPAT_STR[] = "32bit Compat";
109 static const uchar_t LONG_16_COMPAT_STR[] = "16bit Compat";
110
111 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode) {
112     switch (mode) {
113         case REAL:
114             return REAL_STR;
115         case PROTECTED:
116             return PROTECTED_STR;
117         case PROTECTED_PAE:
118             return PROTECTED_PAE_STR;
119         case LONG:
120             return LONG_STR;
121         case LONG_32_COMPAT:
122             return LONG_32_COMPAT_STR;
123         case LONG_16_COMPAT:
124             return LONG_16_COMPAT_STR;
125         default:
126             return NULL;
127     }
128 }
129
130 v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info) {
131     struct cr0_32 * cr0;
132
133     if (info->shdw_pg_mode == SHADOW_PAGING) {
134         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
135     } else if (info->shdw_pg_mode == NESTED_PAGING) {
136         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
137     } else {
138         PrintError("Invalid Paging Mode...\n");
139         V3_ASSERT(0);
140         return -1;
141     }
142
143     if (cr0->pg == 0) {
144         return PHYSICAL_MEM;
145     } else {
146         return VIRTUAL_MEM;
147     }
148 }
149
150 static const uchar_t PHYS_MEM_STR[] = "Physical Memory";
151 static const uchar_t VIRT_MEM_STR[] = "Virtual Memory";
152
153 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode) {
154     switch (mode) {
155         case PHYSICAL_MEM:
156             return PHYS_MEM_STR;
157         case VIRTUAL_MEM:
158             return VIRT_MEM_STR;
159         default:
160             return NULL;
161     }
162 }
163
164
165 void v3_print_segments(struct v3_segments * segs) {
166     int i = 0;
167     struct v3_segment * seg_ptr;
168
169     seg_ptr=(struct v3_segment *)segs;
170   
171     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
172     V3_Print("Segments\n");
173
174     for (i = 0; seg_names[i] != NULL; i++) {
175
176         V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
177                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
178                    seg_ptr[i].long_mode, seg_ptr[i].db);
179
180     }
181 }
182
183 //
184 // We don't handle those fancy 64 bit system segments...
185 //
186 int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
187     struct v3_segment * gdt = &(info->segments.gdtr);
188     addr_t gdt_addr = 0;
189     uint16_t seg_offset = (selector & ~0x7);
190     addr_t seg_addr = 0;
191     struct gen_segment * gen_seg = NULL;
192     struct seg_selector sel;
193
194     memset(seg, 0, sizeof(struct v3_segment));
195
196     sel.value = selector;
197
198     if (sel.ti == 1) {
199         PrintError("LDT translations not supported\n");
200         return -1;
201     }
202
203     if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
204         PrintError("Unable to translate GDT address\n");
205         return -1;
206     }
207
208     seg_addr = gdt_addr + seg_offset;
209     gen_seg = (struct gen_segment *)seg_addr;
210
211     //translate
212     seg->selector = selector;
213
214     seg->limit = gen_seg->limit_hi;
215     seg->limit <<= 16;
216     seg->limit += gen_seg->limit_lo;
217
218     seg->base = gen_seg->base_hi;
219     seg->base <<= 24;
220     seg->base += gen_seg->base_lo;
221
222     if (gen_seg->granularity == 1) {
223         seg->limit <<= 12;
224         seg->limit |= 0xfff;
225     }
226
227     seg->type = gen_seg->type;
228     seg->system = gen_seg->system;
229     seg->dpl = gen_seg->dpl;
230     seg->present = gen_seg->present;
231     seg->avail = gen_seg->avail;
232     seg->long_mode = gen_seg->long_mode;
233     seg->db = gen_seg->db;
234     seg->granularity = gen_seg->granularity;
235     
236     return 0;
237 }
238
239
240
241
242 void v3_print_ctrl_regs(struct guest_info * info) {
243     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
244     int i = 0;
245     v3_reg_t * reg_ptr;
246     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
247    
248
249     reg_ptr = (v3_reg_t *)regs;
250
251     V3_Print("Ctrl Regs:\n");
252
253     for (i = 0; reg_names[i] != NULL; i++) {
254         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
255     }
256
257
258 }
259
260 #if 0
261 static int safe_gva_to_hva(struct guest_info * info, addr_t linear_addr, addr_t * host_addr) {
262     /* select the proper translation based on guest mode */
263     if (info->mem_mode == PHYSICAL_MEM) {
264         if (v3_gpa_to_hva(info, linear_addr, host_addr) == -1) return -1;
265     } else if (info->mem_mode == VIRTUAL_MEM) {
266         if (v3_gva_to_hva(info, linear_addr, host_addr) == -1) return -1;
267     }
268     return 0;
269 }
270
271 static int v3_print_disassembly(struct guest_info * info) {
272     int passed_rip = 0;
273     addr_t rip, rip_linear, rip_host;
274
275     /* we don't know where the instructions preceding RIP start, so we just take
276      * a guess and hope the instruction stream synced up with our disassembly
277      * some time before RIP; if it has not we correct RIP at that point
278      */
279
280     /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
281     rip = (addr_t) info->rip - 64;
282     while ((int) (rip - info->rip) < 32) {
283         V3_Print("disassembly step\n");
284
285         /* always print RIP, even if the instructions before were bad */
286         if (!passed_rip && rip >= info->rip) {
287             if (rip != info->rip) {
288                 V3_Print("***** bad disassembly up to this point *****\n");
289                 rip = info->rip;
290             }
291             passed_rip = 1;
292         }
293
294         /* look up host virtual address for this instruction */
295         rip_linear = get_addr_linear(info, rip, &(info->segments.cs));
296         if (safe_gva_to_hva(info, rip_linear, &rip_host) < 0) {
297             rip++;
298             continue;
299         }
300
301         /* print disassembled instrcution (updates rip) */
302         if (v3_disasm(info, (void *) rip_host, &rip, rip == info->rip) < 0) {
303             rip++;
304             continue;
305         }
306
307     }
308
309     return 0;
310 }
311
312 #endif
313
314 void v3_print_guest_state(struct guest_info * info) {
315     addr_t linear_addr = 0; 
316
317     V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
318     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
319     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
320
321     V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
322
323     V3_Print("IRQ STATE: started=%d, pending=%d\n", 
324              info->intr_core_state.irq_started, 
325              info->intr_core_state.irq_pending);
326     V3_Print("EXCP STATE: err_code_valid=%d, err_code=%x\n", 
327              info->excp_state.excp_error_code_valid, 
328              info->excp_state.excp_error_code);
329
330
331     v3_print_segments(&(info->segments));
332     v3_print_ctrl_regs(info);
333
334     if (info->shdw_pg_mode == SHADOW_PAGING) {
335         V3_Print("Shadow Paging Guest Registers:\n");
336         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
337         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
338         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
339         // CR4
340     }
341     v3_print_GPRs(info);
342
343     v3_print_mem_map(info->vm_info);
344
345     v3_print_stack(info);
346
347     //  v3_print_disassembly(info);
348 }
349
350 void v3_print_guest_state_all(struct v3_vm_info * vm) {
351     int i = 0;
352
353     V3_Print("VM Core states for %s\n", vm->name);
354
355     for (i = 0; i < 80; i++) {
356         V3_Print("-");
357     }
358
359     for (i = 0; i < vm->num_cores; i++) {
360         v3_print_guest_state(&vm->cores[i]);  
361     }
362     
363     for (i = 0; i < 80; i++) {
364         V3_Print("-");
365     }
366
367     V3_Print("\n");    
368 }
369
370 static void print_real_mode_stack(struct guest_info *info)
371 {
372     uint16_t ss;
373     uint16_t sp;
374     addr_t   addr;
375     addr_t   host_addr;
376     int      i;
377
378
379     ss = info->segments.ss.selector & 0xffff;
380     sp = info->vm_regs.rsp & 0xffff;
381     addr = (((uint32_t)ss)<<4) + sp;
382
383    
384     V3_Print("Real Mode Stack starting at 0x%x:0x%x (0x%p):\n",ss,sp,(void*)addr);
385
386     if (info->mem_mode!=PHYSICAL_MEM) {
387         PrintError("Cannot print real mode stack when virtual memory active\n");
388         return;
389     }
390         
391     for (i=0;i<=24;i++,sp+=2) { 
392         // note that it's correct for this to wrap around
393         addr = (((uint32_t)ss)<<4) + sp;
394         if (v3_gpa_to_hva(info,addr,&host_addr)) { 
395             PrintError("Could not translate physical stack address 0x%p\n",(void*)addr);
396             return;
397         }
398         V3_Print("\t0x%.4x\n",*((uint16_t*)host_addr));
399     }
400 }
401         
402
403
404
405 void v3_print_stack(struct guest_info * info) {
406     addr_t linear_addr = 0;
407     addr_t host_addr = 0;
408     int i = 0;
409     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
410
411
412     if (cpu_mode==REAL) { 
413         print_real_mode_stack(info);
414         return;
415     }
416
417     // protected mode, 32 or 64 bit
418
419     linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
420  
421     V3_Print("Stack at %p:\n", (void *)linear_addr);
422    
423     if (info->mem_mode == PHYSICAL_MEM) {
424         if (v3_gpa_to_hva(info, linear_addr, &host_addr) == -1) {
425             PrintError("Could not translate Stack address\n");
426             return;
427         }
428     } else if (info->mem_mode == VIRTUAL_MEM) {
429         if (v3_gva_to_hva(info, linear_addr, &host_addr) == -1) {
430             PrintError("Could not translate Virtual Stack address\n");
431             return;
432         }
433     }
434     
435     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
436  
437     // We start i at one because the current stack pointer points to an unused stack element
438     for (i = 0; i <= 24; i++) {
439         if (cpu_mode == LONG) {
440             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
441         } else {
442             // 32 bit stacks...
443             V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
444         }
445     }
446
447 }    
448
449 #ifdef __V3_32BIT__
450
451 void v3_print_GPRs(struct guest_info * info) {
452     struct v3_gprs * regs = &(info->vm_regs);
453     int i = 0;
454     v3_reg_t * reg_ptr;
455     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
456
457     reg_ptr = (v3_reg_t *)regs;
458
459     V3_Print("32 bit GPRs:\n");
460
461     for (i = 0; reg_names[i] != NULL; i++) {
462         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
463     }
464 }
465
466 #elif __V3_64BIT__
467
468 void v3_print_GPRs(struct guest_info * info) {
469     struct v3_gprs * regs = &(info->vm_regs);
470     int i = 0;
471     v3_reg_t * reg_ptr;
472     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
473                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
474
475     reg_ptr = (v3_reg_t *)regs;
476
477     V3_Print("64 bit GPRs:\n");
478
479     for (i = 0; reg_names[i] != NULL; i++) {
480         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
481     }
482 }
483
484 #endif
485
486
487 #include <palacios/vmcs.h>
488 #include <palacios/vmcb.h>
489 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
490     extern v3_cpu_arch_t v3_mach_type;
491     int cpu_valid = 0;
492
493     V3_Print("************** Guest State ************\n");
494     v3_print_guest_state(core);
495     
496     // init SVM/VMX
497 #ifdef V3_CONFIG_SVM
498     if ((v3_mach_type == V3_SVM_CPU) || (v3_mach_type == V3_SVM_REV3_CPU)) {
499         cpu_valid = 1;
500         PrintDebugVMCB((vmcb_t *)(core->vmm_data));
501     }
502 #endif
503 #ifdef V3_CONFIG_VMX
504     if ((v3_mach_type == V3_VMX_CPU) || (v3_mach_type == V3_VMX_EPT_CPU) || (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
505         cpu_valid = 1;
506         v3_print_vmcs();
507     }
508 #endif
509     if (!cpu_valid) {
510         PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
511         return -1;
512     }
513     
514
515     return 0;
516 }
517
518
519 #ifdef V3_CONFIG_SVM
520 #include <palacios/svm.h>
521 #include <palacios/svm_io.h>
522 #include <palacios/svm_msr.h>
523 #endif
524
525 #ifdef V3_CONFIG_VMX
526 #include <palacios/vmx.h>
527 #include <palacios/vmx_io.h>
528 #include <palacios/vmx_msr.h>
529 #endif
530
531
532 int v3_init_vm(struct v3_vm_info * vm) {
533     extern v3_cpu_arch_t v3_mach_type;
534
535
536
537 #ifdef V3_CONFIG_TELEMETRY
538     v3_init_telemetry(vm);
539 #endif
540
541     v3_init_hypercall_map(vm);
542     v3_init_io_map(vm);
543     v3_init_msr_map(vm);
544     v3_init_cpuid_map(vm);
545     v3_init_host_events(vm);
546     v3_init_intr_routers(vm);
547     v3_init_ext_manager(vm);
548
549     v3_init_barrier(vm);
550
551     // Initialize the memory map
552     if (v3_init_mem_map(vm) == -1) {
553         PrintError("Could not initialize shadow map\n");
554         return -1;
555     }
556
557     v3_init_mem_hooks(vm);
558
559     if (v3_init_shdw_impl(vm) == -1) {
560         PrintError("VM initialization error in shadow implementaion\n");
561         return -1;
562     }
563
564
565     v3_init_time_vm(vm);
566
567
568 #ifdef V3_CONFIG_SYMBIOTIC
569     v3_init_symbiotic_vm(vm);
570 #endif
571
572     v3_init_dev_mgr(vm);
573
574
575     // init SVM/VMX
576     switch (v3_mach_type) {
577 #ifdef V3_CONFIG_SVM
578         case V3_SVM_CPU:
579         case V3_SVM_REV3_CPU:
580             v3_init_svm_io_map(vm);
581             v3_init_svm_msr_map(vm);
582             break;
583 #endif
584 #ifdef V3_CONFIG_VMX
585         case V3_VMX_CPU:
586         case V3_VMX_EPT_CPU:
587         case V3_VMX_EPT_UG_CPU:
588             v3_init_vmx_io_map(vm);
589             v3_init_vmx_msr_map(vm);
590             break;
591 #endif
592         default:
593             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
594             return -1;
595     }
596     
597     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
598
599     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
600
601     return 0;
602 }
603
604
605 int v3_free_vm_internal(struct v3_vm_info * vm) {
606     extern v3_cpu_arch_t v3_mach_type;
607
608     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
609
610
611
612 #ifdef V3_CONFIG_SYMBIOTIC
613     v3_deinit_symbiotic_vm(vm);
614 #endif
615
616     // init SVM/VMX
617     switch (v3_mach_type) {
618 #ifdef V3_CONFIG_SVM
619         case V3_SVM_CPU:
620         case V3_SVM_REV3_CPU:
621             v3_deinit_svm_io_map(vm);
622             v3_deinit_svm_msr_map(vm);
623             break;
624 #endif
625 #ifdef V3_CONFIG_VMX
626         case V3_VMX_CPU:
627         case V3_VMX_EPT_CPU:
628         case V3_VMX_EPT_UG_CPU:
629             v3_deinit_vmx_io_map(vm);
630             v3_deinit_vmx_msr_map(vm);
631             break;
632 #endif
633         default:
634             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
635             return -1;
636     }
637
638     v3_deinit_dev_mgr(vm);
639
640     v3_deinit_time_vm(vm);
641
642     v3_deinit_mem_hooks(vm);
643     v3_delete_mem_map(vm);
644     v3_deinit_shdw_impl(vm);
645
646     v3_deinit_intr_routers(vm);
647     v3_deinit_host_events(vm);
648
649     v3_deinit_barrier(vm);
650
651     v3_deinit_cpuid_map(vm);
652     v3_deinit_msr_map(vm);
653     v3_deinit_io_map(vm);
654     v3_deinit_hypercall_map(vm);
655
656 #ifdef V3_CONFIG_TELEMETRY
657     v3_deinit_telemetry(vm);
658 #endif
659
660
661
662     return 0;
663 }
664
665
666 int v3_init_core(struct guest_info * core) {
667     extern v3_cpu_arch_t v3_mach_type;
668     struct v3_vm_info * vm = core->vm_info;
669
670
671
672     /*
673      * Initialize the subsystem data strutures
674      */
675 #ifdef V3_CONFIG_TELEMETRY
676     v3_init_core_telemetry(core);
677 #endif
678
679     if (core->shdw_pg_mode == SHADOW_PAGING) {
680         v3_init_shdw_pg_state(core);
681     }
682
683     v3_init_time_core(core);
684     v3_init_intr_controllers(core);
685     v3_init_exception_state(core);
686
687     v3_init_decoder(core);
688
689
690 #ifdef V3_CONFIG_SYMBIOTIC
691     v3_init_symbiotic_core(core);
692 #endif
693
694     // init SVM/VMX
695
696
697     switch (v3_mach_type) {
698 #ifdef V3_CONFIG_SVM
699         case V3_SVM_CPU:
700         case V3_SVM_REV3_CPU:
701             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
702                 PrintError("Error in SVM initialization\n");
703                 return -1;
704             }
705             break;
706 #endif
707 #ifdef V3_CONFIG_VMX
708         case V3_VMX_CPU:
709         case V3_VMX_EPT_CPU:
710         case V3_VMX_EPT_UG_CPU:
711             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
712                 PrintError("Error in VMX initialization\n");
713                 return -1;
714             }
715             break;
716 #endif
717         default:
718             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
719             return -1;
720     }
721
722     return 0;
723 }
724
725
726
727 int v3_free_core(struct guest_info * core) {
728     extern v3_cpu_arch_t v3_mach_type;
729
730     
731 #ifdef V3_CONFIG_SYMBIOTIC
732     v3_deinit_symbiotic_core(core);
733 #endif
734
735     v3_deinit_decoder(core);
736
737     v3_deinit_intr_controllers(core);
738     v3_deinit_time_core(core);
739
740     if (core->shdw_pg_mode == SHADOW_PAGING) {
741         v3_deinit_shdw_pg_state(core);
742     }
743
744     v3_free_passthrough_pts(core);
745
746 #ifdef V3_CONFIG_TELEMETRY
747     v3_deinit_core_telemetry(core);
748 #endif
749
750     switch (v3_mach_type) {
751 #ifdef V3_CONFIG_SVM
752         case V3_SVM_CPU:
753         case V3_SVM_REV3_CPU:
754             if (v3_deinit_svm_vmcb(core) == -1) {
755                 PrintError("Error in SVM initialization\n");
756                 return -1;
757             }
758             break;
759 #endif
760 #ifdef V3_CONFIG_VMX
761         case V3_VMX_CPU:
762         case V3_VMX_EPT_CPU:
763         case V3_VMX_EPT_UG_CPU:
764             if (v3_deinit_vmx_vmcs(core) == -1) {
765                 PrintError("Error in VMX initialization\n");
766                 return -1;
767             }
768             break;
769 #endif
770         default:
771             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
772             return -1;
773     }
774
775     return 0;
776 }
777
778
779