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.


build fixes to merge the Palacios configuration parameters with Linux parameters.
[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
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     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
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 *)&(guest_state->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     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
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 *)&(guest_state->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", NULL};
247     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
248
249     reg_ptr = (v3_reg_t *)regs;
250
251     V3_Print("32 bit 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     V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
258
259 }
260
261 #if 0
262 static int safe_gva_to_hva(struct guest_info * info, addr_t linear_addr, addr_t * host_addr) {
263     /* select the proper translation based on guest mode */
264     if (info->mem_mode == PHYSICAL_MEM) {
265         if (v3_gpa_to_hva(info, linear_addr, host_addr) == -1) return -1;
266     } else if (info->mem_mode == VIRTUAL_MEM) {
267         if (v3_gva_to_hva(info, linear_addr, host_addr) == -1) return -1;
268     }
269     return 0;
270 }
271
272 static int v3_print_disassembly(struct guest_info * info) {
273     int passed_rip = 0;
274     addr_t rip, rip_linear, rip_host;
275
276     /* we don't know where the instructions preceding RIP start, so we just take
277      * a guess and hope the instruction stream synced up with our disassembly
278      * some time before RIP; if it has not we correct RIP at that point
279      */
280
281     /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
282     rip = (addr_t) info->rip - 64;
283     while ((int) (rip - info->rip) < 32) {
284         V3_Print("disassembly step\n");
285
286         /* always print RIP, even if the instructions before were bad */
287         if (!passed_rip && rip >= info->rip) {
288             if (rip != info->rip) {
289                 V3_Print("***** bad disassembly up to this point *****\n");
290                 rip = info->rip;
291             }
292             passed_rip = 1;
293         }
294
295         /* look up host virtual address for this instruction */
296         rip_linear = get_addr_linear(info, rip, &(info->segments.cs));
297         if (safe_gva_to_hva(info, rip_linear, &rip_host) < 0) {
298             rip++;
299             continue;
300         }
301
302         /* print disassembled instrcution (updates rip) */
303         if (v3_disasm(info, (void *) rip_host, &rip, rip == info->rip) < 0) {
304             rip++;
305             continue;
306         }
307
308     }
309
310     return 0;
311 }
312
313 #endif
314
315 void v3_print_guest_state(struct guest_info * info) {
316     addr_t linear_addr = 0; 
317
318     V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
319     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
320     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
321
322     V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
323
324     v3_print_segments(&(info->segments));
325     v3_print_ctrl_regs(info);
326
327     if (info->shdw_pg_mode == SHADOW_PAGING) {
328         V3_Print("Shadow Paging Guest Registers:\n");
329         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
330         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
331         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
332         // CR4
333     }
334     v3_print_GPRs(info);
335
336     v3_print_mem_map(info->vm_info);
337
338     v3_print_stack(info);
339
340     //  v3_print_disassembly(info);
341 }
342
343 void v3_print_guest_state_all(struct v3_vm_info * vm) {
344     int i = 0;
345
346     V3_Print("VM Core states for %s\n", vm->name);
347
348     for (i = 0; i < 80; i++) {
349         V3_Print("-");
350     }
351
352     for (i = 0; i < vm->num_cores; i++) {
353         v3_print_guest_state(&vm->cores[i]);  
354     }
355     
356     for (i = 0; i < 80; i++) {
357         V3_Print("-");
358     }
359
360     V3_Print("\n");    
361 }
362
363 static void print_real_mode_stack(struct guest_info *info)
364 {
365     uint16_t ss;
366     uint16_t sp;
367     addr_t   addr;
368     addr_t   host_addr;
369     int      i;
370
371
372     ss = info->segments.ss.selector & 0xffff;
373     sp = info->vm_regs.rsp & 0xffff;
374     addr = (((uint32_t)ss)<<4) + sp;
375
376    
377     V3_Print("Real Mode Stack starting at 0x%x:0x%x (0x%p):\n",ss,sp,(void*)addr);
378
379     if (info->mem_mode!=PHYSICAL_MEM) {
380         PrintError("Cannot print real mode stack when virtual memory active\n");
381         return;
382     }
383         
384     for (i=0;i<=24;i++,sp+=2) { 
385         // note that it's correct for this to wrap around
386         addr = (((uint32_t)ss)<<4) + sp;
387         if (v3_gpa_to_hva(info,addr,&host_addr)) { 
388             PrintError("Could not translate physical stack address 0x%p\n",(void*)addr);
389             return;
390         }
391         V3_Print("\t0x%.4x\n",*((uint16_t*)host_addr));
392     }
393 }
394         
395
396
397
398 void v3_print_stack(struct guest_info * info) {
399     addr_t linear_addr = 0;
400     addr_t host_addr = 0;
401     int i = 0;
402     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
403
404
405     if (cpu_mode==REAL) { 
406         print_real_mode_stack(info);
407         return;
408     }
409
410     // protected mode, 32 or 64 bit
411
412     linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
413  
414     V3_Print("Stack at %p:\n", (void *)linear_addr);
415    
416     if (info->mem_mode == PHYSICAL_MEM) {
417         if (v3_gpa_to_hva(info, linear_addr, &host_addr) == -1) {
418             PrintError("Could not translate Stack address\n");
419             return;
420         }
421     } else if (info->mem_mode == VIRTUAL_MEM) {
422         if (v3_gva_to_hva(info, linear_addr, &host_addr) == -1) {
423             PrintError("Could not translate Virtual Stack address\n");
424             return;
425         }
426     }
427     
428     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
429  
430     // We start i at one because the current stack pointer points to an unused stack element
431     for (i = 0; i <= 24; i++) {
432         if (cpu_mode == LONG) {
433             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
434         } else {
435             // 32 bit stacks...
436             V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
437         }
438     }
439
440 }    
441
442 #ifdef __V3_32BIT__
443
444 void v3_print_GPRs(struct guest_info * info) {
445     struct v3_gprs * regs = &(info->vm_regs);
446     int i = 0;
447     v3_reg_t * reg_ptr;
448     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
449
450     reg_ptr = (v3_reg_t *)regs;
451
452     V3_Print("32 bit GPRs:\n");
453
454     for (i = 0; reg_names[i] != NULL; i++) {
455         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
456     }
457 }
458
459 #elif __V3_64BIT__
460
461 void v3_print_GPRs(struct guest_info * info) {
462     struct v3_gprs * regs = &(info->vm_regs);
463     int i = 0;
464     v3_reg_t * reg_ptr;
465     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
466                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
467
468     reg_ptr = (v3_reg_t *)regs;
469
470     V3_Print("64 bit GPRs:\n");
471
472     for (i = 0; reg_names[i] != NULL; i++) {
473         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
474     }
475 }
476
477 #endif
478
479
480 #include <palacios/vmcs.h>
481 #include <palacios/vmcb.h>
482 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
483     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
484     int cpu_valid = 0;
485
486     V3_Print("************** Guest State ************\n");
487     v3_print_guest_state(core);
488     
489     // init SVM/VMX
490 #ifdef V3_CONFIG_SVM
491     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
492         cpu_valid = 1;
493         PrintDebugVMCB((vmcb_t *)(core->vmm_data));
494     }
495 #endif
496 #ifdef V3_CONFIG_VMX
497     if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU) || (cpu_type == V3_VMX_EPT_UG_CPU)) {
498         cpu_valid = 1;
499         v3_print_vmcs();
500     }
501 #endif
502     if (!cpu_valid) {
503         PrintError("Invalid CPU Type 0x%x\n", cpu_type);
504         return -1;
505     }
506     
507
508     return 0;
509 }
510
511
512 #ifdef V3_CONFIG_SVM
513 #include <palacios/svm.h>
514 #include <palacios/svm_io.h>
515 #include <palacios/svm_msr.h>
516 #endif
517
518 #ifdef V3_CONFIG_VMX
519 #include <palacios/vmx.h>
520 #include <palacios/vmx_io.h>
521 #include <palacios/vmx_msr.h>
522 #endif
523
524
525 int v3_init_vm(struct v3_vm_info * vm) {
526     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
527
528
529
530 #ifdef V3_CONFIG_TELEMETRY
531     v3_init_telemetry(vm);
532 #endif
533
534     v3_init_hypercall_map(vm);
535     v3_init_io_map(vm);
536     v3_init_msr_map(vm);
537     v3_init_cpuid_map(vm);
538     v3_init_host_events(vm);
539     v3_init_intr_routers(vm);
540     v3_init_ext_manager(vm);
541
542     // Initialize the memory map
543     if (v3_init_mem_map(vm) == -1) {
544         PrintError("Could not initialize shadow map\n");
545         return -1;
546     }
547
548     v3_init_mem_hooks(vm);
549
550     if (v3_init_shdw_impl(vm) == -1) {
551         PrintError("VM initialization error in shadow implementaion\n");
552         return -1;
553     }
554
555
556     v3_init_time_vm(vm);
557
558
559 #ifdef V3_CONFIG_SYMBIOTIC
560     v3_init_symbiotic_vm(vm);
561 #endif
562
563     v3_init_dev_mgr(vm);
564
565
566     // init SVM/VMX
567     switch (cpu_type) {
568 #ifdef V3_CONFIG_SVM
569         case V3_SVM_CPU:
570         case V3_SVM_REV3_CPU:
571             v3_init_svm_io_map(vm);
572             v3_init_svm_msr_map(vm);
573             break;
574 #endif
575 #ifdef V3_CONFIG_VMX
576         case V3_VMX_CPU:
577         case V3_VMX_EPT_CPU:
578         case V3_VMX_EPT_UG_CPU:
579             v3_init_vmx_io_map(vm);
580             v3_init_vmx_msr_map(vm);
581             break;
582 #endif
583         default:
584             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
585             return -1;
586     }
587     
588     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
589
590     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
591
592     return 0;
593 }
594
595
596 int v3_free_vm_internal(struct v3_vm_info * vm) {
597     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
598
599     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
600
601
602
603 #ifdef V3_CONFIG_SYMBIOTIC
604     v3_deinit_symbiotic_vm(vm);
605 #endif
606
607     // init SVM/VMX
608     switch (cpu_type) {
609 #ifdef V3_CONFIG_SVM
610         case V3_SVM_CPU:
611         case V3_SVM_REV3_CPU:
612             v3_deinit_svm_io_map(vm);
613             v3_deinit_svm_msr_map(vm);
614             break;
615 #endif
616 #ifdef V3_CONFIG_VMX
617         case V3_VMX_CPU:
618         case V3_VMX_EPT_CPU:
619         case V3_VMX_EPT_UG_CPU:
620             v3_deinit_vmx_io_map(vm);
621             v3_deinit_vmx_msr_map(vm);
622             break;
623 #endif
624         default:
625             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
626             return -1;
627     }
628
629     v3_deinit_dev_mgr(vm);
630
631     v3_deinit_time_vm(vm);
632
633     v3_deinit_mem_hooks(vm);
634     v3_delete_mem_map(vm);
635     v3_deinit_shdw_impl(vm);
636
637     v3_deinit_intr_routers(vm);
638     v3_deinit_host_events(vm);
639
640     v3_deinit_cpuid_map(vm);
641     v3_deinit_msr_map(vm);
642     v3_deinit_io_map(vm);
643     v3_deinit_hypercall_map(vm);
644
645 #ifdef V3_CONFIG_TELEMETRY
646     v3_deinit_telemetry(vm);
647 #endif
648
649
650
651     return 0;
652 }
653
654
655 int v3_init_core(struct guest_info * core) {
656     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
657     struct v3_vm_info * vm = core->vm_info;
658
659
660
661     /*
662      * Initialize the subsystem data strutures
663      */
664 #ifdef V3_CONFIG_TELEMETRY
665     v3_init_core_telemetry(core);
666 #endif
667
668     if (core->shdw_pg_mode == SHADOW_PAGING) {
669         v3_init_shdw_pg_state(core);
670     }
671
672     v3_init_time_core(core);
673     v3_init_intr_controllers(core);
674     v3_init_exception_state(core);
675
676     v3_init_decoder(core);
677
678
679 #ifdef V3_CONFIG_SYMBIOTIC
680     v3_init_symbiotic_core(core);
681 #endif
682
683     // init SVM/VMX
684
685
686     switch (cpu_type) {
687 #ifdef V3_CONFIG_SVM
688         case V3_SVM_CPU:
689         case V3_SVM_REV3_CPU:
690             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
691                 PrintError("Error in SVM initialization\n");
692                 return -1;
693             }
694             break;
695 #endif
696 #ifdef V3_CONFIG_VMX
697         case V3_VMX_CPU:
698         case V3_VMX_EPT_CPU:
699         case V3_VMX_EPT_UG_CPU:
700             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
701                 PrintError("Error in VMX initialization\n");
702                 return -1;
703             }
704             break;
705 #endif
706         default:
707             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
708             return -1;
709     }
710
711     return 0;
712 }
713
714
715
716 int v3_free_core(struct guest_info * core) {
717     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
718
719     
720 #ifdef V3_CONFIG_SYMBIOTIC
721     v3_deinit_symbiotic_core(core);
722 #endif
723
724     v3_deinit_decoder(core);
725
726     v3_deinit_intr_controllers(core);
727     v3_deinit_time_core(core);
728
729     if (core->shdw_pg_mode == SHADOW_PAGING) {
730         v3_deinit_shdw_pg_state(core);
731     }
732
733     v3_free_passthrough_pts(core);
734
735 #ifdef V3_CONFIG_TELEMETRY
736     v3_deinit_core_telemetry(core);
737 #endif
738
739     switch (cpu_type) {
740 #ifdef V3_CONFIG_SVM
741         case V3_SVM_CPU:
742         case V3_SVM_REV3_CPU:
743             if (v3_deinit_svm_vmcb(core) == -1) {
744                 PrintError("Error in SVM initialization\n");
745                 return -1;
746             }
747             break;
748 #endif
749 #ifdef V3_CONFIG_VMX
750         case V3_VMX_CPU:
751         case V3_VMX_EPT_CPU:
752         case V3_VMX_EPT_UG_CPU:
753             if (v3_deinit_vmx_vmcs(core) == -1) {
754                 PrintError("Error in VMX initialization\n");
755                 return -1;
756             }
757             break;
758 #endif
759         default:
760             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
761             return -1;
762     }
763
764     return 0;
765 }
766
767
768