qemu/target/i386/hax-windows.c
<<
>>
Prefs
   1/*
   2 * QEMU HAXM support
   3 *
   4 * Copyright (c) 2011 Intel Corporation
   5 *  Written by:
   6 *  Jiang Yunhong<yunhong.jiang@intel.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   9 * See the COPYING file in the top-level directory.
  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 * return 0 when success, -1 when driver not loaded,
  20 * other negative value for other failure
  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/* hax_fd hax_mod_open */
  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;        /* handle to hax module */
 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; /* handle to hax module */
 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