4 * Copyright (c) 2011 Intel Corporation
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"
15 #include "hax-accel-ops.h"
18 * return 0 when success, -1 when driver not loaded,
19 * other negative value for other failure
21 static int hax_open_device(hax_fd
*fd
)
30 hDevice
= CreateFile("\\\\.\\HAX",
31 GENERIC_READ
| GENERIC_WRITE
,
32 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
34 if (hDevice
== INVALID_HANDLE_VALUE
) {
35 fprintf(stderr
, "Failed to open the HAX device!\n");
36 errNum
= GetLastError();
37 if (errNum
== ERROR_FILE_NOT_FOUND
) {
46 /* hax_fd hax_mod_open */
47 hax_fd
hax_mod_open(void)
52 ret
= hax_open_device(&fd
);
54 fprintf(stderr
, "Open HAX device failed\n");
60 int hax_populate_ram(uint64_t va
, uint64_t size
)
66 if (!hax_global
.vm
|| !hax_global
.vm
->fd
) {
67 fprintf(stderr
, "Allocate memory before vm create?\n");
71 hDeviceVM
= hax_global
.vm
->fd
;
72 if (hax_global
.supports_64bit_ramblock
) {
73 struct hax_ramblock_info ramblock
= {
79 ret
= DeviceIoControl(hDeviceVM
,
80 HAX_VM_IOCTL_ADD_RAMBLOCK
,
81 &ramblock
, sizeof(ramblock
), NULL
, 0, &dSize
,
84 struct hax_alloc_ram_info info
= {
85 .size
= (uint32_t) size
,
90 ret
= DeviceIoControl(hDeviceVM
,
91 HAX_VM_IOCTL_ALLOC_RAM
,
92 &info
, sizeof(info
), NULL
, 0, &dSize
,
97 fprintf(stderr
, "Failed to register RAM block: va=0x%" PRIx64
98 ", size=0x%" PRIx64
", method=%s\n", va
, size
,
99 hax_global
.supports_64bit_ramblock
? "new" : "legacy");
106 int hax_set_ram(uint64_t start_pa
, uint32_t size
, uint64_t host_va
, int flags
)
108 struct hax_set_ram_info info
;
109 HANDLE hDeviceVM
= hax_global
.vm
->fd
;
113 info
.pa_start
= start_pa
;
116 info
.flags
= (uint8_t) flags
;
118 ret
= DeviceIoControl(hDeviceVM
, HAX_VM_IOCTL_SET_RAM
,
119 &info
, sizeof(info
), NULL
, 0, &dSize
,
120 (LPOVERLAPPED
) NULL
);
129 int hax_capability(struct hax_state
*hax
, struct hax_capabilityinfo
*cap
)
132 HANDLE hDevice
= hax
->fd
; /* handle to hax module */
136 if (hax_invalid_fd(hDevice
)) {
137 fprintf(stderr
, "Invalid fd for hax device!\n");
141 ret
= DeviceIoControl(hDevice
, HAX_IOCTL_CAPABILITY
, NULL
, 0, cap
,
142 sizeof(*cap
), &dSize
, (LPOVERLAPPED
) NULL
);
145 err
= GetLastError();
146 if (err
== ERROR_INSUFFICIENT_BUFFER
|| err
== ERROR_MORE_DATA
) {
147 fprintf(stderr
, "hax capability is too long to hold.\n");
149 fprintf(stderr
, "Failed to get Hax capability:%luu\n", err
);
156 int hax_mod_version(struct hax_state
*hax
, struct hax_module_version
*version
)
159 HANDLE hDevice
= hax
->fd
; /* handle to hax module */
163 if (hax_invalid_fd(hDevice
)) {
164 fprintf(stderr
, "Invalid fd for hax device!\n");
168 ret
= DeviceIoControl(hDevice
,
171 version
, sizeof(*version
), &dSize
,
172 (LPOVERLAPPED
) NULL
);
175 err
= GetLastError();
176 if (err
== ERROR_INSUFFICIENT_BUFFER
|| err
== ERROR_MORE_DATA
) {
177 fprintf(stderr
, "hax module verion is too long to hold.\n");
179 fprintf(stderr
, "Failed to get Hax module version:%lu\n", err
);
186 static char *hax_vm_devfs_string(int vm_id
)
188 return g_strdup_printf("\\\\.\\hax_vm%02d", vm_id
);
191 static char *hax_vcpu_devfs_string(int vm_id
, int vcpu_id
)
193 return g_strdup_printf("\\\\.\\hax_vm%02d_vcpu%02d", vm_id
, vcpu_id
);
196 int hax_host_create_vm(struct hax_state
*hax
, int *vmid
)
202 if (hax_invalid_fd(hax
->fd
)) {
210 ret
= DeviceIoControl(hax
->fd
,
212 NULL
, 0, &vm_id
, sizeof(vm_id
), &dSize
,
213 (LPOVERLAPPED
) NULL
);
215 fprintf(stderr
, "Failed to create VM. Error code: %lu\n",
223 hax_fd
hax_host_open_vm(struct hax_state
*hax
, int vm_id
)
225 char *vm_name
= NULL
;
228 vm_name
= hax_vm_devfs_string(vm_id
);
230 fprintf(stderr
, "Failed to open VM. VM name is null\n");
231 return INVALID_HANDLE_VALUE
;
234 hDeviceVM
= CreateFile(vm_name
,
235 GENERIC_READ
| GENERIC_WRITE
,
236 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
237 if (hDeviceVM
== INVALID_HANDLE_VALUE
) {
238 fprintf(stderr
, "Open the vm device error:%s, ec:%lu\n",
239 vm_name
, GetLastError());
246 int hax_notify_qemu_version(hax_fd vm_fd
, struct hax_qemu_version
*qversion
)
250 if (hax_invalid_fd(vm_fd
)) {
253 ret
= DeviceIoControl(vm_fd
,
254 HAX_VM_IOCTL_NOTIFY_QEMU_VERSION
,
255 qversion
, sizeof(struct hax_qemu_version
),
256 NULL
, 0, &dSize
, (LPOVERLAPPED
) NULL
);
258 fprintf(stderr
, "Failed to notify qemu API version\n");
264 int hax_host_create_vcpu(hax_fd vm_fd
, int vcpuid
)
269 ret
= DeviceIoControl(vm_fd
,
270 HAX_VM_IOCTL_VCPU_CREATE
,
271 &vcpuid
, sizeof(vcpuid
), NULL
, 0, &dSize
,
272 (LPOVERLAPPED
) NULL
);
274 fprintf(stderr
, "Failed to create vcpu %x\n", vcpuid
);
281 hax_fd
hax_host_open_vcpu(int vmid
, int vcpuid
)
283 char *devfs_path
= NULL
;
286 devfs_path
= hax_vcpu_devfs_string(vmid
, vcpuid
);
288 fprintf(stderr
, "Failed to get the devfs\n");
289 return INVALID_HANDLE_VALUE
;
292 hDeviceVCPU
= CreateFile(devfs_path
,
293 GENERIC_READ
| GENERIC_WRITE
,
294 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
,
297 if (hDeviceVCPU
== INVALID_HANDLE_VALUE
) {
298 fprintf(stderr
, "Failed to open the vcpu devfs\n");
304 int hax_host_setup_vcpu_channel(struct hax_vcpu_state
*vcpu
)
306 hax_fd hDeviceVCPU
= vcpu
->fd
;
308 struct hax_tunnel_info info
;
311 ret
= DeviceIoControl(hDeviceVCPU
,
312 HAX_VCPU_IOCTL_SETUP_TUNNEL
,
313 NULL
, 0, &info
, sizeof(info
), &dSize
,
314 (LPOVERLAPPED
) NULL
);
316 fprintf(stderr
, "Failed to setup the hax tunnel\n");
320 if (!valid_hax_tunnel_size(info
.size
)) {
321 fprintf(stderr
, "Invalid hax tunnel size %x\n", info
.size
);
325 vcpu
->tunnel
= (struct hax_tunnel
*) (intptr_t) (info
.va
);
326 vcpu
->iobuf
= (unsigned char *) (intptr_t) (info
.io_va
);
330 int hax_vcpu_run(struct hax_vcpu_state
*vcpu
)
333 HANDLE hDeviceVCPU
= vcpu
->fd
;
336 ret
= DeviceIoControl(hDeviceVCPU
,
338 NULL
, 0, NULL
, 0, &dSize
, (LPOVERLAPPED
) NULL
);
346 int hax_sync_fpu(CPUArchState
*env
, struct fx_layout
*fl
, int set
)
353 fd
= hax_vcpu_get_fd(env
);
354 if (hax_invalid_fd(fd
)) {
361 ret
= DeviceIoControl(hDeviceVCPU
,
362 HAX_VCPU_IOCTL_SET_FPU
,
363 fl
, sizeof(*fl
), NULL
, 0, &dSize
,
364 (LPOVERLAPPED
) NULL
);
366 ret
= DeviceIoControl(hDeviceVCPU
,
367 HAX_VCPU_IOCTL_GET_FPU
,
368 NULL
, 0, fl
, sizeof(*fl
), &dSize
,
369 (LPOVERLAPPED
) NULL
);
378 int hax_sync_msr(CPUArchState
*env
, struct hax_msr_data
*msrs
, int set
)
385 fd
= hax_vcpu_get_fd(env
);
386 if (hax_invalid_fd(fd
)) {
392 ret
= DeviceIoControl(hDeviceVCPU
,
393 HAX_VCPU_IOCTL_SET_MSRS
,
395 msrs
, sizeof(*msrs
), &dSize
, (LPOVERLAPPED
) NULL
);
397 ret
= DeviceIoControl(hDeviceVCPU
,
398 HAX_VCPU_IOCTL_GET_MSRS
,
400 msrs
, sizeof(*msrs
), &dSize
, (LPOVERLAPPED
) NULL
);
409 int hax_sync_vcpu_state(CPUArchState
*env
, struct vcpu_state_t
*state
, int set
)
416 fd
= hax_vcpu_get_fd(env
);
417 if (hax_invalid_fd(fd
)) {
424 ret
= DeviceIoControl(hDeviceVCPU
,
426 state
, sizeof(*state
),
427 NULL
, 0, &dSize
, (LPOVERLAPPED
) NULL
);
429 ret
= DeviceIoControl(hDeviceVCPU
,
432 state
, sizeof(*state
), &dSize
,
433 (LPOVERLAPPED
) NULL
);
442 int hax_inject_interrupt(CPUArchState
*env
, int vector
)
449 fd
= hax_vcpu_get_fd(env
);
450 if (hax_invalid_fd(fd
)) {
456 ret
= DeviceIoControl(hDeviceVCPU
,
457 HAX_VCPU_IOCTL_INTERRUPT
,
458 &vector
, sizeof(vector
), NULL
, 0, &dSize
,
459 (LPOVERLAPPED
) NULL
);
467 static void CALLBACK
dummy_apc_func(ULONG_PTR unused
)
471 void hax_kick_vcpu_thread(CPUState
*cpu
)
474 * FIXME: race condition with the exit_request check in
477 cpu
->exit_request
= 1;
478 if (!qemu_cpu_is_self(cpu
)) {
479 if (!QueueUserAPC(dummy_apc_func
, cpu
->hThread
, 0)) {
480 fprintf(stderr
, "%s: QueueUserAPC failed with error %lu\n",
481 __func__
, GetLastError());