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.


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