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.


7bd275f77a2aef9c5fa7edacb226c8fb5b8ce853
[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     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     v3_init_barrier(vm);
543
544     // Initialize the memory map
545     if (v3_init_mem_map(vm) == -1) {
546         PrintError("Could not initialize shadow map\n");
547         return -1;
548     }
549
550     v3_init_mem_hooks(vm);
551
552     if (v3_init_shdw_impl(vm) == -1) {
553         PrintError("VM initialization error in shadow implementaion\n");
554         return -1;
555     }
556
557
558     v3_init_time_vm(vm);
559
560
561 #ifdef V3_CONFIG_SYMBIOTIC
562     v3_init_symbiotic_vm(vm);
563 #endif
564
565     v3_init_dev_mgr(vm);
566
567
568     // init SVM/VMX
569     switch (cpu_type) {
570 #ifdef V3_CONFIG_SVM
571         case V3_SVM_CPU:
572         case V3_SVM_REV3_CPU:
573             v3_init_svm_io_map(vm);
574             v3_init_svm_msr_map(vm);
575             break;
576 #endif
577 #ifdef V3_CONFIG_VMX
578         case V3_VMX_CPU:
579         case V3_VMX_EPT_CPU:
580         case V3_VMX_EPT_UG_CPU:
581             v3_init_vmx_io_map(vm);
582             v3_init_vmx_msr_map(vm);
583             break;
584 #endif
585         default:
586             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
587             return -1;
588     }
589     
590     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
591
592     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
593
594     return 0;
595 }
596
597
598 int v3_free_vm_internal(struct v3_vm_info * vm) {
599     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
600
601     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
602
603
604
605 #ifdef V3_CONFIG_SYMBIOTIC
606     v3_deinit_symbiotic_vm(vm);
607 #endif
608
609     // init SVM/VMX
610     switch (cpu_type) {
611 #ifdef V3_CONFIG_SVM
612         case V3_SVM_CPU:
613         case V3_SVM_REV3_CPU:
614             v3_deinit_svm_io_map(vm);
615             v3_deinit_svm_msr_map(vm);
616             break;
617 #endif
618 #ifdef V3_CONFIG_VMX
619         case V3_VMX_CPU:
620         case V3_VMX_EPT_CPU:
621         case V3_VMX_EPT_UG_CPU:
622             v3_deinit_vmx_io_map(vm);
623             v3_deinit_vmx_msr_map(vm);
624             break;
625 #endif
626         default:
627             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
628             return -1;
629     }
630
631     v3_deinit_dev_mgr(vm);
632
633     v3_deinit_time_vm(vm);
634
635     v3_deinit_mem_hooks(vm);
636     v3_delete_mem_map(vm);
637     v3_deinit_shdw_impl(vm);
638
639     v3_deinit_intr_routers(vm);
640     v3_deinit_host_events(vm);
641
642     v3_deinit_barrier(vm);
643
644     v3_deinit_cpuid_map(vm);
645     v3_deinit_msr_map(vm);
646     v3_deinit_io_map(vm);
647     v3_deinit_hypercall_map(vm);
648
649 #ifdef V3_CONFIG_TELEMETRY
650     v3_deinit_telemetry(vm);
651 #endif
652
653
654
655     return 0;
656 }
657
658
659 int v3_init_core(struct guest_info * core) {
660     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
661     struct v3_vm_info * vm = core->vm_info;
662
663
664
665     /*
666      * Initialize the subsystem data strutures
667      */
668 #ifdef V3_CONFIG_TELEMETRY
669     v3_init_core_telemetry(core);
670 #endif
671
672     if (core->shdw_pg_mode == SHADOW_PAGING) {
673         v3_init_shdw_pg_state(core);
674     }
675
676     v3_init_time_core(core);
677     v3_init_intr_controllers(core);
678     v3_init_exception_state(core);
679
680     v3_init_decoder(core);
681
682
683 #ifdef V3_CONFIG_SYMBIOTIC
684     v3_init_symbiotic_core(core);
685 #endif
686
687     // init SVM/VMX
688
689
690     switch (cpu_type) {
691 #ifdef V3_CONFIG_SVM
692         case V3_SVM_CPU:
693         case V3_SVM_REV3_CPU:
694             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
695                 PrintError("Error in SVM initialization\n");
696                 return -1;
697             }
698             break;
699 #endif
700 #ifdef V3_CONFIG_VMX
701         case V3_VMX_CPU:
702         case V3_VMX_EPT_CPU:
703         case V3_VMX_EPT_UG_CPU:
704             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
705                 PrintError("Error in VMX initialization\n");
706                 return -1;
707             }
708             break;
709 #endif
710         default:
711             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
712             return -1;
713     }
714
715     return 0;
716 }
717
718
719
720 int v3_free_core(struct guest_info * core) {
721     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
722
723     
724 #ifdef V3_CONFIG_SYMBIOTIC
725     v3_deinit_symbiotic_core(core);
726 #endif
727
728     v3_deinit_decoder(core);
729
730     v3_deinit_intr_controllers(core);
731     v3_deinit_time_core(core);
732
733     if (core->shdw_pg_mode == SHADOW_PAGING) {
734         v3_deinit_shdw_pg_state(core);
735     }
736
737     v3_free_passthrough_pts(core);
738
739 #ifdef V3_CONFIG_TELEMETRY
740     v3_deinit_core_telemetry(core);
741 #endif
742
743     switch (cpu_type) {
744 #ifdef V3_CONFIG_SVM
745         case V3_SVM_CPU:
746         case V3_SVM_REV3_CPU:
747             if (v3_deinit_svm_vmcb(core) == -1) {
748                 PrintError("Error in SVM initialization\n");
749                 return -1;
750             }
751             break;
752 #endif
753 #ifdef V3_CONFIG_VMX
754         case V3_VMX_CPU:
755         case V3_VMX_EPT_CPU:
756         case V3_VMX_EPT_UG_CPU:
757             if (v3_deinit_vmx_vmcs(core) == -1) {
758                 PrintError("Error in VMX initialization\n");
759                 return -1;
760             }
761             break;
762 #endif
763         default:
764             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
765             return -1;
766     }
767
768     return 0;
769 }
770
771
772