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.


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