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