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.


*** empty log message ***
[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
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
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     /*
114       (exit_code == VMEXIT_INVLPG)    ||
115       (exit_code == VMEXIT_INVLPGA)   || 
116     */
117     
118   } else if (exit_code == VMEXIT_INTR) {
119
120     //    handle_svm_intr(info);
121
122   } else if (exit_code == VMEXIT_HLT) {
123     PrintDebug("Guest halted\n");
124     return -1;
125   } else {
126     addr_t rip_addr;
127     char buf[15];
128     addr_t host_addr;
129
130
131     rip_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
132
133
134
135     PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
136     PrintDebug("RIP: %x\n", guest_state->rip);
137     PrintDebug("RIP Linear: %x\n", rip_addr);
138     
139     PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
140     
141     PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
142     PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
143     
144     PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
145     PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
146
147     
148
149     if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
150       PrintDebug("Could not translate guest_state->rip to host address\n");
151       return -1;
152     }
153
154     PrintDebug("Host Address of rip = 0x%x\n", host_addr);
155
156     memset(buf, 0, 15);
157     
158     PrintDebug("Reading from 0x%x in guest\n", rip_addr);
159     
160     read_guest_pa_memory(info, rip_addr, 15, buf);
161
162     PrintTraceMemDump(buf, 15);
163
164     while(1);
165
166   }
167
168
169   // Update the low level state
170
171   if (intr_pending(info)) {
172
173     switch (get_intr_type(info)) {
174     case EXTERNAL_IRQ: 
175       {
176         uint_t irq = get_intr_number(info);
177         guest_ctrl->EVENTINJ.vector = irq;
178         guest_ctrl->EVENTINJ.valid = 1;
179         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
180         
181         injecting_intr(info, irq, EXTERNAL_IRQ);
182         
183         break;
184       }
185     case NMI:
186       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
187       break;
188     case EXCEPTION:
189       {
190         uint_t excp = get_intr_number(info);
191
192         guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
193         
194         if (info->intr_state.excp_error_code) {
195           guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
196           guest_ctrl->EVENTINJ.ev = 1;
197         }
198         
199         guest_ctrl->EVENTINJ.vector = excp;
200         
201         injecting_intr(info, excp, EXCEPTION);
202         break;
203       }
204     case SOFTWARE:
205       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
206       break;
207     case VIRTUAL:
208       guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
209       break;
210
211     case INVALID_INTR: 
212     default:
213       PrintDebug("Attempted to issue an invalid interrupt\n");
214       return -1;
215     }
216
217     PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
218   }
219
220
221   guest_state->cr0 = info->ctrl_regs.cr0;
222   guest_state->cr2 = info->ctrl_regs.cr2;
223   guest_state->cr3 = info->ctrl_regs.cr3;
224   guest_state->cr4 = info->ctrl_regs.cr4;
225   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
226   guest_state->rflags = info->ctrl_regs.rflags;
227
228
229   guest_state->rax = info->vm_regs.rax;
230   guest_state->rip = info->rip;
231   guest_state->rsp = info->vm_regs.rsp;
232
233
234   set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
235
236   if (exit_code == VMEXIT_INTR) {
237     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
238   }
239
240   return 0;
241 }
242