hax-windows.c revision 1d1280d7d347bb9467bfe9c161cba254f9e55d1c
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_mod_version(struct hax_state *hax, struct hax_module_version *version) 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_VERSION, 150 NULL, 0, 151 version, sizeof(*version), 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 module is too large.\n"); 160 dprint("Failed to get Hax module version:%d\n", err); 161 return -EFAULT; 162 } else 163 return 0; 164} 165 166static char *hax_vm_devfs_string(int vm_id) 167{ 168 char *name; 169 170 if (vm_id > MAX_VM_ID) 171 { 172 dprint("Too big VM id\n"); 173 return NULL; 174 } 175 176 name = qemu_strdup("\\\\.\\hax_vmxx"); 177 if (!name) 178 return NULL; 179 sprintf(name, "\\\\.\\hax_vm%02d", vm_id); 180 181 return name; 182} 183 184static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id) 185{ 186 char *name; 187 188 if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) 189 { 190 dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id); 191 return NULL; 192 } 193 name = qemu_strdup("\\\\.\\hax_vmxx_vcpuxx"); 194 if (!name) 195 return NULL; 196 sprintf(name, "\\\\.\\hax_vm%02d_vcpu%02d", vm_id, vcpu_id); 197 198 return name; 199} 200 201int hax_host_create_vm(struct hax_state *hax, int *vmid) 202{ 203 int ret; 204 int vm_id = 0; 205 DWORD dSize = 0; 206 207 if (hax_invalid_fd(hax->fd)) 208 return -EINVAL; 209 210 if (hax->vm) 211 return 0; 212 213 ret = DeviceIoControl(hax->fd, 214 HAX_IOCTL_CREATE_VM, 215 NULL, 0, 216 &vm_id, sizeof(vm_id), 217 &dSize, 218 (LPOVERLAPPED) NULL); 219 if (!ret) { 220 dprint("error code:%d", GetLastError()); 221 return -1; 222 } 223 *vmid = vm_id; 224 return 0; 225} 226 227hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id) 228{ 229 char *vm_name = NULL; 230 hax_fd hDeviceVM; 231 232 vm_name = hax_vm_devfs_string(vm_id); 233 if (!vm_name) { 234 dprint("Incorrect name\n"); 235 return INVALID_HANDLE_VALUE; 236 } 237 238 hDeviceVM = CreateFile(vm_name, 239 GENERIC_READ | GENERIC_WRITE, 240 0, 241 NULL, 242 CREATE_ALWAYS, 243 FILE_ATTRIBUTE_NORMAL, 244 NULL); 245 if (hDeviceVM == INVALID_HANDLE_VALUE) 246 dprint("Open the vm devcie error:%s, ec:%d\n", vm_name, GetLastError()); 247 248 qemu_free(vm_name); 249 return hDeviceVM; 250} 251 252int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid) 253{ 254 int ret; 255 DWORD dSize = 0; 256 257 ret = DeviceIoControl(vm_fd, 258 HAX_VM_IOCTL_VCPU_CREATE, 259 &vcpuid, sizeof(vcpuid), 260 NULL, 0, 261 &dSize, 262 (LPOVERLAPPED) NULL); 263 if (!ret) 264 { 265 dprint("Failed to create vcpu %x\n", vcpuid); 266 return -1; 267 } 268 269 return 0; 270} 271 272hax_fd hax_host_open_vcpu(int vmid, int vcpuid) 273{ 274 char *devfs_path = NULL; 275 hax_fd hDeviceVCPU; 276 277 devfs_path = hax_vcpu_devfs_string(vmid, vcpuid); 278 if (!devfs_path) 279 { 280 dprint("Failed to get the devfs\n"); 281 return INVALID_HANDLE_VALUE; 282 } 283 284 hDeviceVCPU = CreateFile( devfs_path, 285 GENERIC_READ | GENERIC_WRITE, 286 0, 287 NULL, 288 CREATE_ALWAYS, 289 FILE_ATTRIBUTE_NORMAL, 290 NULL); 291 292 if (hDeviceVCPU == INVALID_HANDLE_VALUE) 293 dprint("Failed to open the vcpu devfs\n"); 294 qemu_free(devfs_path); 295 return hDeviceVCPU; 296} 297 298int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu) 299{ 300 hax_fd hDeviceVCPU = vcpu->fd; 301 int ret; 302 struct hax_tunnel_info info; 303 DWORD dSize = 0; 304 305 ret = DeviceIoControl(hDeviceVCPU, 306 HAX_VCPU_IOCTL_SETUP_TUNNEL, 307 NULL, 0, 308 &info, sizeof(info), 309 &dSize, 310 (LPOVERLAPPED) NULL); 311 if (!ret) 312 { 313 dprint("Failed to setup the hax tunnel\n"); 314 return -1; 315 } 316 317 if (!valid_hax_tunnel_size(info.size)) 318 { 319 dprint("Invalid hax tunnel size %x\n", info.size); 320 ret = -EINVAL; 321 return ret; 322 } 323 vcpu->tunnel = (struct hax_tunnel *)(info.va); 324 vcpu->iobuf = (unsigned char *)(info.io_va); 325 return 0; 326} 327 328int hax_vcpu_run(struct hax_vcpu_state* vcpu) 329{ 330 int ret; 331 HANDLE hDeviceVCPU = vcpu->fd; 332 DWORD dSize = 0; 333 334 ret = DeviceIoControl(hDeviceVCPU, 335 HAX_VCPU_IOCTL_RUN, 336 NULL, 0, 337 NULL, 0, 338 &dSize, 339 (LPOVERLAPPED) NULL); 340 if (!ret) 341 return -EFAULT; 342 else 343 return 0; 344} 345 346int hax_sync_fpu(CPUState *env, struct fx_layout *fl, int set) 347{ 348 int ret; 349 hax_fd fd; 350 HANDLE hDeviceVCPU; 351 DWORD dSize = 0; 352 353 fd = hax_vcpu_get_fd(env); 354 if (hax_invalid_fd(fd)) 355 return -1; 356 357 hDeviceVCPU = fd; 358 359 if (set) 360 ret = DeviceIoControl(hDeviceVCPU, 361 HAX_VCPU_IOCTL_SET_FPU, 362 fl, sizeof(*fl), 363 NULL, 0, 364 &dSize, 365 (LPOVERLAPPED) NULL); 366 else 367 ret = DeviceIoControl(hDeviceVCPU, 368 HAX_VCPU_IOCTL_GET_FPU, 369 NULL, 0, 370 fl, sizeof(*fl), 371 &dSize, 372 (LPOVERLAPPED) NULL); 373 if (!ret) 374 return -EFAULT; 375 else 376 return 0; 377} 378 379int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set) 380{ 381 int ret; 382 hax_fd fd; 383 HANDLE hDeviceVCPU; 384 DWORD dSize = 0; 385 386 fd = hax_vcpu_get_fd(env); 387 if (hax_invalid_fd(fd)) 388 return -1; 389 hDeviceVCPU = fd; 390 391 if (set) 392 ret = DeviceIoControl(hDeviceVCPU, 393 HAX_VCPU_IOCTL_SET_MSRS, 394 msrs, sizeof(*msrs), 395 msrs, sizeof(*msrs), 396 &dSize, 397 (LPOVERLAPPED) NULL); 398 else 399 ret = DeviceIoControl(hDeviceVCPU, 400 HAX_VCPU_IOCTL_GET_MSRS, 401 msrs, sizeof(*msrs), 402 msrs, sizeof(*msrs), 403 &dSize, 404 (LPOVERLAPPED) NULL); 405 if (!ret) 406 return -EFAULT; 407 else 408 return 0; 409} 410 411int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set) 412{ 413 int ret; 414 hax_fd fd; 415 HANDLE hDeviceVCPU; 416 DWORD dSize; 417 418 fd = hax_vcpu_get_fd(env); 419 if (hax_invalid_fd(fd)) 420 return -1; 421 422 hDeviceVCPU = fd; 423 424 if (set) 425 ret = DeviceIoControl(hDeviceVCPU, 426 HAX_VCPU_SET_REGS, 427 state, sizeof(*state), 428 NULL, 0, 429 &dSize, 430 (LPOVERLAPPED) NULL); 431 else 432 ret = DeviceIoControl(hDeviceVCPU, 433 HAX_VCPU_GET_REGS, 434 NULL, 0, 435 state, sizeof(*state), 436 &dSize, 437 (LPOVERLAPPED) NULL); 438 if (!ret) 439 return -EFAULT; 440 else 441 return 0; 442} 443 444int hax_inject_interrupt(CPUState *env, int vector) 445{ 446 int ret; 447 hax_fd fd; 448 HANDLE hDeviceVCPU; 449 DWORD dSize; 450 451 fd = hax_vcpu_get_fd(env); 452 if (hax_invalid_fd(fd)) 453 return -1; 454 455 hDeviceVCPU = fd; 456 457 ret = DeviceIoControl(hDeviceVCPU, 458 HAX_VCPU_IOCTL_INTERRUPT, 459 &vector, sizeof(vector), 460 NULL, 0, 461 &dSize, 462 (LPOVERLAPPED) NULL); 463 if (!ret) 464 return -EFAULT; 465 else 466 return 0; 467} 468