hax: Support guest RAM sizes of 4GB or more
[qemu/kevin.git] / target / i386 / hax-windows.c
blobb1ac737ae40b702b8eb8d406aa2975599de8f37a
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, uint64_t size)
63 int ret;
64 HANDLE hDeviceVM;
65 DWORD dSize = 0;
67 if (!hax_global.vm || !hax_global.vm->fd) {
68 fprintf(stderr, "Allocate memory before vm create?\n");
69 return -EINVAL;
72 hDeviceVM = hax_global.vm->fd;
73 if (hax_global.supports_64bit_ramblock) {
74 struct hax_ramblock_info ramblock = {
75 .start_va = va,
76 .size = size,
77 .reserved = 0
80 ret = DeviceIoControl(hDeviceVM,
81 HAX_VM_IOCTL_ADD_RAMBLOCK,
82 &ramblock, sizeof(ramblock), NULL, 0, &dSize,
83 (LPOVERLAPPED) NULL);
84 } else {
85 struct hax_alloc_ram_info info = {
86 .size = (uint32_t) size,
87 .pad = 0,
88 .va = va
91 ret = DeviceIoControl(hDeviceVM,
92 HAX_VM_IOCTL_ALLOC_RAM,
93 &info, sizeof(info), NULL, 0, &dSize,
94 (LPOVERLAPPED) NULL);
97 if (!ret) {
98 fprintf(stderr, "Failed to register RAM block: va=0x%" PRIx64
99 ", size=0x%" PRIx64 ", method=%s\n", va, size,
100 hax_global.supports_64bit_ramblock ? "new" : "legacy");
101 return ret;
104 return 0;
107 int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
109 struct hax_set_ram_info info;
110 HANDLE hDeviceVM = hax_global.vm->fd;
111 DWORD dSize = 0;
112 int ret;
114 info.pa_start = start_pa;
115 info.size = size;
116 info.va = host_va;
117 info.flags = (uint8_t) flags;
119 ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM,
120 &info, sizeof(info), NULL, 0, &dSize,
121 (LPOVERLAPPED) NULL);
123 if (!ret) {
124 return -EFAULT;
125 } else {
126 return 0;
130 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
132 int ret;
133 HANDLE hDevice = hax->fd; /* handle to hax module */
134 DWORD dSize = 0;
135 DWORD err = 0;
137 if (hax_invalid_fd(hDevice)) {
138 fprintf(stderr, "Invalid fd for hax device!\n");
139 return -ENODEV;
142 ret = DeviceIoControl(hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap,
143 sizeof(*cap), &dSize, (LPOVERLAPPED) NULL);
145 if (!ret) {
146 err = GetLastError();
147 if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
148 fprintf(stderr, "hax capability is too long to hold.\n");
150 fprintf(stderr, "Failed to get Hax capability:%luu\n", err);
151 return -EFAULT;
152 } else {
153 return 0;
157 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
159 int ret;
160 HANDLE hDevice = hax->fd; /* handle to hax module */
161 DWORD dSize = 0;
162 DWORD err = 0;
164 if (hax_invalid_fd(hDevice)) {
165 fprintf(stderr, "Invalid fd for hax device!\n");
166 return -ENODEV;
169 ret = DeviceIoControl(hDevice,
170 HAX_IOCTL_VERSION,
171 NULL, 0,
172 version, sizeof(*version), &dSize,
173 (LPOVERLAPPED) NULL);
175 if (!ret) {
176 err = GetLastError();
177 if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
178 fprintf(stderr, "hax module verion is too long to hold.\n");
180 fprintf(stderr, "Failed to get Hax module version:%lu\n", err);
181 return -EFAULT;
182 } else {
183 return 0;
187 static char *hax_vm_devfs_string(int vm_id)
189 char *name;
191 if (vm_id > MAX_VM_ID) {
192 fprintf(stderr, "Too big VM id\n");
193 return NULL;
196 #define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
197 name = g_strdup(HAX_VM_DEVFS);
198 if (!name) {
199 return NULL;
202 snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
203 return name;
206 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
208 char *name;
210 if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
211 fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
212 return NULL;
215 #define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
216 name = g_strdup(HAX_VCPU_DEVFS);
217 if (!name) {
218 return NULL;
221 snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
222 vm_id, vcpu_id);
223 return name;
226 int hax_host_create_vm(struct hax_state *hax, int *vmid)
228 int ret;
229 int vm_id = 0;
230 DWORD dSize = 0;
232 if (hax_invalid_fd(hax->fd)) {
233 return -EINVAL;
236 if (hax->vm) {
237 return 0;
240 ret = DeviceIoControl(hax->fd,
241 HAX_IOCTL_CREATE_VM,
242 NULL, 0, &vm_id, sizeof(vm_id), &dSize,
243 (LPOVERLAPPED) NULL);
244 if (!ret) {
245 fprintf(stderr, "Failed to create VM. Error code: %lu\n",
246 GetLastError());
247 return -1;
249 *vmid = vm_id;
250 return 0;
253 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
255 char *vm_name = NULL;
256 hax_fd hDeviceVM;
258 vm_name = hax_vm_devfs_string(vm_id);
259 if (!vm_name) {
260 fprintf(stderr, "Failed to open VM. VM name is null\n");
261 return INVALID_HANDLE_VALUE;
264 hDeviceVM = CreateFile(vm_name,
265 GENERIC_READ | GENERIC_WRITE,
266 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
267 if (hDeviceVM == INVALID_HANDLE_VALUE) {
268 fprintf(stderr, "Open the vm device error:%s, ec:%lu\n",
269 vm_name, GetLastError());
272 g_free(vm_name);
273 return hDeviceVM;
276 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
278 int ret;
279 DWORD dSize = 0;
280 if (hax_invalid_fd(vm_fd)) {
281 return -EINVAL;
283 ret = DeviceIoControl(vm_fd,
284 HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
285 qversion, sizeof(struct hax_qemu_version),
286 NULL, 0, &dSize, (LPOVERLAPPED) NULL);
287 if (!ret) {
288 fprintf(stderr, "Failed to notify qemu API version\n");
289 return -1;
291 return 0;
294 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
296 int ret;
297 DWORD dSize = 0;
299 ret = DeviceIoControl(vm_fd,
300 HAX_VM_IOCTL_VCPU_CREATE,
301 &vcpuid, sizeof(vcpuid), NULL, 0, &dSize,
302 (LPOVERLAPPED) NULL);
303 if (!ret) {
304 fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
305 return -1;
308 return 0;
311 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
313 char *devfs_path = NULL;
314 hax_fd hDeviceVCPU;
316 devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
317 if (!devfs_path) {
318 fprintf(stderr, "Failed to get the devfs\n");
319 return INVALID_HANDLE_VALUE;
322 hDeviceVCPU = CreateFile(devfs_path,
323 GENERIC_READ | GENERIC_WRITE,
324 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
325 NULL);
327 if (hDeviceVCPU == INVALID_HANDLE_VALUE) {
328 fprintf(stderr, "Failed to open the vcpu devfs\n");
330 g_free(devfs_path);
331 return hDeviceVCPU;
334 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
336 hax_fd hDeviceVCPU = vcpu->fd;
337 int ret;
338 struct hax_tunnel_info info;
339 DWORD dSize = 0;
341 ret = DeviceIoControl(hDeviceVCPU,
342 HAX_VCPU_IOCTL_SETUP_TUNNEL,
343 NULL, 0, &info, sizeof(info), &dSize,
344 (LPOVERLAPPED) NULL);
345 if (!ret) {
346 fprintf(stderr, "Failed to setup the hax tunnel\n");
347 return -1;
350 if (!valid_hax_tunnel_size(info.size)) {
351 fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
352 ret = -EINVAL;
353 return ret;
355 vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
356 vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
357 return 0;
360 int hax_vcpu_run(struct hax_vcpu_state *vcpu)
362 int ret;
363 HANDLE hDeviceVCPU = vcpu->fd;
364 DWORD dSize = 0;
366 ret = DeviceIoControl(hDeviceVCPU,
367 HAX_VCPU_IOCTL_RUN,
368 NULL, 0, NULL, 0, &dSize, (LPOVERLAPPED) NULL);
369 if (!ret) {
370 return -EFAULT;
371 } else {
372 return 0;
376 int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
378 int ret;
379 hax_fd fd;
380 HANDLE hDeviceVCPU;
381 DWORD dSize = 0;
383 fd = hax_vcpu_get_fd(env);
384 if (hax_invalid_fd(fd)) {
385 return -1;
388 hDeviceVCPU = fd;
390 if (set) {
391 ret = DeviceIoControl(hDeviceVCPU,
392 HAX_VCPU_IOCTL_SET_FPU,
393 fl, sizeof(*fl), NULL, 0, &dSize,
394 (LPOVERLAPPED) NULL);
395 } else {
396 ret = DeviceIoControl(hDeviceVCPU,
397 HAX_VCPU_IOCTL_GET_FPU,
398 NULL, 0, fl, sizeof(*fl), &dSize,
399 (LPOVERLAPPED) NULL);
401 if (!ret) {
402 return -EFAULT;
403 } else {
404 return 0;
408 int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
410 int ret;
411 hax_fd fd;
412 HANDLE hDeviceVCPU;
413 DWORD dSize = 0;
415 fd = hax_vcpu_get_fd(env);
416 if (hax_invalid_fd(fd)) {
417 return -1;
419 hDeviceVCPU = fd;
421 if (set) {
422 ret = DeviceIoControl(hDeviceVCPU,
423 HAX_VCPU_IOCTL_SET_MSRS,
424 msrs, sizeof(*msrs),
425 msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
426 } else {
427 ret = DeviceIoControl(hDeviceVCPU,
428 HAX_VCPU_IOCTL_GET_MSRS,
429 msrs, sizeof(*msrs),
430 msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
432 if (!ret) {
433 return -EFAULT;
434 } else {
435 return 0;
439 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
441 int ret;
442 hax_fd fd;
443 HANDLE hDeviceVCPU;
444 DWORD dSize;
446 fd = hax_vcpu_get_fd(env);
447 if (hax_invalid_fd(fd)) {
448 return -1;
451 hDeviceVCPU = fd;
453 if (set) {
454 ret = DeviceIoControl(hDeviceVCPU,
455 HAX_VCPU_SET_REGS,
456 state, sizeof(*state),
457 NULL, 0, &dSize, (LPOVERLAPPED) NULL);
458 } else {
459 ret = DeviceIoControl(hDeviceVCPU,
460 HAX_VCPU_GET_REGS,
461 NULL, 0,
462 state, sizeof(*state), &dSize,
463 (LPOVERLAPPED) NULL);
465 if (!ret) {
466 return -EFAULT;
467 } else {
468 return 0;
472 int hax_inject_interrupt(CPUArchState *env, int vector)
474 int ret;
475 hax_fd fd;
476 HANDLE hDeviceVCPU;
477 DWORD dSize;
479 fd = hax_vcpu_get_fd(env);
480 if (hax_invalid_fd(fd)) {
481 return -1;
484 hDeviceVCPU = fd;
486 ret = DeviceIoControl(hDeviceVCPU,
487 HAX_VCPU_IOCTL_INTERRUPT,
488 &vector, sizeof(vector), NULL, 0, &dSize,
489 (LPOVERLAPPED) NULL);
490 if (!ret) {
491 return -EFAULT;
492 } else {
493 return 0;