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.


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