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