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