blob: 5db687ba4d9577264c0a387198356110c392803c [file] [log] [blame]
Jun Nakajimae4a3c782011-12-17 19:22:12 -08001/*
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 */
20static 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
50hax_fd hax_mod_open(void)
51{
52 int ret;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010053 hax_fd fd = INVALID_HANDLE_VALUE;
Jun Nakajimae4a3c782011-12-17 19:22:12 -080054
55 ret = hax_open_device(&fd);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010056 if (ret != 0) {
Jun Nakajimae4a3c782011-12-17 19:22:12 -080057 dprint("Open HAX device failed\n");
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010058 return INVALID_HANDLE_VALUE;
59 }
Jun Nakajimae4a3c782011-12-17 19:22:12 -080060
61 return fd;
62}
63
64int 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) {
David 'Digit' Turnerf2de2ae2014-03-07 16:25:58 +010090 dprint("HAX: Failed to allocate %x memory (address %llx)\n",
91 size, (unsigned long long)va);
92 return -1;
Jun Nakajimae4a3c782011-12-17 19:22:12 -080093 }
94
95 return 0;
96}
97
98
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +010099int hax_set_phys_mem(hwaddr start_addr, ram_addr_t size, ram_addr_t phys_offset)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800100{
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;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +0100121 info.va = (uint64_t)(uintptr_t)qemu_get_ram_ptr(phys_offset);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800122 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
Jiang, Yunhong4a5a0ef2012-02-23 06:31:12 +0800139int 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
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800169int 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
199static 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
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100209 name = g_strdup("\\\\.\\hax_vmxx");
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800210 if (!name)
211 return NULL;
212 sprintf(name, "\\\\.\\hax_vm%02d", vm_id);
213
214 return name;
215}
216
217static 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 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100226 name = g_strdup("\\\\.\\hax_vmxx_vcpuxx");
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800227 if (!name)
228 return NULL;
229 sprintf(name, "\\\\.\\hax_vm%02d_vcpu%02d", vm_id, vcpu_id);
230
231 return name;
232}
233
Jiang, Yunhong1d1280d2012-02-23 05:21:15 +0800234int hax_host_create_vm(struct hax_state *hax, int *vmid)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800235{
236 int ret;
Jiang, Yunhong1d1280d2012-02-23 05:21:15 +0800237 int vm_id = 0;
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800238 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 }
Jiang, Yunhong1d1280d2012-02-23 05:21:15 +0800256 *vmid = vm_id;
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800257 return 0;
258}
259
260hax_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
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100281 g_free(vm_name);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800282 return hDeviceVM;
283}
284
Jiang, Yunhong8a539ea2012-03-23 13:47:38 +0800285int 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
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800308int 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
328hax_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");
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100350 g_free(devfs_path);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800351 return hDeviceVCPU;
352}
353
354int 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 }
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +0100379 vcpu->tunnel = (struct hax_tunnel *)(uintptr_t)(info.va);
380 vcpu->iobuf = (unsigned char *)(uintptr_t)(info.io_va);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800381 return 0;
382}
383
384int 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
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100402int hax_sync_fpu(CPUState *cpu, struct fx_layout *fl, int set)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800403{
404 int ret;
405 hax_fd fd;
406 HANDLE hDeviceVCPU;
407 DWORD dSize = 0;
408
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100409 fd = hax_vcpu_get_fd(cpu);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800410 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
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100435int hax_sync_msr(CPUState *cpu, struct hax_msr_data *msrs, int set)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800436{
437 int ret;
438 hax_fd fd;
439 HANDLE hDeviceVCPU;
440 DWORD dSize = 0;
441
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100442 fd = hax_vcpu_get_fd(cpu);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800443 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
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100467int hax_sync_vcpu_state(CPUState *cpu, struct vcpu_state_t *state, int set)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800468{
469 int ret;
470 hax_fd fd;
471 HANDLE hDeviceVCPU;
472 DWORD dSize;
473
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100474 fd = hax_vcpu_get_fd(cpu);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800475 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
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100500int hax_inject_interrupt(CPUState *cpu, int vector)
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800501{
502 int ret;
503 hax_fd fd;
504 HANDLE hDeviceVCPU;
505 DWORD dSize;
506
David 'Digit' Turner7f38c7f2014-03-26 10:20:11 +0100507 fd = hax_vcpu_get_fd(cpu);
Jun Nakajimae4a3c782011-12-17 19:22:12 -0800508 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}