hax-windows.c revision 1d1280d7d347bb9467bfe9c161cba254f9e55d1c
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 */
20static 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
50hax_fd hax_mod_open(void)
51{
52    int ret;
53    hax_fd fd;
54
55    ret = hax_open_device(&fd);
56    if (ret != 0)
57        dprint("Open HAX device failed\n");
58
59    return fd;
60}
61
62int hax_populate_ram(uint64_t va, uint32_t size)
63{
64    int ret;
65    struct hax_alloc_ram_info info;
66    HANDLE hDeviceVM;
67    DWORD dSize = 0;
68
69    if (!hax_global.vm || !hax_global.vm->fd)
70    {
71        dprint("Allocate memory before vm create?\n");
72        return -EINVAL;
73    }
74
75    info.size = size;
76    info.va = va;
77
78    hDeviceVM = hax_global.vm->fd;
79
80    ret = DeviceIoControl(hDeviceVM,
81      HAX_VM_IOCTL_ALLOC_RAM,
82      &info, sizeof(info),
83      NULL, 0,
84      &dSize,
85      (LPOVERLAPPED) NULL);
86
87    if (!ret) {
88        dprint("Failed to allocate %x memory\n", size);
89        return ret;
90    }
91
92    return 0;
93}
94
95
96int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset)
97{
98    struct hax_set_ram_info info, *pinfo = &info;
99    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
100    HANDLE hDeviceVM;
101    DWORD dSize = 0;
102    int ret = 0;
103
104    /* We look for the  RAM and ROM only */
105    if (flags >= IO_MEM_UNASSIGNED)
106        return 0;
107
108    if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK))
109    {
110        dprint(
111          "set_phys_mem %x %lx requires page aligned addr and size\n",
112          start_addr, size);
113        return -1;
114    }
115
116    info.pa_start = start_addr;
117    info.size = size;
118    info.va = (uint64_t)qemu_get_ram_ptr(phys_offset);
119    info.flags = (flags & IO_MEM_ROM) ? 1 : 0;
120
121    hDeviceVM = hax_global.vm->fd;
122
123    ret = DeviceIoControl(hDeviceVM,
124      HAX_VM_IOCTL_SET_RAM,
125      pinfo, sizeof(*pinfo),
126      NULL, 0,
127      &dSize,
128      (LPOVERLAPPED) NULL);
129
130    if (!ret)
131        return -EFAULT;
132    else
133        return 0;
134}
135
136int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
137{
138    int ret;
139    HANDLE hDevice = hax->fd;   //handle to hax module
140    DWORD dSize = 0;
141    DWORD err = 0;
142
143    if (hax_invalid_fd(hDevice)) {
144        dprint("Invalid fd for hax device!\n");
145        return -ENODEV;
146    }
147
148    ret = DeviceIoControl(hDevice,
149      HAX_IOCTL_VERSION,
150      NULL, 0,
151      version, sizeof(*version),
152      &dSize,
153      (LPOVERLAPPED) NULL);
154
155    if (!ret) {
156        err = GetLastError();
157        if (err == ERROR_INSUFFICIENT_BUFFER ||
158            err == ERROR_MORE_DATA)
159            dprint("HAX module is too large.\n");
160        dprint("Failed to get Hax module version:%d\n", err);
161        return -EFAULT;
162    } else
163        return 0;
164}
165
166static char *hax_vm_devfs_string(int vm_id)
167{
168    char *name;
169
170    if (vm_id > MAX_VM_ID)
171    {
172        dprint("Too big VM id\n");
173        return NULL;
174    }
175
176    name = qemu_strdup("\\\\.\\hax_vmxx");
177    if (!name)
178        return NULL;
179    sprintf(name, "\\\\.\\hax_vm%02d", vm_id);
180
181    return name;
182}
183
184static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
185{
186    char *name;
187
188    if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID)
189    {
190        dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
191        return NULL;
192    }
193    name = qemu_strdup("\\\\.\\hax_vmxx_vcpuxx");
194    if (!name)
195        return NULL;
196    sprintf(name, "\\\\.\\hax_vm%02d_vcpu%02d", vm_id, vcpu_id);
197
198    return name;
199}
200
201int hax_host_create_vm(struct hax_state *hax, int *vmid)
202{
203    int ret;
204    int vm_id = 0;
205    DWORD dSize = 0;
206
207    if (hax_invalid_fd(hax->fd))
208        return -EINVAL;
209
210    if (hax->vm)
211        return 0;
212
213    ret = DeviceIoControl(hax->fd,
214      HAX_IOCTL_CREATE_VM,
215      NULL, 0,
216      &vm_id, sizeof(vm_id),
217      &dSize,
218      (LPOVERLAPPED) NULL);
219    if (!ret) {
220        dprint("error code:%d", GetLastError());
221        return -1;
222    }
223    *vmid = vm_id;
224    return 0;
225}
226
227hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
228{
229    char *vm_name = NULL;
230    hax_fd hDeviceVM;
231
232    vm_name = hax_vm_devfs_string(vm_id);
233    if (!vm_name) {
234        dprint("Incorrect name\n");
235        return INVALID_HANDLE_VALUE;
236    }
237
238    hDeviceVM = CreateFile(vm_name,
239      GENERIC_READ | GENERIC_WRITE,
240      0,
241      NULL,
242      CREATE_ALWAYS,
243      FILE_ATTRIBUTE_NORMAL,
244      NULL);
245    if (hDeviceVM == INVALID_HANDLE_VALUE)
246        dprint("Open the vm devcie error:%s, ec:%d\n", vm_name, GetLastError());
247
248    qemu_free(vm_name);
249    return hDeviceVM;
250}
251
252int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
253{
254    int ret;
255    DWORD dSize = 0;
256
257    ret = DeviceIoControl(vm_fd,
258      HAX_VM_IOCTL_VCPU_CREATE,
259      &vcpuid, sizeof(vcpuid),
260      NULL, 0,
261      &dSize,
262      (LPOVERLAPPED) NULL);
263    if (!ret)
264    {
265        dprint("Failed to create vcpu %x\n", vcpuid);
266        return -1;
267    }
268
269    return 0;
270}
271
272hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
273{
274    char *devfs_path = NULL;
275    hax_fd hDeviceVCPU;
276
277    devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
278    if (!devfs_path)
279    {
280        dprint("Failed to get the devfs\n");
281        return INVALID_HANDLE_VALUE;
282    }
283
284    hDeviceVCPU = CreateFile( devfs_path,
285      GENERIC_READ | GENERIC_WRITE,
286      0,
287      NULL,
288      CREATE_ALWAYS,
289      FILE_ATTRIBUTE_NORMAL,
290      NULL);
291
292    if (hDeviceVCPU == INVALID_HANDLE_VALUE)
293        dprint("Failed to open the vcpu devfs\n");
294    qemu_free(devfs_path);
295    return hDeviceVCPU;
296}
297
298int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
299{
300    hax_fd hDeviceVCPU = vcpu->fd;
301    int ret;
302    struct hax_tunnel_info info;
303    DWORD dSize = 0;
304
305    ret = DeviceIoControl(hDeviceVCPU,
306      HAX_VCPU_IOCTL_SETUP_TUNNEL,
307      NULL, 0,
308      &info, sizeof(info),
309      &dSize,
310      (LPOVERLAPPED) NULL);
311    if (!ret)
312    {
313        dprint("Failed to setup the hax tunnel\n");
314        return -1;
315    }
316
317    if (!valid_hax_tunnel_size(info.size))
318    {
319        dprint("Invalid hax tunnel size %x\n", info.size);
320        ret = -EINVAL;
321        return ret;
322    }
323    vcpu->tunnel = (struct hax_tunnel *)(info.va);
324    vcpu->iobuf = (unsigned char *)(info.io_va);
325    return 0;
326}
327
328int hax_vcpu_run(struct hax_vcpu_state* vcpu)
329{
330    int ret;
331    HANDLE hDeviceVCPU = vcpu->fd;
332    DWORD dSize = 0;
333
334    ret = DeviceIoControl(hDeviceVCPU,
335      HAX_VCPU_IOCTL_RUN,
336      NULL, 0,
337      NULL, 0,
338      &dSize,
339      (LPOVERLAPPED) NULL);
340    if (!ret)
341        return -EFAULT;
342    else
343        return 0;
344}
345
346int hax_sync_fpu(CPUState *env, struct fx_layout *fl, int set)
347{
348    int ret;
349    hax_fd fd;
350    HANDLE hDeviceVCPU;
351    DWORD dSize = 0;
352
353    fd = hax_vcpu_get_fd(env);
354    if (hax_invalid_fd(fd))
355        return -1;
356
357    hDeviceVCPU = fd;
358
359    if (set)
360        ret = DeviceIoControl(hDeviceVCPU,
361          HAX_VCPU_IOCTL_SET_FPU,
362          fl, sizeof(*fl),
363          NULL, 0,
364          &dSize,
365          (LPOVERLAPPED) NULL);
366    else
367        ret = DeviceIoControl(hDeviceVCPU,
368          HAX_VCPU_IOCTL_GET_FPU,
369          NULL, 0,
370          fl, sizeof(*fl),
371          &dSize,
372          (LPOVERLAPPED) NULL);
373    if (!ret)
374        return -EFAULT;
375    else
376        return 0;
377}
378
379int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set)
380{
381    int ret;
382    hax_fd fd;
383    HANDLE hDeviceVCPU;
384    DWORD dSize = 0;
385
386    fd = hax_vcpu_get_fd(env);
387    if (hax_invalid_fd(fd))
388        return -1;
389    hDeviceVCPU = fd;
390
391    if (set)
392        ret = DeviceIoControl(hDeviceVCPU,
393          HAX_VCPU_IOCTL_SET_MSRS,
394          msrs, sizeof(*msrs),
395          msrs, sizeof(*msrs),
396          &dSize,
397          (LPOVERLAPPED) NULL);
398    else
399        ret = DeviceIoControl(hDeviceVCPU,
400          HAX_VCPU_IOCTL_GET_MSRS,
401          msrs, sizeof(*msrs),
402          msrs, sizeof(*msrs),
403          &dSize,
404          (LPOVERLAPPED) NULL);
405    if (!ret)
406        return -EFAULT;
407    else
408        return 0;
409}
410
411int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set)
412{
413    int ret;
414    hax_fd fd;
415    HANDLE hDeviceVCPU;
416    DWORD dSize;
417
418    fd = hax_vcpu_get_fd(env);
419    if (hax_invalid_fd(fd))
420        return -1;
421
422    hDeviceVCPU = fd;
423
424    if (set)
425        ret = DeviceIoControl(hDeviceVCPU,
426          HAX_VCPU_SET_REGS,
427          state, sizeof(*state),
428          NULL, 0,
429          &dSize,
430          (LPOVERLAPPED) NULL);
431    else
432        ret = DeviceIoControl(hDeviceVCPU,
433          HAX_VCPU_GET_REGS,
434          NULL, 0,
435          state, sizeof(*state),
436          &dSize,
437          (LPOVERLAPPED) NULL);
438    if (!ret)
439        return -EFAULT;
440    else
441        return 0;
442}
443
444int hax_inject_interrupt(CPUState *env, int vector)
445{
446    int ret;
447    hax_fd fd;
448    HANDLE hDeviceVCPU;
449    DWORD dSize;
450
451    fd = hax_vcpu_get_fd(env);
452    if (hax_invalid_fd(fd))
453        return -1;
454
455    hDeviceVCPU = fd;
456
457    ret = DeviceIoControl(hDeviceVCPU,
458      HAX_VCPU_IOCTL_INTERRUPT,
459      &vector, sizeof(vector),
460      NULL, 0,
461      &dSize,
462      (LPOVERLAPPED) NULL);
463    if (!ret)
464        return -EFAULT;
465    else
466        return 0;
467}
468