qemu/target/i386/hax-posix.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/* HAX module interface - darwin version */
  14#include "qemu/osdep.h"
  15#include <sys/ioctl.h>
  16
  17#include "target/i386/hax-i386.h"
  18
  19hax_fd hax_mod_open(void)
  20{
  21    int fd = open("/dev/HAX", O_RDWR);
  22    if (fd == -1) {
  23        fprintf(stderr, "Failed to open the hax module\n");
  24    }
  25
  26    fcntl(fd, F_SETFD, FD_CLOEXEC);
  27
  28    return fd;
  29}
  30
  31int hax_populate_ram(uint64_t va, uint64_t size)
  32{
  33    int ret;
  34
  35    if (!hax_global.vm || !hax_global.vm->fd) {
  36        fprintf(stderr, "Allocate memory before vm create?\n");
  37        return -EINVAL;
  38    }
  39
  40    if (hax_global.supports_64bit_ramblock) {
  41        struct hax_ramblock_info ramblock = {
  42            .start_va = va,
  43            .size = size,
  44            .reserved = 0
  45        };
  46
  47        ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ADD_RAMBLOCK, &ramblock);
  48    } else {
  49        struct hax_alloc_ram_info info = {
  50            .size = (uint32_t)size,
  51            .pad = 0,
  52            .va = va
  53        };
  54
  55        ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
  56    }
  57    if (ret < 0) {
  58        fprintf(stderr, "Failed to register RAM block: ret=%d, va=0x%" PRIx64
  59                ", size=0x%" PRIx64 ", method=%s\n", ret, va, size,
  60                hax_global.supports_64bit_ramblock ? "new" : "legacy");
  61        return ret;
  62    }
  63    return 0;
  64}
  65
  66int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
  67{
  68    struct hax_set_ram_info info;
  69    int ret;
  70
  71    info.pa_start = start_pa;
  72    info.size = size;
  73    info.va = host_va;
  74    info.flags = (uint8_t) flags;
  75
  76    ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, &info);
  77    if (ret < 0) {
  78        return -errno;
  79    }
  80    return 0;
  81}
  82
  83int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
  84{
  85    int ret;
  86
  87    ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap);
  88    if (ret == -1) {
  89        fprintf(stderr, "Failed to get HAX capability\n");
  90        return -errno;
  91    }
  92
  93    return 0;
  94}
  95
  96int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
  97{
  98    int ret;
  99
 100    ret = ioctl(hax->fd, HAX_IOCTL_VERSION, version);
 101    if (ret == -1) {
 102        fprintf(stderr, "Failed to get HAX version\n");
 103        return -errno;
 104    }
 105
 106    return 0;
 107}
 108
 109static char *hax_vm_devfs_string(int vm_id)
 110{
 111    char *name;
 112
 113    if (vm_id > MAX_VM_ID) {
 114        fprintf(stderr, "Too big VM id\n");
 115        return NULL;
 116    }
 117
 118#define HAX_VM_DEVFS "/dev/hax_vm/vmxx"
 119    name = g_strdup(HAX_VM_DEVFS);
 120    if (!name) {
 121        return NULL;
 122    }
 123
 124    snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id);
 125    return name;
 126}
 127
 128static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
 129{
 130    char *name;
 131
 132    if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
 133        fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
 134        return NULL;
 135    }
 136
 137#define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx"
 138    name = g_strdup(HAX_VCPU_DEVFS);
 139    if (!name) {
 140        return NULL;
 141    }
 142
 143    snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d",
 144             vm_id, vcpu_id);
 145    return name;
 146}
 147
 148int hax_host_create_vm(struct hax_state *hax, int *vmid)
 149{
 150    int ret;
 151    int vm_id = 0;
 152
 153    if (hax_invalid_fd(hax->fd)) {
 154        return -EINVAL;
 155    }
 156
 157    if (hax->vm) {
 158        return 0;
 159    }
 160
 161    ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
 162    *vmid = vm_id;
 163    return ret;
 164}
 165
 166hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
 167{
 168    hax_fd fd;
 169    char *vm_name = NULL;
 170
 171    vm_name = hax_vm_devfs_string(vm_id);
 172    if (!vm_name) {
 173        return -1;
 174    }
 175
 176    fd = open(vm_name, O_RDWR);
 177    g_free(vm_name);
 178
 179    fcntl(fd, F_SETFD, FD_CLOEXEC);
 180
 181    return fd;
 182}
 183
 184int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
 185{
 186    int ret;
 187
 188    if (hax_invalid_fd(vm_fd)) {
 189        return -EINVAL;
 190    }
 191
 192    ret = ioctl(vm_fd, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, qversion);
 193
 194    if (ret < 0) {
 195        fprintf(stderr, "Failed to notify qemu API version\n");
 196        return ret;
 197    }
 198    return 0;
 199}
 200
 201/* Simply assume the size should be bigger than the hax_tunnel,
 202 * since the hax_tunnel can be extended later with compatibility considered
 203 */
 204int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
 205{
 206    int ret;
 207
 208    ret = ioctl(vm_fd, HAX_VM_IOCTL_VCPU_CREATE, &vcpuid);
 209    if (ret < 0) {
 210        fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
 211    }
 212
 213    return ret;
 214}
 215
 216hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
 217{
 218    char *devfs_path = NULL;
 219    hax_fd fd;
 220
 221    devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
 222    if (!devfs_path) {
 223        fprintf(stderr, "Failed to get the devfs\n");
 224        return -EINVAL;
 225    }
 226
 227    fd = open(devfs_path, O_RDWR);
 228    g_free(devfs_path);
 229    if (fd < 0) {
 230        fprintf(stderr, "Failed to open the vcpu devfs\n");
 231    }
 232    fcntl(fd, F_SETFD, FD_CLOEXEC);
 233    return fd;
 234}
 235
 236int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
 237{
 238    int ret;
 239    struct hax_tunnel_info info;
 240
 241    ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_SETUP_TUNNEL, &info);
 242    if (ret) {
 243        fprintf(stderr, "Failed to setup the hax tunnel\n");
 244        return ret;
 245    }
 246
 247    if (!valid_hax_tunnel_size(info.size)) {
 248        fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
 249        ret = -EINVAL;
 250        return ret;
 251    }
 252
 253    vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
 254    vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
 255    return 0;
 256}
 257
 258int hax_vcpu_run(struct hax_vcpu_state *vcpu)
 259{
 260    return ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
 261}
 262
 263int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
 264{
 265    int ret, fd;
 266
 267    fd = hax_vcpu_get_fd(env);
 268    if (fd <= 0) {
 269        return -1;
 270    }
 271
 272    if (set) {
 273        ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
 274    } else {
 275        ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
 276    }
 277    return ret;
 278}
 279
 280int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
 281{
 282    int ret, fd;
 283
 284    fd = hax_vcpu_get_fd(env);
 285    if (fd <= 0) {
 286        return -1;
 287    }
 288    if (set) {
 289        ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
 290    } else {
 291        ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
 292    }
 293    return ret;
 294}
 295
 296int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
 297{
 298    int ret, fd;
 299
 300    fd = hax_vcpu_get_fd(env);
 301    if (fd <= 0) {
 302        return -1;
 303    }
 304
 305    if (set) {
 306        ret = ioctl(fd, HAX_VCPU_SET_REGS, state);
 307    } else {
 308        ret = ioctl(fd, HAX_VCPU_GET_REGS, state);
 309    }
 310    return ret;
 311}
 312
 313int hax_inject_interrupt(CPUArchState *env, int vector)
 314{
 315    int fd;
 316
 317    fd = hax_vcpu_get_fd(env);
 318    if (fd <= 0) {
 319        return -1;
 320    }
 321
 322    return ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
 323}
 324