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