• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright (c) 2011, Intel Corporation
3 **
4 ** This software is licensed under the terms of the GNU General Public
5 ** License version 2, as published by the Free Software Foundation, and
6 ** may be copied, distributed, and modified under those terms.
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 ** GNU General Public License for more details.
12 */
13 
14 #include "target-i386/hax-i386.h"
15 
16 /*
17  * return 0 upon success, -1 when the driver is not loaded,
18  * other negative value for other failures
19  */
hax_open_device(hax_fd * fd)20 static int hax_open_device(hax_fd *fd)
21 {
22     uint32_t errNum = 0;
23     HANDLE hDevice;
24 
25     if (!fd)
26         return -2;
27 
28     hDevice = CreateFile( "\\\\.\\HAX",
29       GENERIC_READ | GENERIC_WRITE,
30       0,
31       NULL,
32       CREATE_ALWAYS,
33       FILE_ATTRIBUTE_NORMAL,
34       NULL);
35 
36     if (hDevice == INVALID_HANDLE_VALUE)
37     {
38         dprint("Failed to open the HAX device!\n");
39         errNum = GetLastError();
40         if (errNum == ERROR_FILE_NOT_FOUND)
41             return -1;
42         return -2;
43     }
44     *fd = hDevice;
45     dprint("device fd:%d\n", *fd);
46     return 0;
47 }
48 
49 
hax_mod_open(void)50 hax_fd hax_mod_open(void)
51 {
52     int ret;
53     hax_fd fd = INVALID_HANDLE_VALUE;
54 
55     ret = hax_open_device(&fd);
56     if (ret != 0) {
57         dprint("Open HAX device failed\n");
58         return INVALID_HANDLE_VALUE;
59     }
60 
61     return fd;
62 }
63 
hax_populate_ram(uint64_t va,uint32_t size)64 int hax_populate_ram(uint64_t va, uint32_t size)
65 {
66     int ret;
67     struct hax_alloc_ram_info info;
68     HANDLE hDeviceVM;
69     DWORD dSize = 0;
70 
71     if (!hax_global.vm || !hax_global.vm->fd)
72     {
73         dprint("Allocate memory before vm create?\n");
74         return -EINVAL;
75     }
76 
77     info.size = size;
78     info.va = va;
79 
80     hDeviceVM = hax_global.vm->fd;
81 
82     ret = DeviceIoControl(hDeviceVM,
83       HAX_VM_IOCTL_ALLOC_RAM,
84       &info, sizeof(info),
85       NULL, 0,
86       &dSize,
87       (LPOVERLAPPED) NULL);
88 
89     if (!ret) {
90         dprint("HAX: Failed to allocate %x memory (address %llx)\n",
91                size, (unsigned long long)va);
92         return -1;
93     }
94 
95     return 0;
96 }
97 
98 
hax_set_phys_mem(hwaddr start_addr,ram_addr_t size,ram_addr_t phys_offset)99 int hax_set_phys_mem(hwaddr start_addr, ram_addr_t size, ram_addr_t phys_offset)
100 {
101     struct hax_set_ram_info info, *pinfo = &info;
102     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
103     HANDLE hDeviceVM;
104     DWORD dSize = 0;
105     int ret = 0;
106 
107     /* We look for the  RAM and ROM only */
108     if (flags >= IO_MEM_UNASSIGNED)
109         return 0;
110 
111     if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK))
112     {
113         dprint(
114           "set_phys_mem %x %lx requires page aligned addr and size\n",
115           start_addr, size);
116         return -1;
117     }
118 
119     info.pa_start = start_addr;
120     info.size = size;
121     info.va = (uint64_t)(uintptr_t)qemu_get_ram_ptr(phys_offset);
122     info.flags = (flags & IO_MEM_ROM) ? 1 : 0;
123 
124     hDeviceVM = hax_global.vm->fd;
125 
126     ret = DeviceIoControl(hDeviceVM,
127       HAX_VM_IOCTL_SET_RAM,
128       pinfo, sizeof(*pinfo),
129       NULL, 0,
130       &dSize,
131       (LPOVERLAPPED) NULL);
132 
133     if (!ret)
134         return -EFAULT;
135     else
136         return 0;
137 }
138 
hax_capability(struct hax_state * hax,struct hax_capabilityinfo * cap)139 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
140 {
141     int ret;
142     HANDLE hDevice = hax->fd;   //handle to hax module
143     DWORD dSize = 0;
144     DWORD err = 0;
145 
146     if (hax_invalid_fd(hDevice)) {
147         dprint("Invalid fd for hax device!\n");
148         return -ENODEV;
149     }
150 
151     ret = DeviceIoControl(hDevice,
152       HAX_IOCTL_CAPABILITY,
153       NULL, 0,
154       cap, sizeof(*cap),
155       &dSize,
156       (LPOVERLAPPED) NULL);
157 
158     if (!ret) {
159         err = GetLastError();
160         if (err == ERROR_INSUFFICIENT_BUFFER ||
161             err == ERROR_MORE_DATA)
162             dprint("hax capability is too long to hold.\n");
163         dprint("Failed to get Hax capability:%d\n", err);
164         return -EFAULT;
165     } else
166         return 0;
167 }
168 
hax_mod_version(struct hax_state * hax,struct hax_module_version * version)169 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
170 {
171     int ret;
172     HANDLE hDevice = hax->fd;   //handle to hax module
173     DWORD dSize = 0;
174     DWORD err = 0;
175 
176     if (hax_invalid_fd(hDevice)) {
177         dprint("Invalid fd for hax device!\n");
178         return -ENODEV;
179     }
180 
181     ret = DeviceIoControl(hDevice,
182       HAX_IOCTL_VERSION,
183       NULL, 0,
184       version, sizeof(*version),
185       &dSize,
186       (LPOVERLAPPED) NULL);
187 
188     if (!ret) {
189         err = GetLastError();
190         if (err == ERROR_INSUFFICIENT_BUFFER ||
191             err == ERROR_MORE_DATA)
192             dprint("HAX module is too large.\n");
193         dprint("Failed to get Hax module version:%d\n", err);
194         return -EFAULT;
195     } else
196         return 0;
197 }
198 
hax_vm_devfs_string(int vm_id)199 static char *hax_vm_devfs_string(int vm_id)
200 {
201     char *name;
202 
203     if (vm_id > MAX_VM_ID)
204     {
205         dprint("Too big VM id\n");
206         return NULL;
207     }
208 
209     name = g_strdup("\\\\.\\hax_vmxx");
210     if (!name)
211         return NULL;
212     sprintf(name, "\\\\.\\hax_vm%02d", vm_id);
213 
214     return name;
215 }
216 
hax_vcpu_devfs_string(int vm_id,int vcpu_id)217 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
218 {
219     char *name;
220 
221     if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID)
222     {
223         dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
224         return NULL;
225     }
226     name = g_strdup("\\\\.\\hax_vmxx_vcpuxx");
227     if (!name)
228         return NULL;
229     sprintf(name, "\\\\.\\hax_vm%02d_vcpu%02d", vm_id, vcpu_id);
230 
231     return name;
232 }
233 
hax_host_create_vm(struct hax_state * hax,int * vmid)234 int hax_host_create_vm(struct hax_state *hax, int *vmid)
235 {
236     int ret;
237     int vm_id = 0;
238     DWORD dSize = 0;
239 
240     if (hax_invalid_fd(hax->fd))
241         return -EINVAL;
242 
243     if (hax->vm)
244         return 0;
245 
246     ret = DeviceIoControl(hax->fd,
247       HAX_IOCTL_CREATE_VM,
248       NULL, 0,
249       &vm_id, sizeof(vm_id),
250       &dSize,
251       (LPOVERLAPPED) NULL);
252     if (!ret) {
253         dprint("error code:%d", GetLastError());
254         return -1;
255     }
256     *vmid = vm_id;
257     return 0;
258 }
259 
hax_host_open_vm(struct hax_state * hax,int vm_id)260 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
261 {
262     char *vm_name = NULL;
263     hax_fd hDeviceVM;
264 
265     vm_name = hax_vm_devfs_string(vm_id);
266     if (!vm_name) {
267         dprint("Incorrect name\n");
268         return INVALID_HANDLE_VALUE;
269     }
270 
271     hDeviceVM = CreateFile(vm_name,
272       GENERIC_READ | GENERIC_WRITE,
273       0,
274       NULL,
275       CREATE_ALWAYS,
276       FILE_ATTRIBUTE_NORMAL,
277       NULL);
278     if (hDeviceVM == INVALID_HANDLE_VALUE)
279         dprint("Open the vm devcie error:%s, ec:%d\n", vm_name, GetLastError());
280 
281     g_free(vm_name);
282     return hDeviceVM;
283 }
284 
hax_notify_qemu_version(hax_fd vm_fd,struct hax_qemu_version * qversion)285 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
286 {
287     int ret;
288     DWORD dSize = 0;
289 
290     if (hax_invalid_fd(vm_fd))
291         return -EINVAL;
292 
293     ret = DeviceIoControl(vm_fd,
294       HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
295       qversion, sizeof(struct hax_qemu_version),
296       NULL, 0,
297       &dSize,
298       (LPOVERLAPPED) NULL);
299     if (!ret)
300     {
301         dprint("Failed to notify qemu API version\n");
302         return -1;
303     }
304 
305     return 0;
306 }
307 
hax_host_create_vcpu(hax_fd vm_fd,int vcpuid)308 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
309 {
310     int ret;
311     DWORD dSize = 0;
312 
313     ret = DeviceIoControl(vm_fd,
314       HAX_VM_IOCTL_VCPU_CREATE,
315       &vcpuid, sizeof(vcpuid),
316       NULL, 0,
317       &dSize,
318       (LPOVERLAPPED) NULL);
319     if (!ret)
320     {
321         dprint("Failed to create vcpu %x\n", vcpuid);
322         return -1;
323     }
324 
325     return 0;
326 }
327 
hax_host_open_vcpu(int vmid,int vcpuid)328 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
329 {
330     char *devfs_path = NULL;
331     hax_fd hDeviceVCPU;
332 
333     devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
334     if (!devfs_path)
335     {
336         dprint("Failed to get the devfs\n");
337         return INVALID_HANDLE_VALUE;
338     }
339 
340     hDeviceVCPU = CreateFile( devfs_path,
341       GENERIC_READ | GENERIC_WRITE,
342       0,
343       NULL,
344       CREATE_ALWAYS,
345       FILE_ATTRIBUTE_NORMAL,
346       NULL);
347 
348     if (hDeviceVCPU == INVALID_HANDLE_VALUE)
349         dprint("Failed to open the vcpu devfs\n");
350     g_free(devfs_path);
351     return hDeviceVCPU;
352 }
353 
hax_host_setup_vcpu_channel(struct hax_vcpu_state * vcpu)354 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
355 {
356     hax_fd hDeviceVCPU = vcpu->fd;
357     int ret;
358     struct hax_tunnel_info info;
359     DWORD dSize = 0;
360 
361     ret = DeviceIoControl(hDeviceVCPU,
362       HAX_VCPU_IOCTL_SETUP_TUNNEL,
363       NULL, 0,
364       &info, sizeof(info),
365       &dSize,
366       (LPOVERLAPPED) NULL);
367     if (!ret)
368     {
369         dprint("Failed to setup the hax tunnel\n");
370         return -1;
371     }
372 
373     if (!valid_hax_tunnel_size(info.size))
374     {
375         dprint("Invalid hax tunnel size %x\n", info.size);
376         ret = -EINVAL;
377         return ret;
378     }
379     vcpu->tunnel = (struct hax_tunnel *)(uintptr_t)(info.va);
380     vcpu->iobuf = (unsigned char *)(uintptr_t)(info.io_va);
381     return 0;
382 }
383 
hax_vcpu_run(struct hax_vcpu_state * vcpu)384 int hax_vcpu_run(struct hax_vcpu_state* vcpu)
385 {
386     int ret;
387     HANDLE hDeviceVCPU = vcpu->fd;
388     DWORD dSize = 0;
389 
390     ret = DeviceIoControl(hDeviceVCPU,
391       HAX_VCPU_IOCTL_RUN,
392       NULL, 0,
393       NULL, 0,
394       &dSize,
395       (LPOVERLAPPED) NULL);
396     if (!ret)
397         return -EFAULT;
398     else
399         return 0;
400 }
401 
hax_sync_fpu(CPUState * cpu,struct fx_layout * fl,int set)402 int hax_sync_fpu(CPUState *cpu, struct fx_layout *fl, int set)
403 {
404     int ret;
405     hax_fd fd;
406     HANDLE hDeviceVCPU;
407     DWORD dSize = 0;
408 
409     fd = hax_vcpu_get_fd(cpu);
410     if (hax_invalid_fd(fd))
411         return -1;
412 
413     hDeviceVCPU = fd;
414 
415     if (set)
416         ret = DeviceIoControl(hDeviceVCPU,
417           HAX_VCPU_IOCTL_SET_FPU,
418           fl, sizeof(*fl),
419           NULL, 0,
420           &dSize,
421           (LPOVERLAPPED) NULL);
422     else
423         ret = DeviceIoControl(hDeviceVCPU,
424           HAX_VCPU_IOCTL_GET_FPU,
425           NULL, 0,
426           fl, sizeof(*fl),
427           &dSize,
428           (LPOVERLAPPED) NULL);
429     if (!ret)
430         return -EFAULT;
431     else
432         return 0;
433 }
434 
hax_sync_msr(CPUState * cpu,struct hax_msr_data * msrs,int set)435 int hax_sync_msr(CPUState *cpu, struct hax_msr_data *msrs, int set)
436 {
437     int ret;
438     hax_fd fd;
439     HANDLE hDeviceVCPU;
440     DWORD dSize = 0;
441 
442     fd = hax_vcpu_get_fd(cpu);
443     if (hax_invalid_fd(fd))
444         return -1;
445     hDeviceVCPU = fd;
446 
447     if (set)
448         ret = DeviceIoControl(hDeviceVCPU,
449           HAX_VCPU_IOCTL_SET_MSRS,
450           msrs, sizeof(*msrs),
451           msrs, sizeof(*msrs),
452           &dSize,
453           (LPOVERLAPPED) NULL);
454     else
455         ret = DeviceIoControl(hDeviceVCPU,
456           HAX_VCPU_IOCTL_GET_MSRS,
457           msrs, sizeof(*msrs),
458           msrs, sizeof(*msrs),
459           &dSize,
460           (LPOVERLAPPED) NULL);
461     if (!ret)
462         return -EFAULT;
463     else
464         return 0;
465 }
466 
hax_sync_vcpu_state(CPUState * cpu,struct vcpu_state_t * state,int set)467 int hax_sync_vcpu_state(CPUState *cpu, struct vcpu_state_t *state, int set)
468 {
469     int ret;
470     hax_fd fd;
471     HANDLE hDeviceVCPU;
472     DWORD dSize;
473 
474     fd = hax_vcpu_get_fd(cpu);
475     if (hax_invalid_fd(fd))
476         return -1;
477 
478     hDeviceVCPU = fd;
479 
480     if (set)
481         ret = DeviceIoControl(hDeviceVCPU,
482           HAX_VCPU_SET_REGS,
483           state, sizeof(*state),
484           NULL, 0,
485           &dSize,
486           (LPOVERLAPPED) NULL);
487     else
488         ret = DeviceIoControl(hDeviceVCPU,
489           HAX_VCPU_GET_REGS,
490           NULL, 0,
491           state, sizeof(*state),
492           &dSize,
493           (LPOVERLAPPED) NULL);
494     if (!ret)
495         return -EFAULT;
496     else
497         return 0;
498 }
499 
hax_inject_interrupt(CPUState * cpu,int vector)500 int hax_inject_interrupt(CPUState *cpu, int vector)
501 {
502     int ret;
503     hax_fd fd;
504     HANDLE hDeviceVCPU;
505     DWORD dSize;
506 
507     fd = hax_vcpu_get_fd(cpu);
508     if (hax_invalid_fd(fd))
509         return -1;
510 
511     hDeviceVCPU = fd;
512 
513     ret = DeviceIoControl(hDeviceVCPU,
514       HAX_VCPU_IOCTL_INTERRUPT,
515       &vector, sizeof(vector),
516       NULL, 0,
517       &dSize,
518       (LPOVERLAPPED) NULL);
519     if (!ret)
520         return -EFAULT;
521     else
522         return 0;
523 }
524