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