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.


large change to break apart the guest operation mode parameters
[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->shdw_pg_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->shdw_pg_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 (info->mem_mode == PHYSICAL_MEM) {
162       if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
163         PrintDebug("Could not translate guest_state->rip to host address\n");
164         return -1;
165       }
166     } else if (info->mem_mode == VIRTUAL_MEM) {
167       if (guest_va_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
168         PrintDebug("Could not translate guest_state->rip to host address\n");
169         return -1;
170       }
171     } else {
172       PrintDebug("Invalid memory mode\n");
173       return -1;
174     }
175
176     PrintDebug("Host Address of rip = 0x%x\n", host_addr);
177
178     memset(buf, 0, 15);
179     
180     PrintDebug("Reading from 0x%x in guest\n", rip_addr);
181     
182     if (info->mem_mode == PHYSICAL_MEM) {
183       read_guest_pa_memory(info, rip_addr, 15, buf);
184     } else {
185       read_guest_va_memory(info, rip_addr, 15, buf);
186     }
187
188     PrintTraceMemDump(buf, 15);
189
190     while(1);
191
192   }
193
194
195   // Update the low level state
196
197   if (intr_pending(info)) {
198
199     switch (get_intr_type(info)) {
200     case EXTERNAL_IRQ: 
201       {
202         uint_t irq = get_intr_number(info);
203         /*      
204           guest_ctrl->EVENTINJ.vector = irq;
205           guest_ctrl->EVENTINJ.valid = 1;
206           guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
207         */
208         
209         guest_ctrl->guest_ctrl.V_IRQ = 1;
210         guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq;
211         guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
212         guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
213
214         PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->guest_ctrl.V_INTR_VECTOR, info->rip);
215
216         injecting_intr(info, irq, EXTERNAL_IRQ);
217         
218         break;
219       }
220     case NMI:
221       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
222       break;
223     case EXCEPTION:
224       {
225         uint_t excp = get_intr_number(info);
226
227         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
228         
229         if (info->intr_state.excp_error_code) {
230           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
231           guest_ctrl->EVENTINJ.ev = 1;
232         }
233         
234         guest_ctrl->EVENTINJ.vector = excp;
235         
236         PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
237         injecting_intr(info, excp, EXCEPTION);
238         break;
239       }
240     case SOFTWARE_INTR:
241       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
242       break;
243     case VIRTUAL_INTR:
244       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
245       break;
246
247     case INVALID_INTR: 
248     default:
249       PrintDebug("Attempted to issue an invalid interrupt\n");
250       return -1;
251     }
252
253   }
254
255
256   guest_state->cr0 = info->ctrl_regs.cr0;
257   guest_state->cr2 = info->ctrl_regs.cr2;
258   guest_state->cr3 = info->ctrl_regs.cr3;
259   guest_state->cr4 = info->ctrl_regs.cr4;
260   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
261   guest_state->rflags = info->ctrl_regs.rflags;
262
263
264   guest_state->cpl = info->cpl;
265
266   guest_state->rax = info->vm_regs.rax;
267   guest_state->rip = info->rip;
268   guest_state->rsp = info->vm_regs.rsp;
269
270
271   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
272
273   if (exit_code == VMEXIT_INTR) {
274     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
275   }
276
277   return 0;
278 }
279