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