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