]> Git Repo - qemu.git/blob - target/i386/hax-windows.c
qapi: Separate type QNull from QObject
[qemu.git] / target / i386 / hax-windows.c
1 /*
2  * QEMU HAXM support
3  *
4  * Copyright (c) 2011 Intel Corporation
5  *  Written by:
6  *  Jiang Yunhong<[email protected]>
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9  * See the COPYING file in the top-level directory.
10  *
11  */
12
13 #include "qemu/osdep.h"
14 #include "cpu.h"
15 #include "exec/exec-all.h"
16 #include "hax-i386.h"
17
18 /*
19  * return 0 when success, -1 when driver not loaded,
20  * other negative value for other failure
21  */
22 static int hax_open_device(hax_fd *fd)
23 {
24     uint32_t errNum = 0;
25     HANDLE hDevice;
26
27     if (!fd) {
28         return -2;
29     }
30
31     hDevice = CreateFile("\\\\.\\HAX",
32                          GENERIC_READ | GENERIC_WRITE,
33                          0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
34
35     if (hDevice == INVALID_HANDLE_VALUE) {
36         fprintf(stderr, "Failed to open the HAX device!\n");
37         errNum = GetLastError();
38         if (errNum == ERROR_FILE_NOT_FOUND) {
39             return -1;
40         }
41         return -2;
42     }
43     *fd = hDevice;
44     return 0;
45 }
46
47 /* hax_fd hax_mod_open */
48  hax_fd hax_mod_open(void)
49 {
50     int ret;
51     hax_fd fd = NULL;
52
53     ret = hax_open_device(&fd);
54     if (ret != 0) {
55         fprintf(stderr, "Open HAX device failed\n");
56     }
57
58     return fd;
59 }
60
61 int hax_populate_ram(uint64_t va, uint32_t size)
62 {
63     int ret;
64     struct hax_alloc_ram_info info;
65     HANDLE hDeviceVM;
66     DWORD dSize = 0;
67
68     if (!hax_global.vm || !hax_global.vm->fd) {
69         fprintf(stderr, "Allocate memory before vm create?\n");
70         return -EINVAL;
71     }
72
73     info.size = size;
74     info.va = va;
75
76     hDeviceVM = hax_global.vm->fd;
77
78     ret = DeviceIoControl(hDeviceVM,
79                           HAX_VM_IOCTL_ALLOC_RAM,
80                           &info, sizeof(info), NULL, 0, &dSize,
81                           (LPOVERLAPPED) NULL);
82
83     if (!ret) {
84         fprintf(stderr, "Failed to allocate %x memory\n", size);
85         return ret;
86     }
87
88     return 0;
89 }
90
91 int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
92 {
93     struct hax_set_ram_info info;
94     HANDLE hDeviceVM = hax_global.vm->fd;
95     DWORD dSize = 0;
96     int ret;
97
98     info.pa_start = start_pa;
99     info.size = size;
100     info.va = host_va;
101     info.flags = (uint8_t) flags;
102
103     ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM,
104                           &info, sizeof(info), NULL, 0, &dSize,
105                           (LPOVERLAPPED) NULL);
106
107     if (!ret) {
108         return -EFAULT;
109     } else {
110         return 0;
111     }
112 }
113
114 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
115 {
116     int ret;
117     HANDLE hDevice = hax->fd;        /* handle to hax module */
118     DWORD dSize = 0;
119     DWORD err = 0;
120
121     if (hax_invalid_fd(hDevice)) {
122         fprintf(stderr, "Invalid fd for hax device!\n");
123         return -ENODEV;
124     }
125
126     ret = DeviceIoControl(hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap,
127                           sizeof(*cap), &dSize, (LPOVERLAPPED) NULL);
128
129     if (!ret) {
130         err = GetLastError();
131         if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
132             fprintf(stderr, "hax capability is too long to hold.\n");
133         }
134         fprintf(stderr, "Failed to get Hax capability:%luu\n", err);
135         return -EFAULT;
136     } else {
137         return 0;
138     }
139 }
140
141 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
142 {
143     int ret;
144     HANDLE hDevice = hax->fd; /* handle to hax module */
145     DWORD dSize = 0;
146     DWORD err = 0;
147
148     if (hax_invalid_fd(hDevice)) {
149         fprintf(stderr, "Invalid fd for hax device!\n");
150         return -ENODEV;
151     }
152
153     ret = DeviceIoControl(hDevice,
154                           HAX_IOCTL_VERSION,
155                           NULL, 0,
156                           version, sizeof(*version), &dSize,
157                           (LPOVERLAPPED) NULL);
158
159     if (!ret) {
160         err = GetLastError();
161         if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
162             fprintf(stderr, "hax module verion is too long to hold.\n");
163         }
164         fprintf(stderr, "Failed to get Hax module version:%lu\n", err);
165         return -EFAULT;
166     } else {
167         return 0;
168     }
169 }
170
171 static char *hax_vm_devfs_string(int vm_id)
172 {
173     char *name;
174
175     if (vm_id > MAX_VM_ID) {
176         fprintf(stderr, "Too big VM id\n");
177         return NULL;
178     }
179
180 #define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
181     name = g_strdup(HAX_VM_DEVFS);
182     if (!name) {
183         return NULL;
184     }
185
186     snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
187     return name;
188 }
189
190 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
191 {
192     char *name;
193
194     if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
195         fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
196         return NULL;
197     }
198
199 #define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
200     name = g_strdup(HAX_VCPU_DEVFS);
201     if (!name) {
202         return NULL;
203     }
204
205     snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
206              vm_id, vcpu_id);
207     return name;
208 }
209
210 int hax_host_create_vm(struct hax_state *hax, int *vmid)
211 {
212     int ret;
213     int vm_id = 0;
214     DWORD dSize = 0;
215
216     if (hax_invalid_fd(hax->fd)) {
217         return -EINVAL;
218     }
219
220     if (hax->vm) {
221         return 0;
222     }
223
224     ret = DeviceIoControl(hax->fd,
225                           HAX_IOCTL_CREATE_VM,
226                           NULL, 0, &vm_id, sizeof(vm_id), &dSize,
227                           (LPOVERLAPPED) NULL);
228     if (!ret) {
229         fprintf(stderr, "Failed to create VM. Error code: %lu\n",
230                 GetLastError());
231         return -1;
232     }
233     *vmid = vm_id;
234     return 0;
235 }
236
237 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
238 {
239     char *vm_name = NULL;
240     hax_fd hDeviceVM;
241
242     vm_name = hax_vm_devfs_string(vm_id);
243     if (!vm_name) {
244         fprintf(stderr, "Failed to open VM. VM name is null\n");
245         return INVALID_HANDLE_VALUE;
246     }
247
248     hDeviceVM = CreateFile(vm_name,
249                            GENERIC_READ | GENERIC_WRITE,
250                            0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
251     if (hDeviceVM == INVALID_HANDLE_VALUE) {
252         fprintf(stderr, "Open the vm device error:%s, ec:%lu\n",
253                 vm_name, GetLastError());
254     }
255
256     g_free(vm_name);
257     return hDeviceVM;
258 }
259
260 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
261 {
262     int ret;
263     DWORD dSize = 0;
264     if (hax_invalid_fd(vm_fd)) {
265         return -EINVAL;
266     }
267     ret = DeviceIoControl(vm_fd,
268                           HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
269                           qversion, sizeof(struct hax_qemu_version),
270                           NULL, 0, &dSize, (LPOVERLAPPED) NULL);
271     if (!ret) {
272         fprintf(stderr, "Failed to notify qemu API version\n");
273         return -1;
274     }
275     return 0;
276 }
277
278 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
279 {
280     int ret;
281     DWORD dSize = 0;
282
283     ret = DeviceIoControl(vm_fd,
284                           HAX_VM_IOCTL_VCPU_CREATE,
285                           &vcpuid, sizeof(vcpuid), NULL, 0, &dSize,
286                           (LPOVERLAPPED) NULL);
287     if (!ret) {
288         fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
289         return -1;
290     }
291
292     return 0;
293 }
294
295 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
296 {
297     char *devfs_path = NULL;
298     hax_fd hDeviceVCPU;
299
300     devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
301     if (!devfs_path) {
302         fprintf(stderr, "Failed to get the devfs\n");
303         return INVALID_HANDLE_VALUE;
304     }
305
306     hDeviceVCPU = CreateFile(devfs_path,
307                              GENERIC_READ | GENERIC_WRITE,
308                              0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
309                              NULL);
310
311     if (hDeviceVCPU == INVALID_HANDLE_VALUE) {
312         fprintf(stderr, "Failed to open the vcpu devfs\n");
313     }
314     g_free(devfs_path);
315     return hDeviceVCPU;
316 }
317
318 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
319 {
320     hax_fd hDeviceVCPU = vcpu->fd;
321     int ret;
322     struct hax_tunnel_info info;
323     DWORD dSize = 0;
324
325     ret = DeviceIoControl(hDeviceVCPU,
326                           HAX_VCPU_IOCTL_SETUP_TUNNEL,
327                           NULL, 0, &info, sizeof(info), &dSize,
328                           (LPOVERLAPPED) NULL);
329     if (!ret) {
330         fprintf(stderr, "Failed to setup the hax tunnel\n");
331         return -1;
332     }
333
334     if (!valid_hax_tunnel_size(info.size)) {
335         fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
336         ret = -EINVAL;
337         return ret;
338     }
339     vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
340     vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
341     return 0;
342 }
343
344 int hax_vcpu_run(struct hax_vcpu_state *vcpu)
345 {
346     int ret;
347     HANDLE hDeviceVCPU = vcpu->fd;
348     DWORD dSize = 0;
349
350     ret = DeviceIoControl(hDeviceVCPU,
351                           HAX_VCPU_IOCTL_RUN,
352                           NULL, 0, NULL, 0, &dSize, (LPOVERLAPPED) NULL);
353     if (!ret) {
354         return -EFAULT;
355     } else {
356         return 0;
357     }
358 }
359
360 int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
361 {
362     int ret;
363     hax_fd fd;
364     HANDLE hDeviceVCPU;
365     DWORD dSize = 0;
366
367     fd = hax_vcpu_get_fd(env);
368     if (hax_invalid_fd(fd)) {
369         return -1;
370     }
371
372     hDeviceVCPU = fd;
373
374     if (set) {
375         ret = DeviceIoControl(hDeviceVCPU,
376                               HAX_VCPU_IOCTL_SET_FPU,
377                               fl, sizeof(*fl), NULL, 0, &dSize,
378                               (LPOVERLAPPED) NULL);
379     } else {
380         ret = DeviceIoControl(hDeviceVCPU,
381                               HAX_VCPU_IOCTL_GET_FPU,
382                               NULL, 0, fl, sizeof(*fl), &dSize,
383                               (LPOVERLAPPED) NULL);
384     }
385     if (!ret) {
386         return -EFAULT;
387     } else {
388         return 0;
389     }
390 }
391
392 int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
393 {
394     int ret;
395     hax_fd fd;
396     HANDLE hDeviceVCPU;
397     DWORD dSize = 0;
398
399     fd = hax_vcpu_get_fd(env);
400     if (hax_invalid_fd(fd)) {
401         return -1;
402     }
403     hDeviceVCPU = fd;
404
405     if (set) {
406         ret = DeviceIoControl(hDeviceVCPU,
407                               HAX_VCPU_IOCTL_SET_MSRS,
408                               msrs, sizeof(*msrs),
409                               msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
410     } else {
411         ret = DeviceIoControl(hDeviceVCPU,
412                               HAX_VCPU_IOCTL_GET_MSRS,
413                               msrs, sizeof(*msrs),
414                               msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
415     }
416     if (!ret) {
417         return -EFAULT;
418     } else {
419         return 0;
420     }
421 }
422
423 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
424 {
425     int ret;
426     hax_fd fd;
427     HANDLE hDeviceVCPU;
428     DWORD dSize;
429
430     fd = hax_vcpu_get_fd(env);
431     if (hax_invalid_fd(fd)) {
432         return -1;
433     }
434
435     hDeviceVCPU = fd;
436
437     if (set) {
438         ret = DeviceIoControl(hDeviceVCPU,
439                               HAX_VCPU_SET_REGS,
440                               state, sizeof(*state),
441                               NULL, 0, &dSize, (LPOVERLAPPED) NULL);
442     } else {
443         ret = DeviceIoControl(hDeviceVCPU,
444                               HAX_VCPU_GET_REGS,
445                               NULL, 0,
446                               state, sizeof(*state), &dSize,
447                               (LPOVERLAPPED) NULL);
448     }
449     if (!ret) {
450         return -EFAULT;
451     } else {
452         return 0;
453     }
454 }
455
456 int hax_inject_interrupt(CPUArchState *env, int vector)
457 {
458     int ret;
459     hax_fd fd;
460     HANDLE hDeviceVCPU;
461     DWORD dSize;
462
463     fd = hax_vcpu_get_fd(env);
464     if (hax_invalid_fd(fd)) {
465         return -1;
466     }
467
468     hDeviceVCPU = fd;
469
470     ret = DeviceIoControl(hDeviceVCPU,
471                           HAX_VCPU_IOCTL_INTERRUPT,
472                           &vector, sizeof(vector), NULL, 0, &dSize,
473                           (LPOVERLAPPED) NULL);
474     if (!ret) {
475         return -EFAULT;
476     } else {
477         return 0;
478     }
479 }
This page took 0.048766 seconds and 4 git commands to generate.