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.


ce126693d70876059e8466041f569e130f011d6d
[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   PrintDebug("IN on  port %d (0x%x)\n", io_info->port, io_info->port);
24
25   if (io_info->sz8) { 
26     read_size = 1;
27   } else if (io_info->sz16) {
28     read_size = 2;
29   } else if (io_info->sz32) {
30     read_size = 4;
31   }
32
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
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   PrintDebug("OUT on  port %d (0x%x)\n", io_info->port, io_info->port);
165
166   if (io_info->sz8) { 
167     write_size = 1;
168   } else if (io_info->sz16) {
169     write_size = 2;
170   } else if (io_info->sz32) {
171     write_size = 4;
172   }
173
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     // should never happen
241     PrintDebug("Invalid Address length\n");
242     return -1;
243   }
244
245   if (io_info->rep) {
246     rep_num = info->vm_regs.rcx & mask;
247   }
248
249
250   while (rep_num > 0) {
251     addr_t host_addr;
252     dst_addr = get_addr_linear(info, (info->vm_regs.rsi & mask), &(info->segments.ds));
253     
254     if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) {
255       // either page fault or gpf...
256     }
257
258     if (hook->write(io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) {
259       // not sure how we handle errors.....
260       PrintDebug("Write Failure for outs on port %x\n", io_info->port);
261       return -1;
262     }
263
264     info->vm_regs.rsi += write_size * direction;
265
266     if (io_info->rep)
267       info->vm_regs.rcx--;
268     
269     rep_num--;
270   }
271
272
273   info->rip = ctrl_area->exit_info2;
274
275
276   return 0;
277 }