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