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 timer support...
[palacios.releases.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         guest_ctrl->EVENTINJ.vector = irq;
190         guest_ctrl->EVENTINJ.valid = 1;
191         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
192         
193         injecting_intr(info, irq, EXTERNAL_IRQ);
194         
195         break;
196       }
197     case NMI:
198       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
199       break;
200     case EXCEPTION:
201       {
202         uint_t excp = get_intr_number(info);
203
204         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
205         
206         if (info->intr_state.excp_error_code) {
207           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
208           guest_ctrl->EVENTINJ.ev = 1;
209         }
210         
211         guest_ctrl->EVENTINJ.vector = excp;
212         
213         injecting_intr(info, excp, EXCEPTION);
214         break;
215       }
216     case SOFTWARE:
217       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
218       break;
219     case VIRTUAL:
220       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
221       break;
222
223     case INVALID_INTR: 
224     default:
225       PrintDebug("Attempted to issue an invalid interrupt\n");
226       return -1;
227     }
228
229     PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
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->cpl = info->cpl;
242
243   guest_state->rax = info->vm_regs.rax;
244   guest_state->rip = info->rip;
245   guest_state->rsp = info->vm_regs.rsp;
246
247
248   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
249
250   if (exit_code == VMEXIT_INTR) {
251     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
252   }
253
254   return 0;
255 }
256