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.


svm_io.c: these now continue to operate on OUTS, INS even if the address type
[palacios.git] / palacios / src / palacios / svm_io.c
1 #include <palacios/svm_io.h>
2 #include <palacios/vmm_io.h>
3 #include <palacios/vmm_ctrl_regs.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6
7
8 // This should package up an IO request and call vmm_handle_io
9 int handle_svm_io_in(struct guest_info * info) {
10   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
11   //  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
12   struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
13
14   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
15   uint_t read_size = 0;
16
17   if (hook == NULL) {
18     PrintDebug("Hook Not present for in on port %x\n", io_info->port);
19     // error, we should not have exited on this port
20     return -1;
21   }
22
23
24   if (io_info->sz8) { 
25     read_size = 1;
26   } else if (io_info->sz16) {
27     read_size = 2;
28   } else if (io_info->sz32) {
29     read_size = 4;
30   }
31
32   PrintDebug("IN of %d bytes on port %d (0x%x)\n", read_size, io_info->port, io_info->port);
33
34   if (hook->read(io_info->port, &(info->vm_regs.rax), read_size, hook->priv_data) != read_size) {
35     // not sure how we handle errors.....
36     PrintDebug("Read Failure for in on port %x\n", io_info->port);
37     return -1;
38   }
39
40   info->rip = ctrl_area->exit_info2;
41
42   return 0;
43 }
44
45
46
47
48
49 /* We might not handle wrap around of the RDI register correctly...
50  * In that if we do wrap around the effect will manifest in the higher bits of the register
51  */
52 int handle_svm_io_ins(struct guest_info * info) {
53   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
54   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
55   
56   struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
57   
58   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
59   uint_t read_size = 0;
60
61   addr_t dst_addr = 0;
62   uint_t rep_num = 1;
63   ullong_t mask = 0;
64
65
66
67   // This is kind of hacky...
68   // direction can equal either 1 or -1
69   // We will multiply the final added offset by this value to go the correct direction
70   int direction = 1;
71   struct rflags * flags = (struct rflags *)&(guest_state->rflags);  
72   if (flags->df) {
73     direction = -1;
74   }
75
76
77   if (hook == NULL) {
78    PrintDebug("Hook Not present for ins on port %x\n", io_info->port);
79     // error, we should not have exited on this port
80     return -1;
81   }
82
83   PrintDebug("INS on  port %d (0x%x)\n", io_info->port, io_info->port);
84
85   if (io_info->sz8) {
86     read_size = 1;
87   } else if (io_info->sz16) {
88     read_size = 2;
89   } else if (io_info->sz32) {
90     read_size = 4;
91   } else {
92     PrintDebug("io_info Invalid Size\n");
93     return -1;
94   }
95
96   
97   if (io_info->addr16) {
98     mask = 0xffff;
99   } else if (io_info->addr32) {
100     mask = 0xffffffff;
101   } else if (io_info->addr64) {
102     mask = 0xffffffffffffffffLL;
103   } else {
104     // This value should be set depending on the host register size...
105     mask = get_gpr_mask(info);
106
107     PrintDebug("INS io_info invalid address size, assuming 32, io_info=0x%x\n",*((uint_t*)(io_info)));
108     // PrintDebug("INS Aborted... Check implementation\n");
109     //return -1;
110   }
111
112   if (io_info->rep) {
113     //    rep_num = info->vm_regs.rcx & mask;
114     rep_num = info->vm_regs.rcx;
115   }
116
117
118   PrintDebug("INS size=%d for %d steps\n", read_size, rep_num);
119
120   while (rep_num > 0) {
121     addr_t host_addr;
122     dst_addr = get_addr_linear(info, info->vm_regs.rdi & mask, &(info->segments.es));
123     
124     if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) {
125       // either page fault or gpf...
126       PrintDebug("Could not convert Guest VA to host VA\n");
127       return -1;
128     }
129
130     if (hook->read(io_info->port, (char*)host_addr, read_size, hook->priv_data) != read_size) {
131       // not sure how we handle errors.....
132       PrintDebug("Read Failure for ins on port %x\n", io_info->port);
133       return -1;
134     }
135
136     info->vm_regs.rdi += read_size * direction;
137
138     if (io_info->rep)
139       info->vm_regs.rcx--;
140     
141     rep_num--;
142   }
143
144
145   info->rip = ctrl_area->exit_info2;
146
147   return 0;
148 }
149
150 int handle_svm_io_out(struct guest_info * info) {
151   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
152   //  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
153   struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
154
155   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
156   uint_t write_size = 0;
157
158   if (hook == NULL) {
159     PrintDebug("Hook Not present for out on port %x\n", io_info->port);
160     // error, we should not have exited on this port
161     return -1;
162   }
163
164
165   if (io_info->sz8) { 
166     write_size = 1;
167   } else if (io_info->sz16) {
168     write_size = 2;
169   } else if (io_info->sz32) {
170     write_size = 4;
171   }
172
173   PrintDebug("OUT of %d bytes on  port %d (0x%x)\n", write_size, io_info->port, io_info->port);
174
175   if (hook->write(io_info->port, &(info->vm_regs.rax), write_size, hook->priv_data) != write_size) {
176     // not sure how we handle errors.....
177     PrintDebug("Write Failure for out on port %x\n", io_info->port);
178     return -1;
179   }
180
181   info->rip = ctrl_area->exit_info2;
182
183   return 0;
184 }
185
186
187 /* We might not handle wrap around of the RSI register correctly...
188  * In that if we do wrap around the effect will manifest in the higher bits of the register
189  */
190
191 int handle_svm_io_outs(struct guest_info * info) {
192   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
193   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
194   
195   struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
196   
197   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
198   uint_t write_size = 0;
199
200   addr_t dst_addr = 0;
201   uint_t rep_num = 1;
202   ullong_t mask = 0;
203
204
205
206   // This is kind of hacky...
207   // direction can equal either 1 or -1
208   // We will multiply the final added offset by this value to go the correct direction
209   int direction = 1;
210   struct rflags * flags = (struct rflags *)&(guest_state->rflags);  
211   if (flags->df) {
212     direction = -1;
213   }
214
215
216   if (hook == NULL) {
217     PrintDebug("Hook Not present for outs on port %x\n", io_info->port);
218     // error, we should not have exited on this port
219     return -1;
220   }
221
222   PrintDebug("OUTS on  port %d (0x%x)\n", io_info->port, io_info->port);
223
224   if (io_info->sz8) { 
225     write_size = 1;
226   } else if (io_info->sz16) {
227     write_size = 2;
228   } else if (io_info->sz32) {
229     write_size = 4;
230   }
231
232
233   if (io_info->addr16) {
234     mask = 0xffff;
235   } else if (io_info->addr32) {
236     mask = 0xffffffff;
237   } else if (io_info->addr64) {
238     mask = 0xffffffffffffffffLL;
239   } else {
240     // This value should be set depending on the host register size...
241     mask = get_gpr_mask(info);
242
243     PrintDebug("OUTS io_info invalid address size, assuming 32, io_info=0x%x\n",*((uint_t*)(io_info)));
244     // PrintDebug("INS Aborted... Check implementation\n");
245     //return -1;
246     // should never happen
247     //PrintDebug("Invalid Address length\n");
248     //return -1;
249   }
250
251   if (io_info->rep) {
252     rep_num = info->vm_regs.rcx & mask;
253   }
254
255   PrintDebug("OUTS size=%d for %d steps\n", write_size, rep_num);
256
257   while (rep_num > 0) {
258     addr_t host_addr;
259     dst_addr = get_addr_linear(info, (info->vm_regs.rsi & mask), &(info->segments.ds));
260     
261     if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) {
262       // either page fault or gpf...
263     }
264
265     if (hook->write(io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) {
266       // not sure how we handle errors.....
267       PrintDebug("Write Failure for outs on port %x\n", io_info->port);
268       return -1;
269     }
270
271     info->vm_regs.rsi += write_size * direction;
272
273     if (io_info->rep)
274       info->vm_regs.rcx--;
275     
276     rep_num--;
277   }
278
279
280   info->rip = ctrl_area->exit_info2;
281
282
283   return 0;
284 }