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