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