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.


83f76283b35933f40395705bfa00cc1e81157724
[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 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         injecting_intr(info, irq, EXTERNAL_IRQ);
201         
202         break;
203       }
204     case NMI:
205       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
206       break;
207     case EXCEPTION:
208       {
209         uint_t excp = get_intr_number(info);
210
211         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
212         
213         if (info->intr_state.excp_error_code) {
214           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
215           guest_ctrl->EVENTINJ.ev = 1;
216         }
217         
218         guest_ctrl->EVENTINJ.vector = excp;
219         
220         injecting_intr(info, excp, EXCEPTION);
221         break;
222       }
223     case SOFTWARE:
224       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
225       break;
226     case VIRTUAL:
227       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
228       break;
229
230     case INVALID_INTR: 
231     default:
232       PrintDebug("Attempted to issue an invalid interrupt\n");
233       return -1;
234     }
235
236     PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
237   }
238
239
240   guest_state->cr0 = info->ctrl_regs.cr0;
241   guest_state->cr2 = info->ctrl_regs.cr2;
242   guest_state->cr3 = info->ctrl_regs.cr3;
243   guest_state->cr4 = info->ctrl_regs.cr4;
244   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
245   guest_state->rflags = info->ctrl_regs.rflags;
246
247
248   guest_state->cpl = info->cpl;
249
250   guest_state->rax = info->vm_regs.rax;
251   guest_state->rip = info->rip;
252   guest_state->rsp = info->vm_regs.rsp;
253
254
255   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
256
257   if (exit_code == VMEXIT_INTR) {
258     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
259   }
260
261   return 0;
262 }
263