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.


is patch adds a function v3_print_guest_state_all that calls v3_print_guest_state...
[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\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
256     }
257
258     V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
259
260 }
261
262
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         /* always print RIP, even if the instructions before were bad */
286         if (!passed_rip && rip >= info->rip) {
287             if (rip != info->rip) {
288                 V3_Print("***** bad disassembly up to this point *****\n");
289                 rip = info->rip;
290             }
291             passed_rip = 1;
292         }
293
294         /* look up host virtual address for this instruction */
295         rip_linear = get_addr_linear(info, rip, &(info->segments.cs));
296         if (safe_gva_to_hva(info, rip_linear, &rip_host) < 0) {
297             rip++;
298             continue;
299         }
300
301         /* print disassembled instrcution (updates rip) */
302         if (v3_disasm(info, (void *) rip_host, &rip, rip == info->rip) < 0) {
303             rip++;
304             continue;
305         }
306     }
307
308     return 0;
309 }
310
311
312 void v3_print_guest_state(struct guest_info * info) {
313     addr_t linear_addr = 0; 
314
315     V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
316     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
317     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
318
319     V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
320
321     v3_print_segments(&(info->segments));
322     v3_print_ctrl_regs(info);
323
324     if (info->shdw_pg_mode == SHADOW_PAGING) {
325         V3_Print("Shadow Paging Guest Registers:\n");
326         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
327         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
328         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
329         // CR4
330     }
331     v3_print_GPRs(info);
332
333     v3_print_mem_map(info->vm_info);
334
335     v3_print_stack(info);
336
337     v3_print_disassembly(info);
338 }
339
340 void v3_print_guest_state_all(struct v3_vm_info * vm) {
341     int i = 0;
342     
343     V3_Print("VM Core states for %s\n", vm->name);
344
345     for (i = 0; i < 80; i++) {
346         V3_Print("-");
347     }
348
349     for (i = 0; i < vm->num_cores; i++) {
350         v3_print_guest_state(&vm->cores[i]);  
351     }
352     
353     for (i = 0; i < 80; i++) {
354         V3_Print("-");
355     }
356
357     V3_Print("\n");    
358 }
359
360
361 void v3_print_stack(struct guest_info * info) {
362     addr_t linear_addr = 0;
363     addr_t host_addr = 0;
364     int i = 0;
365     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
366
367
368     linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
369  
370     V3_Print("Stack  at %p:\n", (void *)linear_addr);
371    
372     if (info->mem_mode == PHYSICAL_MEM) {
373         if (v3_gpa_to_hva(info, linear_addr, &host_addr) == -1) {
374             PrintError("Could not translate Stack address\n");
375             return;
376         }
377     } else if (info->mem_mode == VIRTUAL_MEM) {
378         if (v3_gva_to_hva(info, linear_addr, &host_addr) == -1) {
379             PrintError("Could not translate Virtual Stack address\n");
380             return;
381         }
382     }
383     
384     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
385  
386     // We start i at one because the current stack pointer points to an unused stack element
387     for (i = 0; i <= 24; i++) {
388         if (cpu_mode == LONG) {
389             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
390         } else if (cpu_mode == REAL) {
391             V3_Print("Don't currently handle 16 bit stacks... \n");
392         } else {
393             // 32 bit stacks...
394             V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
395         }
396     }
397
398 }    
399
400 #ifdef __V3_32BIT__
401
402 void v3_print_GPRs(struct guest_info * info) {
403     struct v3_gprs * regs = &(info->vm_regs);
404     int i = 0;
405     v3_reg_t * reg_ptr;
406     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
407
408     reg_ptr = (v3_reg_t *)regs;
409
410     V3_Print("32 bit GPRs:\n");
411
412     for (i = 0; reg_names[i] != NULL; i++) {
413         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
414     }
415 }
416
417 #elif __V3_64BIT__
418
419 void v3_print_GPRs(struct guest_info * info) {
420     struct v3_gprs * regs = &(info->vm_regs);
421     int i = 0;
422     v3_reg_t * reg_ptr;
423     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
424                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
425
426     reg_ptr = (v3_reg_t *)regs;
427
428     V3_Print("64 bit GPRs:\n");
429
430     for (i = 0; reg_names[i] != NULL; i++) {
431         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
432     }
433 }
434
435 #endif
436
437
438 #include <palacios/vmcs.h>
439 #include <palacios/vmcb.h>
440 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
441     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
442     int cpu_valid = 0;
443
444     V3_Print("************** Guest State ************\n");
445     v3_print_guest_state(core);
446     
447     // init SVM/VMX
448 #ifdef CONFIG_SVM
449     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
450         cpu_valid = 1;
451         PrintDebugVMCB((vmcb_t *)(core->vmm_data));
452     }
453 #endif
454 #ifdef CONFIG_VMX
455     if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
456         cpu_valid = 1;
457         v3_print_vmcs();
458     }
459 #endif
460     if (!cpu_valid) {
461         PrintError("Invalid CPU Type 0x%x\n", cpu_type);
462         return -1;
463     }
464     
465
466     return 0;
467 }
468
469
470 #ifdef CONFIG_SVM
471 #include <palacios/svm.h>
472 #include <palacios/svm_io.h>
473 #include <palacios/svm_msr.h>
474 #endif
475
476 #ifdef CONFIG_VMX
477 #include <palacios/vmx.h>
478 #include <palacios/vmx_io.h>
479 #include <palacios/vmx_msr.h>
480 #endif
481
482
483 int v3_init_vm(struct v3_vm_info * vm) {
484     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
485
486     if (v3_get_foreground_vm() == NULL) {
487         v3_set_foreground_vm(vm);
488     }
489
490 #ifdef CONFIG_TELEMETRY
491     v3_init_telemetry(vm);
492 #endif
493
494     v3_init_hypercall_map(vm);
495     v3_init_io_map(vm);
496     v3_init_msr_map(vm);
497     v3_init_cpuid_map(vm);
498     v3_init_host_events(vm);
499     v3_init_intr_routers(vm);
500
501     // Initialize the memory map
502     if (v3_init_mem_map(vm) == -1) {
503         PrintError("Could not initialize shadow map\n");
504         return -1;
505     }
506
507     v3_init_mem_hooks(vm);
508
509     if (v3_init_shdw_impl(vm) == -1) {
510         PrintError("VM initialization error in shadow implementaion\n");
511         return -1;
512     }
513
514
515     v3_init_time_vm(vm);
516
517
518 #ifdef CONFIG_SYMBIOTIC
519     v3_init_symbiotic_vm(vm);
520 #endif
521
522     v3_init_dev_mgr(vm);
523
524
525     // init SVM/VMX
526     switch (cpu_type) {
527 #ifdef CONFIG_SVM
528         case V3_SVM_CPU:
529         case V3_SVM_REV3_CPU:
530             v3_init_svm_io_map(vm);
531             v3_init_svm_msr_map(vm);
532             break;
533 #endif
534 #ifdef CONFIG_VMX
535         case V3_VMX_CPU:
536         case V3_VMX_EPT_CPU:
537             v3_init_vmx_io_map(vm);
538             v3_init_vmx_msr_map(vm);
539             break;
540 #endif
541         default:
542             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
543             return -1;
544     }
545     
546     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
547
548     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
549
550     return 0;
551 }
552
553
554 int v3_free_vm_internal(struct v3_vm_info * vm) {
555     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
556
557     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
558
559
560
561 #ifdef CONFIG_SYMBIOTIC
562     v3_deinit_symbiotic_vm(vm);
563 #endif
564
565     // init SVM/VMX
566     switch (cpu_type) {
567 #ifdef CONFIG_SVM
568         case V3_SVM_CPU:
569         case V3_SVM_REV3_CPU:
570             v3_deinit_svm_io_map(vm);
571             v3_deinit_svm_msr_map(vm);
572             break;
573 #endif
574 #ifdef CONFIG_VMX
575         case V3_VMX_CPU:
576         case V3_VMX_EPT_CPU:
577             v3_deinit_vmx_io_map(vm);
578             v3_deinit_vmx_msr_map(vm);
579             break;
580 #endif
581         default:
582             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
583             return -1;
584     }
585
586     v3_deinit_dev_mgr(vm);
587
588     v3_deinit_time_vm(vm);
589
590     v3_deinit_mem_hooks(vm);
591     v3_delete_mem_map(vm);
592     v3_deinit_shdw_impl(vm);
593
594     v3_deinit_intr_routers(vm);
595     v3_deinit_host_events(vm);
596
597     v3_deinit_cpuid_map(vm);
598     v3_deinit_msr_map(vm);
599     v3_deinit_io_map(vm);
600     v3_deinit_hypercall_map(vm);
601
602 #ifdef CONFIG_TELEMETRY
603     v3_deinit_telemetry(vm);
604 #endif
605
606
607
608     return 0;
609 }
610
611
612 int v3_init_core(struct guest_info * core) {
613     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
614     struct v3_vm_info * vm = core->vm_info;
615
616     /*
617      * Initialize the subsystem data strutures
618      */
619 #ifdef CONFIG_TELEMETRY
620     v3_init_core_telemetry(core);
621 #endif
622
623     if (core->shdw_pg_mode == SHADOW_PAGING) {
624         v3_init_shdw_pg_state(core);
625     }
626
627     v3_init_time_core(core);
628     v3_init_intr_controllers(core);
629     v3_init_exception_state(core);
630
631     v3_init_decoder(core);
632
633
634 #ifdef CONFIG_SYMBIOTIC
635     v3_init_symbiotic_core(core);
636 #endif
637
638     // init SVM/VMX
639
640
641     switch (cpu_type) {
642 #ifdef CONFIG_SVM
643         case V3_SVM_CPU:
644         case V3_SVM_REV3_CPU:
645             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
646                 PrintError("Error in SVM initialization\n");
647                 return -1;
648             }
649             break;
650 #endif
651 #ifdef CONFIG_VMX
652         case V3_VMX_CPU:
653         case V3_VMX_EPT_CPU:
654             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
655                 PrintError("Error in VMX initialization\n");
656                 return -1;
657             }
658             break;
659 #endif
660         default:
661             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
662             return -1;
663     }
664
665     return 0;
666 }
667
668
669
670 int v3_free_core(struct guest_info * core) {
671     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
672
673     
674 #ifdef CONFIG_SYMBIOTIC
675     v3_deinit_symbiotic_core(core);
676 #endif
677
678     v3_deinit_decoder(core);
679
680     v3_deinit_intr_controllers(core);
681     v3_deinit_time_core(core);
682
683     if (core->shdw_pg_mode == SHADOW_PAGING) {
684         v3_deinit_shdw_pg_state(core);
685     }
686
687     v3_free_passthrough_pts(core);
688
689 #ifdef CONFIG_TELEMETRY
690     v3_deinit_core_telemetry(core);
691 #endif
692
693     switch (cpu_type) {
694 #ifdef CONFIG_SVM
695         case V3_SVM_CPU:
696         case V3_SVM_REV3_CPU:
697             if (v3_deinit_svm_vmcb(core) == -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_deinit_vmx_vmcs(core) == -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