1
2
3
4
5
6
7
8
9
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
20
21
22static 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
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
61int hax_populate_ram(uint64_t va, uint64_t size)
62{
63 int ret;
64 HANDLE hDeviceVM;
65 DWORD dSize = 0;
66
67 if (!hax_global.vm || !hax_global.vm->fd) {
68 fprintf(stderr, "Allocate memory before vm create?\n");
69 return -EINVAL;
70 }
71
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
78 };
79
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
89 };
90
91 ret = DeviceIoControl(hDeviceVM,
92 HAX_VM_IOCTL_ALLOC_RAM,
93 &info, sizeof(info), NULL, 0, &dSize,
94 (LPOVERLAPPED) NULL);
95 }
96
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;
102 }
103
104 return 0;
105}
106
107int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
108{
109 struct hax_set_ram_info info;
110 HANDLE hDeviceVM = hax_global.vm->fd;
111 DWORD dSize = 0;
112 int ret;
113
114 info.pa_start = start_pa;
115 info.size = size;
116 info.va = host_va;
117 info.flags = (uint8_t) flags;
118
119 ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM,
120 &info, sizeof(info), NULL, 0, &dSize,
121 (LPOVERLAPPED) NULL);
122
123 if (!ret) {
124 return -EFAULT;
125 } else {
126 return 0;
127 }
128}
129
130int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
131{
132 int ret;
133 HANDLE hDevice = hax->fd;
134 DWORD dSize = 0;
135 DWORD err = 0;
136
137 if (hax_invalid_fd(hDevice)) {
138 fprintf(stderr, "Invalid fd for hax device!\n");
139 return -ENODEV;
140 }
141
142 ret = DeviceIoControl(hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap,
143 sizeof(*cap), &dSize, (LPOVERLAPPED) NULL);
144
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");
149 }
150 fprintf(stderr, "Failed to get Hax capability:%luu\n", err);
151 return -EFAULT;
152 } else {
153 return 0;
154 }
155}
156
157int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
158{
159 int ret;
160 HANDLE hDevice = hax->fd;
161 DWORD dSize = 0;
162 DWORD err = 0;
163
164 if (hax_invalid_fd(hDevice)) {
165 fprintf(stderr, "Invalid fd for hax device!\n");
166 return -ENODEV;
167 }
168
169 ret = DeviceIoControl(hDevice,
170 HAX_IOCTL_VERSION,
171 NULL, 0,
172 version, sizeof(*version), &dSize,
173 (LPOVERLAPPED) NULL);
174
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");
179 }
180 fprintf(stderr, "Failed to get Hax module version:%lu\n", err);
181 return -EFAULT;
182 } else {
183 return 0;
184 }
185}
186
187static char *hax_vm_devfs_string(int vm_id)
188{
189 char *name;
190
191 if (vm_id > MAX_VM_ID) {
192 fprintf(stderr, "Too big VM id\n");
193 return NULL;
194 }
195
196#define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
197 name = g_strdup(HAX_VM_DEVFS);
198 if (!name) {
199 return NULL;
200 }
201
202 snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
203 return name;
204}
205
206static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
207{
208 char *name;
209
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;
213 }
214
215#define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
216 name = g_strdup(HAX_VCPU_DEVFS);
217 if (!name) {
218 return NULL;
219 }
220
221 snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
222 vm_id, vcpu_id);
223 return name;
224}
225
226int hax_host_create_vm(struct hax_state *hax, int *vmid)
227{
228 int ret;
229 int vm_id = 0;
230 DWORD dSize = 0;
231
232 if (hax_invalid_fd(hax->fd)) {
233 return -EINVAL;
234 }
235
236 if (hax->vm) {
237 return 0;
238 }
239
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;
248 }
249 *vmid = vm_id;
250 return 0;
251}
252
253hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
254{
255 char *vm_name = NULL;
256 hax_fd hDeviceVM;
257
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;
262 }
263
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());
270 }
271
272 g_free(vm_name);
273 return hDeviceVM;
274}
275
276int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
277{
278 int ret;
279 DWORD dSize = 0;
280 if (hax_invalid_fd(vm_fd)) {
281 return -EINVAL;
282 }
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;
290 }
291 return 0;
292}
293
294int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
295{
296 int ret;
297 DWORD dSize = 0;
298
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;
306 }
307
308 return 0;
309}
310
311hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
312{
313 char *devfs_path = NULL;
314 hax_fd hDeviceVCPU;
315
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;
320 }
321
322 hDeviceVCPU = CreateFile(devfs_path,
323 GENERIC_READ | GENERIC_WRITE,
324 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
325 NULL);
326
327 if (hDeviceVCPU == INVALID_HANDLE_VALUE) {
328 fprintf(stderr, "Failed to open the vcpu devfs\n");
329 }
330 g_free(devfs_path);
331 return hDeviceVCPU;
332}
333
334int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
335{
336 hax_fd hDeviceVCPU = vcpu->fd;
337 int ret;
338 struct hax_tunnel_info info;
339 DWORD dSize = 0;
340
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;
348 }
349
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;
354 }
355 vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
356 vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
357 return 0;
358}
359
360int hax_vcpu_run(struct hax_vcpu_state *vcpu)
361{
362 int ret;
363 HANDLE hDeviceVCPU = vcpu->fd;
364 DWORD dSize = 0;
365
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;
373 }
374}
375
376int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
377{
378 int ret;
379 hax_fd fd;
380 HANDLE hDeviceVCPU;
381 DWORD dSize = 0;
382
383 fd = hax_vcpu_get_fd(env);
384 if (hax_invalid_fd(fd)) {
385 return -1;
386 }
387
388 hDeviceVCPU = fd;
389
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);
400 }
401 if (!ret) {
402 return -EFAULT;
403 } else {
404 return 0;
405 }
406}
407
408int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
409{
410 int ret;
411 hax_fd fd;
412 HANDLE hDeviceVCPU;
413 DWORD dSize = 0;
414
415 fd = hax_vcpu_get_fd(env);
416 if (hax_invalid_fd(fd)) {
417 return -1;
418 }
419 hDeviceVCPU = fd;
420
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);
431 }
432 if (!ret) {
433 return -EFAULT;
434 } else {
435 return 0;
436 }
437}
438
439int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
440{
441 int ret;
442 hax_fd fd;
443 HANDLE hDeviceVCPU;
444 DWORD dSize;
445
446 fd = hax_vcpu_get_fd(env);
447 if (hax_invalid_fd(fd)) {
448 return -1;
449 }
450
451 hDeviceVCPU = fd;
452
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);
464 }
465 if (!ret) {
466 return -EFAULT;
467 } else {
468 return 0;
469 }
470}
471
472int hax_inject_interrupt(CPUArchState *env, int vector)
473{
474 int ret;
475 hax_fd fd;
476 HANDLE hDeviceVCPU;
477 DWORD dSize;
478
479 fd = hax_vcpu_get_fd(env);
480 if (hax_invalid_fd(fd)) {
481 return -1;
482 }
483
484 hDeviceVCPU = fd;
485
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;
494 }
495}
496