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.


5535a6fb095c9074148302de8945ba05dafd8dbe
[palacios.git] / palacios / src / palacios / svm_handler.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 #include <palacios/svm_handler.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vm_guest_mem.h>
24 #include <palacios/vmm_decoder.h>
25 #include <palacios/vmm_ctrl_regs.h>
26 #include <palacios/svm_io.h>
27 #include <palacios/svm_halt.h>
28 #include <palacios/svm_pause.h>
29 #include <palacios/svm_wbinvd.h>
30 #include <palacios/vmm_intr.h>
31 #include <palacios/vmm_emulator.h>
32 #include <palacios/svm_msr.h>
33 #include <palacios/vmm_profiler.h>
34 #include <palacios/vmm_hypercall.h>
35 #include <palacios/vmm_direct_paging.h>
36
37
38
39 int v3_handle_svm_exit(struct guest_info * info) {
40     vmcb_ctrl_t * guest_ctrl = 0;
41     vmcb_saved_state_t * guest_state = 0;
42     ulong_t exit_code = 0;
43     
44     guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
45     guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
46   
47
48     // Update the high level state 
49     info->rip = guest_state->rip;
50     info->vm_regs.rsp = guest_state->rsp;
51     info->vm_regs.rax = guest_state->rax;
52
53     info->cpl = guest_state->cpl;
54
55
56     info->ctrl_regs.cr0 = guest_state->cr0;
57     info->ctrl_regs.cr2 = guest_state->cr2;
58     info->ctrl_regs.cr3 = guest_state->cr3;
59     info->ctrl_regs.cr4 = guest_state->cr4;
60     info->dbg_regs.dr6 = guest_state->dr6;
61     info->dbg_regs.dr7 = guest_state->dr7;
62     info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
63     info->ctrl_regs.rflags = guest_state->rflags;
64     info->ctrl_regs.efer = guest_state->efer;
65     
66     get_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
67     info->cpu_mode = v3_get_vm_cpu_mode(info);
68     info->mem_mode = v3_get_vm_mem_mode(info);
69
70
71     exit_code = guest_ctrl->exit_code;
72
73
74     //  PrintDebug("SVM Exit: %s (rip=%p)\n", vmexit_code_to_str(exit_code), (void *)info->rip);
75
76     if ((info->intr_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
77
78 #ifdef DEBUG_INTERRUPTS
79         PrintDebug("Interrupt %d taken by guest\n", info->intr_state.irq_vector);
80 #endif
81         if (!guest_ctrl->exit_int_info.valid) {
82             info->intr_state.irq_pending = 0;
83             // PrintDebug("Injected Interrupt %d\n", info->intr_state.irq_vector);
84             v3_injecting_intr(info, info->intr_state.irq_vector, EXTERNAL_IRQ);
85         } else {
86 #ifdef DEBUG_INTERRUPTS
87             PrintDebug("EXIT INT INFO is set (vec=%d)\n", guest_ctrl->exit_int_info.vector);
88 #endif
89         }
90     }
91
92
93   
94
95     // Disable printing io exits due to bochs debug messages
96     //if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) {
97     
98   
99     if ((0) && (exit_code <= VMEXIT_EXCP14)) {
100         uchar_t instr[32];
101         int ret;
102         // Dump out the instr stream
103
104         //PrintDebug("RIP: %x\n", guest_state->rip);
105         PrintDebug("\n\n\nRIP Linear: %p\n", (void *)get_addr_linear(info, info->rip, &(info->segments.cs)));
106         
107         v3_print_GPRs(info);
108         v3_print_ctrl_regs(info);
109
110
111         // OK, now we will read the instruction
112         // The only difference between PROTECTED and PROTECTED_PG is whether we read
113         // from guest_pa or guest_va
114         if (info->mem_mode == PHYSICAL_MEM) { 
115             // The real rip address is actually a combination of the rip + CS base 
116             ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 32, instr);
117         } else { 
118             ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 32, instr);
119         }
120         
121
122
123         if (ret != 32) {
124             // I think we should inject a GPF into the guest
125             PrintDebug("Could not read instruction (ret=%d)\n", ret);
126         } else {
127             PrintDebug("Instr Stream:\n");
128             PrintTraceMemDump(instr, 32);
129         }
130     }
131
132
133
134     if (info->enable_profiler) {
135         rdtscll(info->profiler.start_time);
136     }
137
138   
139     //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
140
141     switch (exit_code) {
142         case VMEXIT_IOIO: {
143             struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1);
144
145             if (io_info->type == 0) {
146                 if (io_info->str) {
147
148                     if (v3_handle_svm_io_outs(info) == -1 ) {
149                         return -1;
150                     }
151                 } else {
152                     if (v3_handle_svm_io_out(info) == -1) {
153                         return -1;
154                     }
155                 }
156
157             } else {
158
159                 if (io_info->str) {
160                     if (v3_handle_svm_io_ins(info) == -1) {
161                         return -1;
162                     }
163                 } else {
164                     if (v3_handle_svm_io_in(info) == -1) {
165                         return -1;
166                     }
167                 }
168
169             }
170             break;
171         }
172         case VMEXIT_MSR:
173             if (guest_ctrl->exit_info1 == 0) {
174                 if (v3_handle_msr_read(info) == -1) {
175                     return -1;
176                 }
177             } else if (guest_ctrl->exit_info1 == 1) {
178                 if (v3_handle_msr_write(info) == -1) {
179                     return -1;
180                 }
181             } else {
182                 PrintError("Invalid MSR Operation\n");
183                 return -1;
184             }
185                 
186             break;
187         case VMEXIT_CR0_WRITE: 
188 #ifdef DEBUG_CTRL_REGS
189             PrintDebug("CR0 Write\n");
190 #endif
191             if (v3_handle_cr0_write(info) == -1) {
192                 return -1;
193             }
194             break;
195         case VMEXIT_CR0_READ: 
196 #ifdef DEBUG_CTRL_REGS
197             PrintDebug("CR0 Read\n");
198 #endif
199             if (v3_handle_cr0_read(info) == -1) {
200                 return -1;
201             }
202             break;
203         case VMEXIT_CR3_WRITE: 
204 #ifdef DEBUG_CTRL_REGS
205             PrintDebug("CR3 Write\n");
206 #endif
207             if (v3_handle_cr3_write(info) == -1) {
208                 return -1;
209             }    
210             break;
211         case  VMEXIT_CR3_READ: 
212 #ifdef DEBUG_CTRL_REGS
213             PrintDebug("CR3 Read\n");
214 #endif
215             if (v3_handle_cr3_read(info) == -1) {
216                 return -1;
217             }
218             break;
219         case VMEXIT_CR4_WRITE: 
220 #ifdef DEBUG_CTRL_REGS
221             PrintDebug("CR4 Write\n");
222 #endif
223             if (v3_handle_cr4_write(info) == -1) {
224                 return -1;
225             }    
226             break;
227         case  VMEXIT_CR4_READ: 
228 #ifdef DEBUG_CTRL_REGS
229             PrintDebug("CR4 Read\n");
230 #endif
231             if (v3_handle_cr4_read(info) == -1) {
232                 return -1;
233             }
234             break;
235         case VMEXIT_EXCP14: {
236             addr_t fault_addr = guest_ctrl->exit_info2;
237             pf_error_t * error_code = (pf_error_t *)&(guest_ctrl->exit_info1);
238 #ifdef DEBUG_SHADOW_PAGING
239             PrintDebug("PageFault at %p (error=%d)\n", 
240                        (void *)fault_addr, *(uint_t *)error_code);
241 #endif
242             if (info->shdw_pg_mode == SHADOW_PAGING) {
243                 if (v3_handle_shadow_pagefault(info, fault_addr, *error_code) == -1) {
244                     return -1;
245                 }
246             } else {
247                 PrintError("Page fault in un implemented paging mode\n");
248                 return -1;
249             }
250             break;
251         } 
252         case VMEXIT_NPF: {
253             addr_t fault_addr = guest_ctrl->exit_info2;
254             pf_error_t * error_code = (pf_error_t *)&(guest_ctrl->exit_info1);
255
256             if (info->shdw_pg_mode == NESTED_PAGING) {
257                 if (v3_handle_nested_pagefault(info, fault_addr, *error_code) == -1) {
258                     return -1;
259                 }
260             } else {
261                 PrintError("Currently unhandled Nested Page Fault\n");
262                 return -1;
263                     }
264             break;
265             }
266         case VMEXIT_INVLPG: 
267             if (info->shdw_pg_mode == SHADOW_PAGING) {
268 #ifdef DEBUG_SHADOW_PAGING
269                 PrintDebug("Invlpg\n");
270 #endif
271                 if (v3_handle_shadow_invlpg(info) == -1) {
272                     return -1;
273                 }
274             }
275             break;    
276         case VMEXIT_VMMCALL: 
277             /* 
278              * Hypercall 
279              */
280                 
281             if (v3_handle_hypercall(info) == -1) {
282                 return -1;
283             }
284                 
285             // VMMCALL is a 3 byte op
286             info->rip += 3;
287             break;          
288         case VMEXIT_INTR:
289             // handled by interrupt dispatch earlier
290             break;
291         case VMEXIT_SMI:
292             //   handle_svm_smi(info); // ignored for now
293             break;
294         case VMEXIT_HLT:
295 #ifdef DEBUG_HALT
296             PrintDebug("Guest halted\n");
297 #endif
298             if (v3_handle_svm_halt(info) == -1) {
299                 return -1;
300             }
301             break;
302         case VMEXIT_PAUSE:
303             //PrintDebug("Guest paused\n");
304             if (v3_handle_svm_pause(info) == -1) { 
305                 return -1;
306             }
307             break;
308         case VMEXIT_WBINVD:   
309 #ifdef DEBUG_EMULATOR
310             PrintDebug("WBINVD\n");
311 #endif
312             if (v3_handle_svm_wbinvd(info) == -1) { 
313                 return -1;
314             }
315             break;
316         
317
318
319
320
321             /* Exits Following this line are NOT HANDLED */
322             /*=======================================================================*/
323             
324         default: {
325
326             addr_t rip_addr;
327             
328             PrintDebug("Unhandled SVM Exit: %s\n", vmexit_code_to_str(exit_code));
329             
330             rip_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
331             
332             
333             PrintError("SVM Returned:(VMCB=%p)\n", (void *)(info->vmm_data)); 
334             PrintError("RIP: %p\n", (void *)(addr_t)(guest_state->rip));
335             PrintError("RIP Linear: %p\n", (void *)(addr_t)(rip_addr));
336             
337             PrintError("SVM Returned: Exit Code: %p\n", (void *)(addr_t)exit_code); 
338             
339             PrintError("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
340             PrintError("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
341             
342             PrintError("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
343             PrintError("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
344             
345             
346             if (info->shdw_pg_mode == SHADOW_PAGING) {
347                 //      PrintHostPageTables(info, info->ctrl_regs.cr3);
348                 //PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3);
349             }
350             
351             return -1;              
352         }
353     }
354     // END OF SWITCH (EXIT_CODE)
355
356
357     if (info->enable_profiler) {
358         rdtscll(info->profiler.end_time);
359         v3_profile_exit(info, exit_code);
360     }
361
362
363     // Update the low level state
364     if (v3_excp_pending(info)) {
365         uint_t excp = v3_get_excp_number(info);
366         
367         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
368         
369         if (info->excp_state.excp_error_code_valid) {
370             guest_ctrl->EVENTINJ.error_code = info->excp_state.excp_error_code;
371             guest_ctrl->EVENTINJ.ev = 1;
372 #ifdef DEBUG_INTERRUPTS
373             PrintDebug("Injecting exception %d with error code %x\n", excp, guest_ctrl->EVENTINJ.error_code);
374 #endif
375         }
376         
377         guest_ctrl->EVENTINJ.vector = excp;
378         
379         guest_ctrl->EVENTINJ.valid = 1;
380 #ifdef DEBUG_INTERRUPTS
381         PrintDebug("Injecting Exception %d (EIP=%p)\n", 
382                    guest_ctrl->EVENTINJ.vector, 
383                    (void *)(addr_t)info->rip);
384 #endif
385         v3_injecting_excp(info, excp);
386     } else if (info->intr_state.irq_pending == 1) {
387 #ifdef DEBUG_INTERRUPTS
388         PrintDebug("IRQ pending from previous injection\n");
389 #endif
390         guest_ctrl->guest_ctrl.V_IRQ = 1;
391         guest_ctrl->guest_ctrl.V_INTR_VECTOR = info->intr_state.irq_vector;
392         guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
393         guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
394
395     } else if (v3_intr_pending(info)) {
396
397         switch (v3_get_intr_type(info)) {
398             case EXTERNAL_IRQ: {
399                 uint_t irq = v3_get_intr_number(info);
400                     
401                 // check to see if ==-1 (non exists)
402                     
403                     
404                 guest_ctrl->guest_ctrl.V_IRQ = 1;
405                 guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq;
406                 guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
407                 guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
408
409 #ifdef DEBUG_INTERRUPTS
410                 PrintDebug("Injecting Interrupt %d (EIP=%p)\n", 
411                            guest_ctrl->guest_ctrl.V_INTR_VECTOR, 
412                            (void *)(addr_t)info->rip);
413 #endif
414
415                 info->intr_state.irq_pending = 1;
416                 info->intr_state.irq_vector = irq;
417                     
418                 break;
419             }
420             case NMI:
421                 guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
422                 break;
423             case SOFTWARE_INTR:
424                 guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
425                 break;
426             case VIRTUAL_INTR:
427                 guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
428                 break;
429                 
430             case INVALID_INTR: 
431             default:
432                 PrintError("Attempted to issue an invalid interrupt\n");
433                 return -1;
434         }
435         
436     } else {
437         //PrintDebug("Not interrupts or exceptions pending\n");
438     }
439
440
441     guest_state->cr0 = info->ctrl_regs.cr0;
442     guest_state->cr2 = info->ctrl_regs.cr2;
443     guest_state->cr3 = info->ctrl_regs.cr3;
444     guest_state->cr4 = info->ctrl_regs.cr4;
445     guest_state->dr6 = info->dbg_regs.dr6;
446     guest_state->dr7 = info->dbg_regs.dr7;
447     guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
448     guest_state->rflags = info->ctrl_regs.rflags;
449     guest_state->efer = info->ctrl_regs.efer;
450     
451     guest_state->cpl = info->cpl;
452
453     guest_state->rax = info->vm_regs.rax;
454     guest_state->rip = info->rip;
455     guest_state->rsp = info->vm_regs.rsp;
456
457
458     set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
459
460     if (exit_code == VMEXIT_INTR) {
461         //PrintDebug("INTR ret IP = %x\n", guest_state->rip);
462     }
463     
464     return 0;
465 }
466
467
468 static const char VMEXIT_CR0_READ_STR[] = "VMEXIT_CR0_READ";
469 static const char VMEXIT_CR1_READ_STR[] = "VMEXIT_CR1_READ";
470 static const char VMEXIT_CR2_READ_STR[] = "VMEXIT_CR2_READ";
471 static const char VMEXIT_CR3_READ_STR[] = "VMEXIT_CR3_READ";
472 static const char VMEXIT_CR4_READ_STR[] = "VMEXIT_CR4_READ";
473 static const char VMEXIT_CR5_READ_STR[] = "VMEXIT_CR5_READ";
474 static const char VMEXIT_CR6_READ_STR[] = "VMEXIT_CR6_READ";
475 static const char VMEXIT_CR7_READ_STR[] = "VMEXIT_CR7_READ";
476 static const char VMEXIT_CR8_READ_STR[] = "VMEXIT_CR8_READ";
477 static const char VMEXIT_CR9_READ_STR[] = "VMEXIT_CR9_READ";
478 static const char VMEXIT_CR10_READ_STR[] = "VMEXIT_CR10_READ";
479 static const char VMEXIT_CR11_READ_STR[] = "VMEXIT_CR11_READ";
480 static const char VMEXIT_CR12_READ_STR[] = "VMEXIT_CR12_READ";
481 static const char VMEXIT_CR13_READ_STR[] = "VMEXIT_CR13_READ";
482 static const char VMEXIT_CR14_READ_STR[] = "VMEXIT_CR14_READ";
483 static const char VMEXIT_CR15_READ_STR[] = "VMEXIT_CR15_READ";
484 static const char VMEXIT_CR0_WRITE_STR[] = "VMEXIT_CR0_WRITE";
485 static const char VMEXIT_CR1_WRITE_STR[] = "VMEXIT_CR1_WRITE";
486 static const char VMEXIT_CR2_WRITE_STR[] = "VMEXIT_CR2_WRITE";
487 static const char VMEXIT_CR3_WRITE_STR[] = "VMEXIT_CR3_WRITE";
488 static const char VMEXIT_CR4_WRITE_STR[] = "VMEXIT_CR4_WRITE";
489 static const char VMEXIT_CR5_WRITE_STR[] = "VMEXIT_CR5_WRITE";
490 static const char VMEXIT_CR6_WRITE_STR[] = "VMEXIT_CR6_WRITE";
491 static const char VMEXIT_CR7_WRITE_STR[] = "VMEXIT_CR7_WRITE";
492 static const char VMEXIT_CR8_WRITE_STR[] = "VMEXIT_CR8_WRITE";
493 static const char VMEXIT_CR9_WRITE_STR[] = "VMEXIT_CR9_WRITE";
494 static const char VMEXIT_CR10_WRITE_STR[] = "VMEXIT_CR10_WRITE";
495 static const char VMEXIT_CR11_WRITE_STR[] = "VMEXIT_CR11_WRITE";
496 static const char VMEXIT_CR12_WRITE_STR[] = "VMEXIT_CR12_WRITE";
497 static const char VMEXIT_CR13_WRITE_STR[] = "VMEXIT_CR13_WRITE";
498 static const char VMEXIT_CR14_WRITE_STR[] = "VMEXIT_CR14_WRITE";
499 static const char VMEXIT_CR15_WRITE_STR[] = "VMEXIT_CR15_WRITE";
500 static const char VMEXIT_DR0_READ_STR[] = "VMEXIT_DR0_READ";
501 static const char VMEXIT_DR1_READ_STR[] = "VMEXIT_DR1_READ";
502 static const char VMEXIT_DR2_READ_STR[] = "VMEXIT_DR2_READ";
503 static const char VMEXIT_DR3_READ_STR[] = "VMEXIT_DR3_READ";
504 static const char VMEXIT_DR4_READ_STR[] = "VMEXIT_DR4_READ";
505 static const char VMEXIT_DR5_READ_STR[] = "VMEXIT_DR5_READ";
506 static const char VMEXIT_DR6_READ_STR[] = "VMEXIT_DR6_READ";
507 static const char VMEXIT_DR7_READ_STR[] = "VMEXIT_DR7_READ";
508 static const char VMEXIT_DR8_READ_STR[] = "VMEXIT_DR8_READ";
509 static const char VMEXIT_DR9_READ_STR[] = "VMEXIT_DR9_READ";
510 static const char VMEXIT_DR10_READ_STR[] = "VMEXIT_DR10_READ";
511 static const char VMEXIT_DR11_READ_STR[] = "VMEXIT_DR11_READ";
512 static const char VMEXIT_DR12_READ_STR[] = "VMEXIT_DR12_READ";
513 static const char VMEXIT_DR13_READ_STR[] = "VMEXIT_DR13_READ";
514 static const char VMEXIT_DR14_READ_STR[] = "VMEXIT_DR14_READ";
515 static const char VMEXIT_DR15_READ_STR[] = "VMEXIT_DR15_READ";
516 static const char VMEXIT_DR0_WRITE_STR[] = "VMEXIT_DR0_WRITE";
517 static const char VMEXIT_DR1_WRITE_STR[] = "VMEXIT_DR1_WRITE";
518 static const char VMEXIT_DR2_WRITE_STR[] = "VMEXIT_DR2_WRITE";
519 static const char VMEXIT_DR3_WRITE_STR[] = "VMEXIT_DR3_WRITE";
520 static const char VMEXIT_DR4_WRITE_STR[] = "VMEXIT_DR4_WRITE";
521 static const char VMEXIT_DR5_WRITE_STR[] = "VMEXIT_DR5_WRITE";
522 static const char VMEXIT_DR6_WRITE_STR[] = "VMEXIT_DR6_WRITE";
523 static const char VMEXIT_DR7_WRITE_STR[] = "VMEXIT_DR7_WRITE";
524 static const char VMEXIT_DR8_WRITE_STR[] = "VMEXIT_DR8_WRITE";
525 static const char VMEXIT_DR9_WRITE_STR[] = "VMEXIT_DR9_WRITE";
526 static const char VMEXIT_DR10_WRITE_STR[] = "VMEXIT_DR10_WRITE";
527 static const char VMEXIT_DR11_WRITE_STR[] = "VMEXIT_DR11_WRITE";
528 static const char VMEXIT_DR12_WRITE_STR[] = "VMEXIT_DR12_WRITE";
529 static const char VMEXIT_DR13_WRITE_STR[] = "VMEXIT_DR13_WRITE";
530 static const char VMEXIT_DR14_WRITE_STR[] = "VMEXIT_DR14_WRITE";
531 static const char VMEXIT_DR15_WRITE_STR[] = "VMEXIT_DR15_WRITE";
532 static const char VMEXIT_EXCP0_STR[] = "VMEXIT_EXCP0";
533 static const char VMEXIT_EXCP1_STR[] = "VMEXIT_EXCP1";
534 static const char VMEXIT_EXCP2_STR[] = "VMEXIT_EXCP2";
535 static const char VMEXIT_EXCP3_STR[] = "VMEXIT_EXCP3";
536 static const char VMEXIT_EXCP4_STR[] = "VMEXIT_EXCP4";
537 static const char VMEXIT_EXCP5_STR[] = "VMEXIT_EXCP5";
538 static const char VMEXIT_EXCP6_STR[] = "VMEXIT_EXCP6";
539 static const char VMEXIT_EXCP7_STR[] = "VMEXIT_EXCP7";
540 static const char VMEXIT_EXCP8_STR[] = "VMEXIT_EXCP8";
541 static const char VMEXIT_EXCP9_STR[] = "VMEXIT_EXCP9";
542 static const char VMEXIT_EXCP10_STR[] = "VMEXIT_EXCP10";
543 static const char VMEXIT_EXCP11_STR[] = "VMEXIT_EXCP11";
544 static const char VMEXIT_EXCP12_STR[] = "VMEXIT_EXCP12";
545 static const char VMEXIT_EXCP13_STR[] = "VMEXIT_EXCP13";
546 static const char VMEXIT_EXCP14_STR[] = "VMEXIT_EXCP14";
547 static const char VMEXIT_EXCP15_STR[] = "VMEXIT_EXCP15";
548 static const char VMEXIT_EXCP16_STR[] = "VMEXIT_EXCP16";
549 static const char VMEXIT_EXCP17_STR[] = "VMEXIT_EXCP17";
550 static const char VMEXIT_EXCP18_STR[] = "VMEXIT_EXCP18";
551 static const char VMEXIT_EXCP19_STR[] = "VMEXIT_EXCP19";
552 static const char VMEXIT_EXCP20_STR[] = "VMEXIT_EXCP20";
553 static const char VMEXIT_EXCP21_STR[] = "VMEXIT_EXCP21";
554 static const char VMEXIT_EXCP22_STR[] = "VMEXIT_EXCP22";
555 static const char VMEXIT_EXCP23_STR[] = "VMEXIT_EXCP23";
556 static const char VMEXIT_EXCP24_STR[] = "VMEXIT_EXCP24";
557 static const char VMEXIT_EXCP25_STR[] = "VMEXIT_EXCP25";
558 static const char VMEXIT_EXCP26_STR[] = "VMEXIT_EXCP26";
559 static const char VMEXIT_EXCP27_STR[] = "VMEXIT_EXCP27";
560 static const char VMEXIT_EXCP28_STR[] = "VMEXIT_EXCP28";
561 static const char VMEXIT_EXCP29_STR[] = "VMEXIT_EXCP29";
562 static const char VMEXIT_EXCP30_STR[] = "VMEXIT_EXCP30";
563 static const char VMEXIT_EXCP31_STR[] = "VMEXIT_EXCP31";
564 static const char VMEXIT_INTR_STR[] = "VMEXIT_INTR";
565 static const char VMEXIT_NMI_STR[] = "VMEXIT_NMI";
566 static const char VMEXIT_SMI_STR[] = "VMEXIT_SMI";
567 static const char VMEXIT_INIT_STR[] = "VMEXIT_INIT";
568 static const char VMEXIT_VINITR_STR[] = "VMEXIT_VINITR";
569 static const char VMEXIT_CR0_SEL_WRITE_STR[] = "VMEXIT_CR0_SEL_WRITE";
570 static const char VMEXIT_IDTR_READ_STR[] = "VMEXIT_IDTR_READ";
571 static const char VMEXIT_GDTR_READ_STR[] = "VMEXIT_GDTR_READ";
572 static const char VMEXIT_LDTR_READ_STR[] = "VMEXIT_LDTR_READ";
573 static const char VMEXIT_TR_READ_STR[] = "VMEXIT_TR_READ";
574 static const char VMEXIT_IDTR_WRITE_STR[] = "VMEXIT_IDTR_WRITE";
575 static const char VMEXIT_GDTR_WRITE_STR[] = "VMEXIT_GDTR_WRITE";
576 static const char VMEXIT_LDTR_WRITE_STR[] = "VMEXIT_LDTR_WRITE";
577 static const char VMEXIT_TR_WRITE_STR[] = "VMEXIT_TR_WRITE";
578 static const char VMEXIT_RDTSC_STR[] = "VMEXIT_RDTSC";
579 static const char VMEXIT_RDPMC_STR[] = "VMEXIT_RDPMC";
580 static const char VMEXIT_PUSHF_STR[] = "VMEXIT_PUSHF";
581 static const char VMEXIT_POPF_STR[] = "VMEXIT_POPF";
582 static const char VMEXIT_CPUID_STR[] = "VMEXIT_CPUID";
583 static const char VMEXIT_RSM_STR[] = "VMEXIT_RSM";
584 static const char VMEXIT_IRET_STR[] = "VMEXIT_IRET";
585 static const char VMEXIT_SWINT_STR[] = "VMEXIT_SWINT";
586 static const char VMEXIT_INVD_STR[] = "VMEXIT_INVD";
587 static const char VMEXIT_PAUSE_STR[] = "VMEXIT_PAUSE";
588 static const char VMEXIT_HLT_STR[] = "VMEXIT_HLT";
589 static const char VMEXIT_INVLPG_STR[] = "VMEXIT_INVLPG";
590 static const char VMEXIT_INVLPGA_STR[] = "VMEXIT_INVLPGA";
591 static const char VMEXIT_IOIO_STR[] = "VMEXIT_IOIO";
592 static const char VMEXIT_MSR_STR[] = "VMEXIT_MSR";
593 static const char VMEXIT_TASK_SWITCH_STR[] = "VMEXIT_TASK_SWITCH";
594 static const char VMEXIT_FERR_FREEZE_STR[] = "VMEXIT_FERR_FREEZE";
595 static const char VMEXIT_SHUTDOWN_STR[] = "VMEXIT_SHUTDOWN";
596 static const char VMEXIT_VMRUN_STR[] = "VMEXIT_VMRUN";
597 static const char VMEXIT_VMMCALL_STR[] = "VMEXIT_VMMCALL";
598 static const char VMEXIT_VMLOAD_STR[] = "VMEXIT_VMLOAD";
599 static const char VMEXIT_VMSAVE_STR[] = "VMEXIT_VMSAVE";
600 static const char VMEXIT_STGI_STR[] = "VMEXIT_STGI";
601 static const char VMEXIT_CLGI_STR[] = "VMEXIT_CLGI";
602 static const char VMEXIT_SKINIT_STR[] = "VMEXIT_SKINIT";
603 static const char VMEXIT_RDTSCP_STR[] = "VMEXIT_RDTSCP";
604 static const char VMEXIT_ICEBP_STR[] = "VMEXIT_ICEBP";
605 static const char VMEXIT_WBINVD_STR[] = "VMEXIT_WBINVD";
606 static const char VMEXIT_MONITOR_STR[] = "VMEXIT_MONITOR";
607 static const char VMEXIT_MWAIT_STR[] = "VMEXIT_MWAIT";
608 static const char VMEXIT_MWAIT_CONDITIONAL_STR[] = "VMEXIT_MWAIT_CONDITIONAL";
609 static const char VMEXIT_NPF_STR[] = "VMEXIT_NPF";
610 static const char VMEXIT_INVALID_VMCB_STR[] = "VMEXIT_INVALID_VMCB";
611
612
613
614 const char * vmexit_code_to_str(uint_t exit_code) {
615     switch(exit_code) {
616         case VMEXIT_CR0_READ:
617             return VMEXIT_CR0_READ_STR;
618         case VMEXIT_CR1_READ:
619             return VMEXIT_CR1_READ_STR;
620         case VMEXIT_CR2_READ:
621             return VMEXIT_CR2_READ_STR;
622         case VMEXIT_CR3_READ:
623             return VMEXIT_CR3_READ_STR;
624         case VMEXIT_CR4_READ:
625             return VMEXIT_CR4_READ_STR;
626         case VMEXIT_CR5_READ:
627             return VMEXIT_CR5_READ_STR;
628         case VMEXIT_CR6_READ:
629             return VMEXIT_CR6_READ_STR;
630         case VMEXIT_CR7_READ:
631             return VMEXIT_CR7_READ_STR;
632         case VMEXIT_CR8_READ:
633             return VMEXIT_CR8_READ_STR;
634         case VMEXIT_CR9_READ:
635             return VMEXIT_CR9_READ_STR;
636         case VMEXIT_CR10_READ:
637             return VMEXIT_CR10_READ_STR;
638         case VMEXIT_CR11_READ:
639             return VMEXIT_CR11_READ_STR;
640         case VMEXIT_CR12_READ:
641             return VMEXIT_CR12_READ_STR;
642         case VMEXIT_CR13_READ:
643             return VMEXIT_CR13_READ_STR;
644         case VMEXIT_CR14_READ:
645             return VMEXIT_CR14_READ_STR;
646         case VMEXIT_CR15_READ:
647             return VMEXIT_CR15_READ_STR;
648         case VMEXIT_CR0_WRITE:
649             return VMEXIT_CR0_WRITE_STR;
650         case VMEXIT_CR1_WRITE:
651             return VMEXIT_CR1_WRITE_STR;
652         case VMEXIT_CR2_WRITE:
653             return VMEXIT_CR2_WRITE_STR;
654         case VMEXIT_CR3_WRITE:
655             return VMEXIT_CR3_WRITE_STR;
656         case VMEXIT_CR4_WRITE:
657             return VMEXIT_CR4_WRITE_STR;
658         case VMEXIT_CR5_WRITE:
659             return VMEXIT_CR5_WRITE_STR;
660         case VMEXIT_CR6_WRITE:
661             return VMEXIT_CR6_WRITE_STR;
662         case VMEXIT_CR7_WRITE:
663             return VMEXIT_CR7_WRITE_STR;
664         case VMEXIT_CR8_WRITE:
665             return VMEXIT_CR8_WRITE_STR;
666         case VMEXIT_CR9_WRITE:
667             return VMEXIT_CR9_WRITE_STR;
668         case VMEXIT_CR10_WRITE:
669             return VMEXIT_CR10_WRITE_STR;
670         case VMEXIT_CR11_WRITE:
671             return VMEXIT_CR11_WRITE_STR;
672         case VMEXIT_CR12_WRITE:
673             return VMEXIT_CR12_WRITE_STR;
674         case VMEXIT_CR13_WRITE:
675             return VMEXIT_CR13_WRITE_STR;
676         case VMEXIT_CR14_WRITE:
677             return VMEXIT_CR14_WRITE_STR;
678         case VMEXIT_CR15_WRITE:
679             return VMEXIT_CR15_WRITE_STR;
680         case VMEXIT_DR0_READ:
681             return VMEXIT_DR0_READ_STR;
682         case VMEXIT_DR1_READ:
683             return VMEXIT_DR1_READ_STR;
684         case VMEXIT_DR2_READ:
685             return VMEXIT_DR2_READ_STR;
686         case VMEXIT_DR3_READ:
687             return VMEXIT_DR3_READ_STR;
688         case VMEXIT_DR4_READ:
689             return VMEXIT_DR4_READ_STR;
690         case VMEXIT_DR5_READ:
691             return VMEXIT_DR5_READ_STR;
692         case VMEXIT_DR6_READ:
693             return VMEXIT_DR6_READ_STR;
694         case VMEXIT_DR7_READ:
695             return VMEXIT_DR7_READ_STR;
696         case VMEXIT_DR8_READ:
697             return VMEXIT_DR8_READ_STR;
698         case VMEXIT_DR9_READ:
699             return VMEXIT_DR9_READ_STR;
700         case VMEXIT_DR10_READ:
701             return VMEXIT_DR10_READ_STR;
702         case VMEXIT_DR11_READ:
703             return VMEXIT_DR11_READ_STR;
704         case VMEXIT_DR12_READ:
705             return VMEXIT_DR12_READ_STR;
706         case VMEXIT_DR13_READ:
707             return VMEXIT_DR13_READ_STR;
708         case VMEXIT_DR14_READ:
709             return VMEXIT_DR14_READ_STR;
710         case VMEXIT_DR15_READ:
711             return VMEXIT_DR15_READ_STR;
712         case VMEXIT_DR0_WRITE:
713             return VMEXIT_DR0_WRITE_STR;
714         case VMEXIT_DR1_WRITE:
715             return VMEXIT_DR1_WRITE_STR;
716         case VMEXIT_DR2_WRITE:
717             return VMEXIT_DR2_WRITE_STR;
718         case VMEXIT_DR3_WRITE:
719             return VMEXIT_DR3_WRITE_STR;
720         case VMEXIT_DR4_WRITE:
721             return VMEXIT_DR4_WRITE_STR;
722         case VMEXIT_DR5_WRITE:
723             return VMEXIT_DR5_WRITE_STR;
724         case VMEXIT_DR6_WRITE:
725             return VMEXIT_DR6_WRITE_STR;
726         case VMEXIT_DR7_WRITE:
727             return VMEXIT_DR7_WRITE_STR;
728         case VMEXIT_DR8_WRITE:
729             return VMEXIT_DR8_WRITE_STR;
730         case VMEXIT_DR9_WRITE:
731             return VMEXIT_DR9_WRITE_STR;
732         case VMEXIT_DR10_WRITE:
733             return VMEXIT_DR10_WRITE_STR;
734         case VMEXIT_DR11_WRITE:
735             return VMEXIT_DR11_WRITE_STR;
736         case VMEXIT_DR12_WRITE:
737             return VMEXIT_DR12_WRITE_STR;
738         case VMEXIT_DR13_WRITE:
739             return VMEXIT_DR13_WRITE_STR;
740         case VMEXIT_DR14_WRITE:
741             return VMEXIT_DR14_WRITE_STR;
742         case VMEXIT_DR15_WRITE:
743             return VMEXIT_DR15_WRITE_STR;
744         case VMEXIT_EXCP0:
745             return VMEXIT_EXCP0_STR;
746         case VMEXIT_EXCP1:
747             return VMEXIT_EXCP1_STR;
748         case VMEXIT_EXCP2:
749             return VMEXIT_EXCP2_STR;
750         case VMEXIT_EXCP3:
751             return VMEXIT_EXCP3_STR;
752         case VMEXIT_EXCP4:
753             return VMEXIT_EXCP4_STR;
754         case VMEXIT_EXCP5:
755             return VMEXIT_EXCP5_STR;
756         case VMEXIT_EXCP6:
757             return VMEXIT_EXCP6_STR;
758         case VMEXIT_EXCP7:
759             return VMEXIT_EXCP7_STR;
760         case VMEXIT_EXCP8:
761             return VMEXIT_EXCP8_STR;
762         case VMEXIT_EXCP9:
763             return VMEXIT_EXCP9_STR;
764         case VMEXIT_EXCP10:
765             return VMEXIT_EXCP10_STR;
766         case VMEXIT_EXCP11:
767             return VMEXIT_EXCP11_STR;
768         case VMEXIT_EXCP12:
769             return VMEXIT_EXCP12_STR;
770         case VMEXIT_EXCP13:
771             return VMEXIT_EXCP13_STR;
772         case VMEXIT_EXCP14:
773             return VMEXIT_EXCP14_STR;
774         case VMEXIT_EXCP15:
775             return VMEXIT_EXCP15_STR;
776         case VMEXIT_EXCP16:
777             return VMEXIT_EXCP16_STR;
778         case VMEXIT_EXCP17:
779             return VMEXIT_EXCP17_STR;
780         case VMEXIT_EXCP18:
781             return VMEXIT_EXCP18_STR;
782         case VMEXIT_EXCP19:
783             return VMEXIT_EXCP19_STR;
784         case VMEXIT_EXCP20:
785             return VMEXIT_EXCP20_STR;
786         case VMEXIT_EXCP21:
787             return VMEXIT_EXCP21_STR;
788         case VMEXIT_EXCP22:
789             return VMEXIT_EXCP22_STR;
790         case VMEXIT_EXCP23:
791             return VMEXIT_EXCP23_STR;
792         case VMEXIT_EXCP24:
793             return VMEXIT_EXCP24_STR;
794         case VMEXIT_EXCP25:
795             return VMEXIT_EXCP25_STR;
796         case VMEXIT_EXCP26:
797             return VMEXIT_EXCP26_STR;
798         case VMEXIT_EXCP27:
799             return VMEXIT_EXCP27_STR;
800         case VMEXIT_EXCP28:
801             return VMEXIT_EXCP28_STR;
802         case VMEXIT_EXCP29:
803             return VMEXIT_EXCP29_STR;
804         case VMEXIT_EXCP30:
805             return VMEXIT_EXCP30_STR;
806         case VMEXIT_EXCP31:
807             return VMEXIT_EXCP31_STR;
808         case VMEXIT_INTR:
809             return VMEXIT_INTR_STR;
810         case VMEXIT_NMI:
811             return VMEXIT_NMI_STR;
812         case VMEXIT_SMI:
813             return VMEXIT_SMI_STR;
814         case VMEXIT_INIT:
815             return VMEXIT_INIT_STR;
816         case VMEXIT_VINITR:
817             return VMEXIT_VINITR_STR;
818         case VMEXIT_CR0_SEL_WRITE:
819             return VMEXIT_CR0_SEL_WRITE_STR;
820         case VMEXIT_IDTR_READ:
821             return VMEXIT_IDTR_READ_STR;
822         case VMEXIT_GDTR_READ:
823             return VMEXIT_GDTR_READ_STR;
824         case VMEXIT_LDTR_READ:
825             return VMEXIT_LDTR_READ_STR;
826         case VMEXIT_TR_READ:
827             return VMEXIT_TR_READ_STR;
828         case VMEXIT_IDTR_WRITE:
829             return VMEXIT_IDTR_WRITE_STR;
830         case VMEXIT_GDTR_WRITE:
831             return VMEXIT_GDTR_WRITE_STR;
832         case VMEXIT_LDTR_WRITE:
833             return VMEXIT_LDTR_WRITE_STR;
834         case VMEXIT_TR_WRITE:
835             return VMEXIT_TR_WRITE_STR;
836         case VMEXIT_RDTSC:
837             return VMEXIT_RDTSC_STR;
838         case VMEXIT_RDPMC:
839             return VMEXIT_RDPMC_STR;
840         case VMEXIT_PUSHF:
841             return VMEXIT_PUSHF_STR;
842         case VMEXIT_POPF:
843             return VMEXIT_POPF_STR;
844         case VMEXIT_CPUID:
845             return VMEXIT_CPUID_STR;
846         case VMEXIT_RSM:
847             return VMEXIT_RSM_STR;
848         case VMEXIT_IRET:
849             return VMEXIT_IRET_STR;
850         case VMEXIT_SWINT:
851             return VMEXIT_SWINT_STR;
852         case VMEXIT_INVD:
853             return VMEXIT_INVD_STR;
854         case VMEXIT_PAUSE:
855             return VMEXIT_PAUSE_STR;
856         case VMEXIT_HLT:
857             return VMEXIT_HLT_STR;
858         case VMEXIT_INVLPG:
859             return VMEXIT_INVLPG_STR;
860         case VMEXIT_INVLPGA:
861             return VMEXIT_INVLPGA_STR;
862         case VMEXIT_IOIO:
863             return VMEXIT_IOIO_STR;
864         case VMEXIT_MSR:
865             return VMEXIT_MSR_STR;
866         case VMEXIT_TASK_SWITCH:
867             return VMEXIT_TASK_SWITCH_STR;
868         case VMEXIT_FERR_FREEZE:
869             return VMEXIT_FERR_FREEZE_STR;
870         case VMEXIT_SHUTDOWN:
871             return VMEXIT_SHUTDOWN_STR;
872         case VMEXIT_VMRUN:
873             return VMEXIT_VMRUN_STR;
874         case VMEXIT_VMMCALL:
875             return VMEXIT_VMMCALL_STR;
876         case VMEXIT_VMLOAD:
877             return VMEXIT_VMLOAD_STR;
878         case VMEXIT_VMSAVE:
879             return VMEXIT_VMSAVE_STR;
880         case VMEXIT_STGI:
881             return VMEXIT_STGI_STR;
882         case VMEXIT_CLGI:
883             return VMEXIT_CLGI_STR;
884         case VMEXIT_SKINIT:
885             return VMEXIT_SKINIT_STR;
886         case VMEXIT_RDTSCP:
887             return VMEXIT_RDTSCP_STR;
888         case VMEXIT_ICEBP:
889             return VMEXIT_ICEBP_STR;
890         case VMEXIT_WBINVD:
891             return VMEXIT_WBINVD_STR;
892         case VMEXIT_MONITOR:
893             return VMEXIT_MONITOR_STR;
894         case VMEXIT_MWAIT:
895             return VMEXIT_MWAIT_STR;
896         case VMEXIT_MWAIT_CONDITIONAL:
897             return VMEXIT_MWAIT_CONDITIONAL_STR;
898         case VMEXIT_NPF:
899             return VMEXIT_NPF_STR;
900         case VMEXIT_INVALID_VMCB:
901             return VMEXIT_INVALID_VMCB_STR;
902     }
903     return NULL;
904 }