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 invlpg support
[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   //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
40   // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
41
42
43   // PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
44   //PrintDebug("RIP: %x\n", guest_state->rip);
45
46   
47   //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
48   
49   if (exit_code == VMEXIT_IOIO) {
50     struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1);
51     
52     if (io_info->type == 0) {
53       if (io_info->str) {
54         if (handle_svm_io_outs(info) == -1 ) {
55           return -1;
56         }
57       } else {
58         if (handle_svm_io_out(info) == -1) {
59           return -1;
60         }
61       }
62     } else {
63       if (io_info->str) {
64         if (handle_svm_io_ins(info) == -1) {
65           return -1;
66         }
67       } else {
68         if (handle_svm_io_in(info) == -1) {
69           return -1;
70         }
71       }
72     }
73   } else if (exit_code == VMEXIT_CR0_WRITE) {
74     PrintDebug("CR0 Write\n");
75
76     if (handle_cr0_write(info) == -1) {
77       return -1;
78     }
79   } else if (exit_code == VMEXIT_CR0_READ) {
80     PrintDebug("CR0 Read\n");
81
82     if (handle_cr0_read(info) == -1) {
83       return -1;
84     }
85   } else if (exit_code == VMEXIT_CR3_WRITE) {
86     PrintDebug("CR3 Write\n");
87
88     if (handle_cr3_write(info) == -1) {
89       return -1;
90     }    
91   } else if (exit_code == VMEXIT_CR3_READ) {
92     PrintDebug("CR3 Read\n");
93
94     if (handle_cr3_read(info) == -1) {
95       return -1;
96     }
97
98   } else if (exit_code == VMEXIT_EXCP14) {
99     addr_t fault_addr = guest_ctrl->exit_info2;
100     pf_error_t * error_code = (pf_error_t *)&(guest_ctrl->exit_info1);
101     
102     PrintDebug("PageFault at %x (error=%d)\n", fault_addr, *error_code);
103
104     if (info->page_mode == SHADOW_PAGING) {
105       if (handle_shadow_pagefault(info, fault_addr, *error_code) == -1) {
106         return -1;
107       }
108     } else {
109       PrintDebug("Page fault in un implemented paging mode\n");
110       return -1;
111     }
112
113   } else if (exit_code == VMEXIT_INVLPG) {
114     if (info->page_mode == SHADOW_PAGING) {
115       PrintDebug("Invlpg\n");
116       if (handle_shadow_invlpg(info) == -1) {
117         return -1;
118       }
119     }
120    
121     /*
122       (exit_code == VMEXIT_INVLPGA)   || 
123     */
124     
125   } else if (exit_code == VMEXIT_INTR) {
126
127     //    handle_svm_intr(info);
128
129   } else if (exit_code == VMEXIT_HLT) {
130     PrintDebug("Guest halted\n");
131     return -1;
132   } else {
133     addr_t rip_addr;
134     char buf[15];
135     addr_t host_addr;
136
137
138     rip_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
139
140
141
142     PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
143     PrintDebug("RIP: %x\n", guest_state->rip);
144     PrintDebug("RIP Linear: %x\n", rip_addr);
145     
146     PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
147     
148     PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
149     PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
150     
151     PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
152     PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
153
154     
155
156     if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
157       PrintDebug("Could not translate guest_state->rip to host address\n");
158       return -1;
159     }
160
161     PrintDebug("Host Address of rip = 0x%x\n", host_addr);
162
163     memset(buf, 0, 15);
164     
165     PrintDebug("Reading from 0x%x in guest\n", rip_addr);
166     
167     read_guest_pa_memory(info, rip_addr, 15, buf);
168
169     PrintTraceMemDump(buf, 15);
170
171     while(1);
172
173   }
174
175
176   // Update the low level state
177
178   if (intr_pending(info)) {
179
180     switch (get_intr_type(info)) {
181     case EXTERNAL_IRQ: 
182       {
183         uint_t irq = get_intr_number(info);
184         guest_ctrl->EVENTINJ.vector = irq;
185         guest_ctrl->EVENTINJ.valid = 1;
186         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
187         
188         injecting_intr(info, irq, EXTERNAL_IRQ);
189         
190         break;
191       }
192     case NMI:
193       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
194       break;
195     case EXCEPTION:
196       {
197         uint_t excp = get_intr_number(info);
198
199         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
200         
201         if (info->intr_state.excp_error_code) {
202           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
203           guest_ctrl->EVENTINJ.ev = 1;
204         }
205         
206         guest_ctrl->EVENTINJ.vector = excp;
207         
208         injecting_intr(info, excp, EXCEPTION);
209         break;
210       }
211     case SOFTWARE:
212       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
213       break;
214     case VIRTUAL:
215       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
216       break;
217
218     case INVALID_INTR: 
219     default:
220       PrintDebug("Attempted to issue an invalid interrupt\n");
221       return -1;
222     }
223
224     PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
225   }
226
227
228   guest_state->cr0 = info->ctrl_regs.cr0;
229   guest_state->cr2 = info->ctrl_regs.cr2;
230   guest_state->cr3 = info->ctrl_regs.cr3;
231   guest_state->cr4 = info->ctrl_regs.cr4;
232   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
233   guest_state->rflags = info->ctrl_regs.rflags;
234
235
236   guest_state->cpl = info->cpl;
237
238   guest_state->rax = info->vm_regs.rax;
239   guest_state->rip = info->rip;
240   guest_state->rsp = info->vm_regs.rsp;
241
242
243   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
244
245   if (exit_code == VMEXIT_INTR) {
246     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
247   }
248
249   return 0;
250 }
251