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.


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