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.


removed muxer
[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 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 CONFIG_VMX
497     if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_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 CONFIG_SVM
513 #include <palacios/svm.h>
514 #include <palacios/svm_io.h>
515 #include <palacios/svm_msr.h>
516 #endif
517
518 #ifdef 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 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 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 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 CONFIG_VMX
576         case V3_VMX_CPU:
577         case V3_VMX_EPT_CPU:
578             v3_init_vmx_io_map(vm);
579             v3_init_vmx_msr_map(vm);
580             break;
581 #endif
582         default:
583             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
584             return -1;
585     }
586     
587     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
588
589     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
590
591     return 0;
592 }
593
594
595 int v3_free_vm_internal(struct v3_vm_info * vm) {
596     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
597
598     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
599
600
601
602 #ifdef CONFIG_SYMBIOTIC
603     v3_deinit_symbiotic_vm(vm);
604 #endif
605
606     // init SVM/VMX
607     switch (cpu_type) {
608 #ifdef CONFIG_SVM
609         case V3_SVM_CPU:
610         case V3_SVM_REV3_CPU:
611             v3_deinit_svm_io_map(vm);
612             v3_deinit_svm_msr_map(vm);
613             break;
614 #endif
615 #ifdef CONFIG_VMX
616         case V3_VMX_CPU:
617         case V3_VMX_EPT_CPU:
618             v3_deinit_vmx_io_map(vm);
619             v3_deinit_vmx_msr_map(vm);
620             break;
621 #endif
622         default:
623             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
624             return -1;
625     }
626
627     v3_deinit_dev_mgr(vm);
628
629     v3_deinit_time_vm(vm);
630
631     v3_deinit_mem_hooks(vm);
632     v3_delete_mem_map(vm);
633     v3_deinit_shdw_impl(vm);
634
635     v3_deinit_intr_routers(vm);
636     v3_deinit_host_events(vm);
637
638     v3_deinit_cpuid_map(vm);
639     v3_deinit_msr_map(vm);
640     v3_deinit_io_map(vm);
641     v3_deinit_hypercall_map(vm);
642
643 #ifdef CONFIG_TELEMETRY
644     v3_deinit_telemetry(vm);
645 #endif
646
647
648
649     return 0;
650 }
651
652
653 int v3_init_core(struct guest_info * core) {
654     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
655     struct v3_vm_info * vm = core->vm_info;
656
657
658
659     /*
660      * Initialize the subsystem data strutures
661      */
662 #ifdef CONFIG_TELEMETRY
663     v3_init_core_telemetry(core);
664 #endif
665
666     if (core->shdw_pg_mode == SHADOW_PAGING) {
667         v3_init_shdw_pg_state(core);
668     }
669
670     v3_init_time_core(core);
671     v3_init_intr_controllers(core);
672     v3_init_exception_state(core);
673
674     v3_init_decoder(core);
675
676
677 #ifdef CONFIG_SYMBIOTIC
678     v3_init_symbiotic_core(core);
679 #endif
680
681     // init SVM/VMX
682
683
684     switch (cpu_type) {
685 #ifdef CONFIG_SVM
686         case V3_SVM_CPU:
687         case V3_SVM_REV3_CPU:
688             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
689                 PrintError("Error in SVM initialization\n");
690                 return -1;
691             }
692             break;
693 #endif
694 #ifdef CONFIG_VMX
695         case V3_VMX_CPU:
696         case V3_VMX_EPT_CPU:
697             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
698                 PrintError("Error in VMX initialization\n");
699                 return -1;
700             }
701             break;
702 #endif
703         default:
704             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
705             return -1;
706     }
707
708     return 0;
709 }
710
711
712
713 int v3_free_core(struct guest_info * core) {
714     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
715
716     
717 #ifdef CONFIG_SYMBIOTIC
718     v3_deinit_symbiotic_core(core);
719 #endif
720
721     v3_deinit_decoder(core);
722
723     v3_deinit_intr_controllers(core);
724     v3_deinit_time_core(core);
725
726     if (core->shdw_pg_mode == SHADOW_PAGING) {
727         v3_deinit_shdw_pg_state(core);
728     }
729
730     v3_free_passthrough_pts(core);
731
732 #ifdef CONFIG_TELEMETRY
733     v3_deinit_core_telemetry(core);
734 #endif
735
736     switch (cpu_type) {
737 #ifdef CONFIG_SVM
738         case V3_SVM_CPU:
739         case V3_SVM_REV3_CPU:
740             if (v3_deinit_svm_vmcb(core) == -1) {
741                 PrintError("Error in SVM initialization\n");
742                 return -1;
743             }
744             break;
745 #endif
746 #ifdef CONFIG_VMX
747         case V3_VMX_CPU:
748         case V3_VMX_EPT_CPU:
749             if (v3_deinit_vmx_vmcs(core) == -1) {
750                 PrintError("Error in VMX initialization\n");
751                 return -1;
752             }
753             break;
754 #endif
755         default:
756             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
757             return -1;
758     }
759
760     return 0;
761 }
762
763
764