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.


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