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.


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