Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / target / i386 / hax-windows.c
blob15a180b646a8a02294d3265b9ed681c2d5fce92e
1 /*
2 * QEMU HAXM support
4 * Copyright (c) 2011 Intel Corporation
5 * Written by:
6 * Jiang Yunhong<yunhong.jiang@intel.com>
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.
13 #include "qemu/osdep.h"
14 #include "cpu.h"
15 #include "exec/exec-all.h"
16 #include "hax-i386.h"
19 * return 0 when success, -1 when driver not loaded,
20 * other negative value for other failure
22 static int hax_open_device(hax_fd *fd)
24 uint32_t errNum = 0;
25 HANDLE hDevice;
27 if (!fd) {
28 return -2;
31 hDevice = CreateFile("\\\\.\\HAX",
32 GENERIC_READ | GENERIC_WRITE,
33 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
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;
41 return -2;
43 *fd = hDevice;
44 return 0;
47 /* hax_fd hax_mod_open */
48 hax_fd hax_mod_open(void)
50 int ret;
51 hax_fd fd = NULL;
53 ret = hax_open_device(&fd);
54 if (ret != 0) {
55 fprintf(stderr, "Open HAX device failed\n");
58 return fd;
61 int hax_populate_ram(uint64_t va, uint32_t size)
63 int ret;
64 struct hax_alloc_ram_info info;
65 HANDLE hDeviceVM;
66 DWORD dSize = 0;
68 if (!hax_global.vm || !hax_global.vm->fd) {
69 fprintf(stderr, "Allocate memory before vm create?\n");
70 return -EINVAL;
73 info.size = size;
74 info.va = va;
76 hDeviceVM = hax_global.vm->fd;
78 ret = DeviceIoControl(hDeviceVM,
79 HAX_VM_IOCTL_ALLOC_RAM,
80 &info, sizeof(info), NULL, 0, &dSize,
81 (LPOVERLAPPED) NULL);
83 if (!ret) {
84 fprintf(stderr, "Failed to allocate %x memory\n", size);
85 return ret;
88 return 0;
91 int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
93 struct hax_set_ram_info info;
94 HANDLE hDeviceVM = hax_global.vm->fd;
95 DWORD dSize = 0;
96 int ret;
98 info.pa_start = start_pa;
99 info.size = size;
100 info.va = host_va;
101 info.flags = (uint8_t) flags;
103 ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM,
104 &info, sizeof(info), NULL, 0, &dSize,
105 (LPOVERLAPPED) NULL);
107 if (!ret) {
108 return -EFAULT;
109 } else {
110 return 0;
114 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
116 int ret;
117 HANDLE hDevice = hax->fd; /* handle to hax module */
118 DWORD dSize = 0;
119 DWORD err = 0;
121 if (hax_invalid_fd(hDevice)) {
122 fprintf(stderr, "Invalid fd for hax device!\n");
123 return -ENODEV;
126 ret = DeviceIoControl(hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap,
127 sizeof(*cap), &dSize, (LPOVERLAPPED) NULL);
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");
134 fprintf(stderr, "Failed to get Hax capability:%luu\n", err);
135 return -EFAULT;
136 } else {
137 return 0;
141 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
143 int ret;
144 HANDLE hDevice = hax->fd; /* handle to hax module */
145 DWORD dSize = 0;
146 DWORD err = 0;
148 if (hax_invalid_fd(hDevice)) {
149 fprintf(stderr, "Invalid fd for hax device!\n");
150 return -ENODEV;
153 ret = DeviceIoControl(hDevice,
154 HAX_IOCTL_VERSION,
155 NULL, 0,
156 version, sizeof(*version), &dSize,
157 (LPOVERLAPPED) NULL);
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");
164 fprintf(stderr, "Failed to get Hax module version:%lu\n", err);
165 return -EFAULT;
166 } else {
167 return 0;
171 static char *hax_vm_devfs_string(int vm_id)
173 char *name;
175 if (vm_id > MAX_VM_ID) {
176 fprintf(stderr, "Too big VM id\n");
177 return NULL;
180 #define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
181 name = g_strdup(HAX_VM_DEVFS);
182 if (!name) {
183 return NULL;
186 snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
187 return name;
190 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
192 char *name;
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;
199 #define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
200 name = g_strdup(HAX_VCPU_DEVFS);
201 if (!name) {
202 return NULL;
205 snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
206 vm_id, vcpu_id);
207 return name;
210 int hax_host_create_vm(struct hax_state *hax, int *vmid)
212 int ret;
213 int vm_id = 0;
214 DWORD dSize = 0;
216 if (hax_invalid_fd(hax->fd)) {
217 return -EINVAL;
220 if (hax->vm) {
221 return 0;
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;
233 *vmid = vm_id;
234 return 0;
237 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
239 char *vm_name = NULL;
240 hax_fd hDeviceVM;
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;
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());
256 g_free(vm_name);
257 return hDeviceVM;
260 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
262 int ret;
263 DWORD dSize = 0;
264 if (hax_invalid_fd(vm_fd)) {
265 return -EINVAL;
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;
275 return 0;
278 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
280 int ret;
281 DWORD dSize = 0;
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;
292 return 0;
295 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
297 char *devfs_path = NULL;
298 hax_fd hDeviceVCPU;
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;
306 hDeviceVCPU = CreateFile(devfs_path,
307 GENERIC_READ | GENERIC_WRITE,
308 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
309 NULL);
311 if (hDeviceVCPU == INVALID_HANDLE_VALUE) {
312 fprintf(stderr, "Failed to open the vcpu devfs\n");
314 g_free(devfs_path);
315 return hDeviceVCPU;
318 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
320 hax_fd hDeviceVCPU = vcpu->fd;
321 int ret;
322 struct hax_tunnel_info info;
323 DWORD dSize = 0;
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;
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;
339 vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
340 vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
341 return 0;
344 int hax_vcpu_run(struct hax_vcpu_state *vcpu)
346 int ret;
347 HANDLE hDeviceVCPU = vcpu->fd;
348 DWORD dSize = 0;
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;
360 int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
362 int ret;
363 hax_fd fd;
364 HANDLE hDeviceVCPU;
365 DWORD dSize = 0;
367 fd = hax_vcpu_get_fd(env);
368 if (hax_invalid_fd(fd)) {
369 return -1;
372 hDeviceVCPU = fd;
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);
385 if (!ret) {
386 return -EFAULT;
387 } else {
388 return 0;
392 int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
394 int ret;
395 hax_fd fd;
396 HANDLE hDeviceVCPU;
397 DWORD dSize = 0;
399 fd = hax_vcpu_get_fd(env);
400 if (hax_invalid_fd(fd)) {
401 return -1;
403 hDeviceVCPU = fd;
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);
416 if (!ret) {
417 return -EFAULT;
418 } else {
419 return 0;
423 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
425 int ret;
426 hax_fd fd;
427 HANDLE hDeviceVCPU;
428 DWORD dSize;
430 fd = hax_vcpu_get_fd(env);
431 if (hax_invalid_fd(fd)) {
432 return -1;
435 hDeviceVCPU = fd;
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);
449 if (!ret) {
450 return -EFAULT;
451 } else {
452 return 0;
456 int hax_inject_interrupt(CPUArchState *env, int vector)
458 int ret;
459 hax_fd fd;
460 HANDLE hDeviceVCPU;
461 DWORD dSize;
463 fd = hax_vcpu_get_fd(env);
464 if (hax_invalid_fd(fd)) {
465 return -1;
468 hDeviceVCPU = fd;
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;