Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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