Home | History | Annotate | Download | only in target-i386
      1 /*
      2 ** Copyright (c) 2011, Intel Corporation
      3 **
      4 ** This software is licensed under the terms of the GNU General Public
      5 ** License version 2, as published by the Free Software Foundation, and
      6 ** may be copied, distributed, and modified under those terms.
      7 **
      8 ** This program is distributed in the hope that it will be useful,
      9 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
     10 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 ** GNU General Public License for more details.
     12 */
     13 
     14 /* HAX module interface - darwin version */
     15 #include <sys/types.h>
     16 #include <sys/stat.h>
     17 #include <fcntl.h>
     18 #include <errno.h>
     19 #include <sys/ioctl.h>
     20 
     21 #include "target-i386/hax-i386.h"
     22 hax_fd hax_mod_open(void)
     23 {
     24     int fd = open("/dev/HAX", O_RDWR);
     25 
     26     if (fd == -1)
     27     {
     28         dprint("Failed to open the hax module\n");
     29         return -errno;
     30     }
     31 
     32     return fd;
     33 }
     34 
     35 int 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     {
     42         dprint("Allocate memory before vm create?\n");
     43         return -EINVAL;
     44     }
     45 
     46     info.size = size;
     47     info.va = va;
     48     ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
     49     if (ret < 0)
     50     {
     51         dprint("Failed to allocate %x memory\n", size);
     52         return ret;
     53     }
     54     return 0;
     55 }
     56 
     57 int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset)
     58 {
     59     struct hax_set_ram_info info, *pinfo = &info;
     60     int ret;
     61     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
     62 
     63     /* We look for the  RAM and ROM only */
     64     if (flags >= IO_MEM_UNASSIGNED)
     65         return 0;
     66 
     67     if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK))
     68     {
     69         dprint("set_phys_mem %x %lx requires page aligned addr and size\n", start_addr, size);
     70         exit(1);
     71         return -1;
     72     }
     73 
     74     info.pa_start = start_addr;
     75     info.size = size;
     76     info.va = (uint64_t)qemu_get_ram_ptr(phys_offset);
     77     info.flags = (flags & IO_MEM_ROM) ? 1 : 0;
     78 
     79     ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, pinfo);
     80     if (ret < 0)
     81     {
     82         dprint("has set phys mem failed\n");
     83         exit(1);
     84     }
     85     return ret;
     86 }
     87 
     88 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
     89 {
     90     int ret;
     91 
     92     ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap);
     93     if (ret == -1)
     94     {
     95         dprint("Failed to get HAX capability\n");
     96         return -errno;
     97     }
     98 
     99     return 0;
    100 }
    101 
    102 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
    103 {
    104     int ret;
    105 
    106     ret = ioctl(hax->fd, HAX_IOCTL_VERSION, version);
    107     if (ret == -1)
    108     {
    109         dprint("Failed to get HAX version\n");
    110         return -errno;
    111     }
    112 
    113     return 0;
    114 }
    115 
    116 static char *hax_vm_devfs_string(int vm_id)
    117 {
    118     char *name;
    119 
    120     if (vm_id > MAX_VM_ID)
    121     {
    122         dprint("Too big VM id\n");
    123         return NULL;
    124     }
    125 
    126     name = qemu_strdup("/dev/hax_vm/vmxx");
    127     if (!name)
    128         return NULL;
    129     sprintf(name, "/dev/hax_vm/vm%02d", vm_id);
    130 
    131     return name;
    132 }
    133 
    134 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
    135 {
    136     char *name;
    137 
    138     if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID)
    139     {
    140         dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
    141         return NULL;
    142     }
    143 
    144     name = qemu_strdup("/dev/hax_vmxx/vcpuyy");
    145     if (!name)
    146         return NULL;
    147 
    148     sprintf(name, "/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id);
    149 
    150     return name;
    151 }
    152 
    153 int hax_host_create_vm(struct hax_state *hax, int *vmid)
    154 {
    155     int ret;
    156     int vm_id = 0;
    157 
    158     if (hax_invalid_fd(hax->fd))
    159         return -EINVAL;
    160 
    161     if (hax->vm)
    162         return 0;
    163 
    164     ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
    165     *vmid = vm_id;
    166     return ret;
    167 }
    168 
    169 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
    170 {
    171     hax_fd fd;
    172     char *vm_name = NULL;
    173 
    174     vm_name = hax_vm_devfs_string(vm_id);
    175     if (!vm_name)
    176         return -1;
    177 
    178     fd = open(vm_name, O_RDWR);
    179     qemu_free(vm_name);
    180 
    181     return fd;
    182 }
    183 
    184 int 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     ret = ioctl(vm_fd, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, qversion);
    192     if (ret == -1)
    193     {
    194         dprint("Failed to notify qemu API version\n");
    195         return -errno;
    196     }
    197 
    198     return 0;
    199 }
    200 
    201 /*
    202  * Simply assume that the size should be bigger than the hax_tunnel,
    203  * since the hax_tunnel can be extended later with backward
    204  * compatibility.
    205  */
    206 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
    207 {
    208     int ret;
    209 
    210     ret = ioctl(vm_fd, HAX_VM_IOCTL_VCPU_CREATE, &vcpuid);
    211     if (ret < 0)
    212         dprint("Failed to create vcpu %x\n", vcpuid);
    213 
    214     return ret;
    215 }
    216 
    217 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
    218 {
    219     char *devfs_path = NULL;
    220     hax_fd fd;
    221 
    222     devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
    223     if (!devfs_path)
    224     {
    225         dprint("Failed to get the devfs\n");
    226         return -EINVAL;
    227     }
    228 
    229     fd = open(devfs_path, O_RDWR);
    230     qemu_free(devfs_path);
    231     if (fd < 0)
    232         dprint("Failed to open the vcpu devfs\n");
    233     return fd;
    234 }
    235 
    236 int 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     {
    244         dprint("Failed to setup the hax tunnel\n");
    245         return ret;
    246     }
    247 
    248     if (!valid_hax_tunnel_size(info.size))
    249     {
    250         dprint("Invalid hax tunnel size %x\n", info.size);
    251         ret = -EINVAL;
    252         return ret;
    253     }
    254 
    255     vcpu->tunnel = (struct hax_tunnel *)(info.va);
    256     vcpu->iobuf = (unsigned char *)(info.io_va);
    257     return 0;
    258 }
    259 
    260 int hax_vcpu_run(struct hax_vcpu_state* vcpu)
    261 {
    262     int ret;
    263 
    264     ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
    265     return ret;
    266 }
    267 
    268 int hax_sync_fpu(CPUState *env, struct fx_layout *fl, int set)
    269 {
    270     int ret, fd;
    271 
    272     fd = hax_vcpu_get_fd(env);
    273     if (fd <= 0)
    274         return -1;
    275 
    276     if (set)
    277         ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
    278     else
    279         ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
    280     return ret;
    281 }
    282 
    283 int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set)
    284 {
    285     int ret, fd;
    286 
    287     fd = hax_vcpu_get_fd(env);
    288     if (fd <= 0)
    289         return -1;
    290     if (set)
    291         ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
    292     else
    293         ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
    294     return ret;
    295 }
    296 
    297 int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set)
    298 {
    299     int ret, fd;
    300 
    301     fd = hax_vcpu_get_fd(env);
    302     if (fd <= 0)
    303         return -1;
    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     return ret;
    310 }
    311 
    312 int hax_inject_interrupt(CPUState *env, int vector)
    313 {
    314     int ret, fd;
    315 
    316     fd = hax_vcpu_get_fd(env);
    317     if (fd <= 0)
    318         return -1;
    319 
    320     ret = ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
    321     return ret;
    322 }
    323