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 decoder
[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/vmm_intr.h>
8
9
10 int handle_svm_exit(struct guest_info * info) {
11   vmcb_ctrl_t * guest_ctrl = 0;
12   vmcb_saved_state_t * guest_state = 0;
13   ulong_t exit_code = 0;
14   
15   guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
16   guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
17   
18
19   // Update the high level state 
20   info->rip = guest_state->rip;
21   info->vm_regs.rsp = guest_state->rsp;
22   info->vm_regs.rax = guest_state->rax;
23
24   info->cpl = guest_state->cpl;
25
26
27   info->ctrl_regs.cr0 = guest_state->cr0;
28   info->ctrl_regs.cr2 = guest_state->cr2;
29   info->ctrl_regs.cr3 = guest_state->cr3;
30   info->ctrl_regs.cr4 = guest_state->cr4;
31   info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
32   info->ctrl_regs.rflags = guest_state->rflags;
33
34   get_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
35
36
37   exit_code = guest_ctrl->exit_code;
38  
39
40   // Disable printing io exits due to bochs debug messages
41   //if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) {
42
43   PrintDebug("SVM Returned: Exit Code: %x \t\t(tsc=%ul)\n",exit_code, (uint_t)info->time_state.guest_tsc); 
44     //  }
45   // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
46
47
48   // PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
49   //PrintDebug("RIP: %x\n", guest_state->rip);
50
51   
52   //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
53   
54   if (exit_code == VMEXIT_IOIO) {
55     struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1);
56     
57     if (io_info->type == 0) {
58       if (io_info->str) {
59         if (handle_svm_io_outs(info) == -1 ) {
60           return -1;
61         }
62       } else {
63         if (handle_svm_io_out(info) == -1) {
64           return -1;
65         }
66       }
67     } else {
68       if (io_info->str) {
69         if (handle_svm_io_ins(info) == -1) {
70           return -1;
71         }
72       } else {
73         if (handle_svm_io_in(info) == -1) {
74           return -1;
75         }
76       }
77     }
78   } else if (exit_code == VMEXIT_CR0_WRITE) {
79     PrintDebug("CR0 Write\n");
80
81     if (handle_cr0_write(info) == -1) {
82       return -1;
83     }
84   } else if (exit_code == VMEXIT_CR0_READ) {
85     PrintDebug("CR0 Read\n");
86
87     if (handle_cr0_read(info) == -1) {
88       return -1;
89     }
90   } else if (exit_code == VMEXIT_CR3_WRITE) {
91     PrintDebug("CR3 Write\n");
92
93     if (handle_cr3_write(info) == -1) {
94       return -1;
95     }    
96   } else if (exit_code == VMEXIT_CR3_READ) {
97     PrintDebug("CR3 Read\n");
98
99     if (handle_cr3_read(info) == -1) {
100       return -1;
101     }
102
103   } else if (exit_code == VMEXIT_EXCP14) {
104     addr_t fault_addr = guest_ctrl->exit_info2;
105     pf_error_t * error_code = (pf_error_t *)&(guest_ctrl->exit_info1);
106     
107     PrintDebug("PageFault at %x (error=%d)\n", fault_addr, *error_code);
108
109     if (info->page_mode == SHADOW_PAGING) {
110       if (handle_shadow_pagefault(info, fault_addr, *error_code) == -1) {
111         return -1;
112       }
113     } else {
114       PrintDebug("Page fault in un implemented paging mode\n");
115       return -1;
116     }
117
118   } else if (exit_code == VMEXIT_INVLPG) {
119     if (info->page_mode == SHADOW_PAGING) {
120       PrintDebug("Invlpg\n");
121       if (handle_shadow_invlpg(info) == -1) {
122         return -1;
123       }
124     }
125    
126     /*
127       (exit_code == VMEXIT_INVLPGA)   || 
128     */
129     
130   } else if (exit_code == VMEXIT_INTR) {
131
132     //    handle_svm_intr(info);
133
134   } else if (exit_code == VMEXIT_HLT) {
135     PrintDebug("Guest halted\n");
136     return -1;
137   } else {
138     addr_t rip_addr;
139     char buf[15];
140     addr_t host_addr;
141
142
143     rip_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
144
145
146
147     PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
148     PrintDebug("RIP: %x\n", guest_state->rip);
149     PrintDebug("RIP Linear: %x\n", rip_addr);
150     
151     PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
152     
153     PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
154     PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
155     
156     PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
157     PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
158
159     
160
161     if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
162       PrintDebug("Could not translate guest_state->rip to host address\n");
163       return -1;
164     }
165
166     PrintDebug("Host Address of rip = 0x%x\n", host_addr);
167
168     memset(buf, 0, 15);
169     
170     PrintDebug("Reading from 0x%x in guest\n", rip_addr);
171     
172     read_guest_pa_memory(info, rip_addr, 15, buf);
173
174     PrintTraceMemDump(buf, 15);
175
176     while(1);
177
178   }
179
180
181   // Update the low level state
182
183   if (intr_pending(info)) {
184
185     switch (get_intr_type(info)) {
186     case EXTERNAL_IRQ: 
187       {
188         uint_t irq = get_intr_number(info);
189         /*      
190           guest_ctrl->EVENTINJ.vector = irq;
191           guest_ctrl->EVENTINJ.valid = 1;
192           guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
193         */
194         
195         guest_ctrl->guest_ctrl.V_IRQ = 1;
196         guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq;
197         guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
198         guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
199
200         PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->guest_ctrl.V_INTR_VECTOR, info->rip);
201
202         injecting_intr(info, irq, EXTERNAL_IRQ);
203         
204         break;
205       }
206     case NMI:
207       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
208       break;
209     case EXCEPTION:
210       {
211         uint_t excp = get_intr_number(info);
212
213         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
214         
215         if (info->intr_state.excp_error_code) {
216           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
217           guest_ctrl->EVENTINJ.ev = 1;
218         }
219         
220         guest_ctrl->EVENTINJ.vector = excp;
221         
222         PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
223         injecting_intr(info, excp, EXCEPTION);
224         break;
225       }
226     case SOFTWARE:
227       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
228       break;
229     case VIRTUAL:
230       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
231       break;
232
233     case INVALID_INTR: 
234     default:
235       PrintDebug("Attempted to issue an invalid interrupt\n");
236       return -1;
237     }
238
239   }
240
241
242   guest_state->cr0 = info->ctrl_regs.cr0;
243   guest_state->cr2 = info->ctrl_regs.cr2;
244   guest_state->cr3 = info->ctrl_regs.cr3;
245   guest_state->cr4 = info->ctrl_regs.cr4;
246   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
247   guest_state->rflags = info->ctrl_regs.rflags;
248
249
250   guest_state->cpl = info->cpl;
251
252   guest_state->rax = info->vm_regs.rax;
253   guest_state->rip = info->rip;
254   guest_state->rsp = info->vm_regs.rsp;
255
256
257   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
258
259   if (exit_code == VMEXIT_INTR) {
260     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
261   }
262
263   return 0;
264 }
265