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 #include "target-i386/hax-i386.h"
     15 
     16 /*
     17  * return 0 upon success, -1 when the driver is not loaded,
     18  * other negative value for other failures
     19  */
     20 static int hax_open_device(hax_fd *fd)
     21 {
     22     uint32_t errNum = 0;
     23     HANDLE hDevice;
     24 
     25     if (!fd)
     26         return -2;
     27 
     28     hDevice = CreateFile( "\\\\.\\HAX",
     29       GENERIC_READ | GENERIC_WRITE,
     30       0,
     31       NULL,
     32       CREATE_ALWAYS,
     33       FILE_ATTRIBUTE_NORMAL,
     34       NULL);
     35 
     36     if (hDevice == INVALID_HANDLE_VALUE)
     37     {
     38         dprint("Failed to open the HAX device!\n");
     39         errNum = GetLastError();
     40         if (errNum == ERROR_FILE_NOT_FOUND)
     41             return -1;
     42         return -2;
     43     }
     44     *fd = hDevice;
     45     dprint("device fd:%d\n", *fd);
     46     return 0;
     47 }
     48 
     49 
     50 hax_fd hax_mod_open(void)
     51 {
     52     int ret;
     53     hax_fd fd;
     54 
     55     ret = hax_open_device(&fd);
     56     if (ret != 0)
     57         dprint("Open HAX device failed\n");
     58 
     59     return fd;
     60 }
     61 
     62 int hax_populate_ram(uint64_t va, uint32_t size)
     63 {
     64     int ret;
     65     struct hax_alloc_ram_info info;
     66     HANDLE hDeviceVM;
     67     DWORD dSize = 0;
     68 
     69     if (!hax_global.vm || !hax_global.vm->fd)
     70     {
     71         dprint("Allocate memory before vm create?\n");
     72         return -EINVAL;
     73     }
     74 
     75     info.size = size;
     76     info.va = va;
     77 
     78     hDeviceVM = hax_global.vm->fd;
     79 
     80     ret = DeviceIoControl(hDeviceVM,
     81       HAX_VM_IOCTL_ALLOC_RAM,
     82       &info, sizeof(info),
     83       NULL, 0,
     84       &dSize,
     85       (LPOVERLAPPED) NULL);
     86 
     87     if (!ret) {
     88         dprint("Failed to allocate %x memory\n", size);
     89         return ret;
     90     }
     91 
     92     return 0;
     93 }
     94 
     95 
     96 int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset)
     97 {
     98     struct hax_set_ram_info info, *pinfo = &info;
     99     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
    100     HANDLE hDeviceVM;
    101     DWORD dSize = 0;
    102     int ret = 0;
    103 
    104     /* We look for the  RAM and ROM only */
    105     if (flags >= IO_MEM_UNASSIGNED)
    106         return 0;
    107 
    108     if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK))
    109     {
    110         dprint(
    111           "set_phys_mem %x %lx requires page aligned addr and size\n",
    112           start_addr, size);
    113         return -1;
    114     }
    115 
    116     info.pa_start = start_addr;
    117     info.size = size;
    118     info.va = (uint64_t)qemu_get_ram_ptr(phys_offset);
    119     info.flags = (flags & IO_MEM_ROM) ? 1 : 0;
    120 
    121     hDeviceVM = hax_global.vm->fd;
    122 
    123     ret = DeviceIoControl(hDeviceVM,
    124       HAX_VM_IOCTL_SET_RAM,
    125       pinfo, sizeof(*pinfo),
    126       NULL, 0,
    127       &dSize,
    128       (LPOVERLAPPED) NULL);
    129 
    130     if (!ret)
    131         return -EFAULT;
    132     else
    133         return 0;
    134 }
    135 
    136 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
    137 {
    138     int ret;
    139     HANDLE hDevice = hax->fd;   //handle to hax module
    140     DWORD dSize = 0;
    141     DWORD err = 0;
    142 
    143     if (hax_invalid_fd(hDevice)) {
    144         dprint("Invalid fd for hax device!\n");
    145         return -ENODEV;
    146     }
    147 
    148     ret = DeviceIoControl(hDevice,
    149       HAX_IOCTL_CAPABILITY,
    150       NULL, 0,
    151       cap, sizeof(*cap),
    152       &dSize,
    153       (LPOVERLAPPED) NULL);
    154 
    155     if (!ret) {
    156         err = GetLastError();
    157         if (err == ERROR_INSUFFICIENT_BUFFER ||
    158             err == ERROR_MORE_DATA)
    159             dprint("hax capability is too long to hold.\n");
    160         dprint("Failed to get Hax capability:%d\n", err);
    161         return -EFAULT;
    162     } else
    163         return 0;
    164 }
    165 
    166 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
    167 {
    168     int ret;
    169     HANDLE hDevice = hax->fd;   //handle to hax module
    170     DWORD dSize = 0;
    171     DWORD err = 0;
    172 
    173     if (hax_invalid_fd(hDevice)) {
    174         dprint("Invalid fd for hax device!\n");
    175         return -ENODEV;
    176     }
    177 
    178     ret = DeviceIoControl(hDevice,
    179       HAX_IOCTL_VERSION,
    180       NULL, 0,
    181       version, sizeof(*version),
    182       &dSize,
    183       (LPOVERLAPPED) NULL);
    184 
    185     if (!ret) {
    186         err = GetLastError();
    187         if (err == ERROR_INSUFFICIENT_BUFFER ||
    188             err == ERROR_MORE_DATA)
    189             dprint("HAX module is too large.\n");
    190         dprint("Failed to get Hax module version:%d\n", err);
    191         return -EFAULT;
    192     } else
    193         return 0;
    194 }
    195 
    196 static char *hax_vm_devfs_string(int vm_id)
    197 {
    198     char *name;
    199 
    200     if (vm_id > MAX_VM_ID)
    201     {
    202         dprint("Too big VM id\n");
    203         return NULL;
    204     }
    205 
    206     name = qemu_strdup("\\\\.\\hax_vmxx");
    207     if (!name)
    208         return NULL;
    209     sprintf(name, "\\\\.\\hax_vm%02d", vm_id);
    210 
    211     return name;
    212 }
    213 
    214 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
    215 {
    216     char *name;
    217 
    218     if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID)
    219     {
    220         dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
    221         return NULL;
    222     }
    223     name = qemu_strdup("\\\\.\\hax_vmxx_vcpuxx");
    224     if (!name)
    225         return NULL;
    226     sprintf(name, "\\\\.\\hax_vm%02d_vcpu%02d", vm_id, vcpu_id);
    227 
    228     return name;
    229 }
    230 
    231 int hax_host_create_vm(struct hax_state *hax, int *vmid)
    232 {
    233     int ret;
    234     int vm_id = 0;
    235     DWORD dSize = 0;
    236 
    237     if (hax_invalid_fd(hax->fd))
    238         return -EINVAL;
    239 
    240     if (hax->vm)
    241         return 0;
    242 
    243     ret = DeviceIoControl(hax->fd,
    244       HAX_IOCTL_CREATE_VM,
    245       NULL, 0,
    246       &vm_id, sizeof(vm_id),
    247       &dSize,
    248       (LPOVERLAPPED) NULL);
    249     if (!ret) {
    250         dprint("error code:%d", GetLastError());
    251         return -1;
    252     }
    253     *vmid = vm_id;
    254     return 0;
    255 }
    256 
    257 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
    258 {
    259     char *vm_name = NULL;
    260     hax_fd hDeviceVM;
    261 
    262     vm_name = hax_vm_devfs_string(vm_id);
    263     if (!vm_name) {
    264         dprint("Incorrect name\n");
    265         return INVALID_HANDLE_VALUE;
    266     }
    267 
    268     hDeviceVM = CreateFile(vm_name,
    269       GENERIC_READ | GENERIC_WRITE,
    270       0,
    271       NULL,
    272       CREATE_ALWAYS,
    273       FILE_ATTRIBUTE_NORMAL,
    274       NULL);
    275     if (hDeviceVM == INVALID_HANDLE_VALUE)
    276         dprint("Open the vm devcie error:%s, ec:%d\n", vm_name, GetLastError());
    277 
    278     qemu_free(vm_name);
    279     return hDeviceVM;
    280 }
    281 
    282 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
    283 {
    284     int ret;
    285     DWORD dSize = 0;
    286 
    287     if (hax_invalid_fd(vm_fd))
    288         return -EINVAL;
    289 
    290     ret = DeviceIoControl(vm_fd,
    291       HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
    292       qversion, sizeof(struct hax_qemu_version),
    293       NULL, 0,
    294       &dSize,
    295       (LPOVERLAPPED) NULL);
    296     if (!ret)
    297     {
    298         dprint("Failed to notify qemu API version\n");
    299         return -1;
    300     }
    301 
    302     return 0;
    303 }
    304 
    305 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
    306 {
    307     int ret;
    308     DWORD dSize = 0;
    309 
    310     ret = DeviceIoControl(vm_fd,
    311       HAX_VM_IOCTL_VCPU_CREATE,
    312       &vcpuid, sizeof(vcpuid),
    313       NULL, 0,
    314       &dSize,
    315       (LPOVERLAPPED) NULL);
    316     if (!ret)
    317     {
    318         dprint("Failed to create vcpu %x\n", vcpuid);
    319         return -1;
    320     }
    321 
    322     return 0;
    323 }
    324 
    325 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
    326 {
    327     char *devfs_path = NULL;
    328     hax_fd hDeviceVCPU;
    329 
    330     devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
    331     if (!devfs_path)
    332     {
    333         dprint("Failed to get the devfs\n");
    334         return INVALID_HANDLE_VALUE;
    335     }
    336 
    337     hDeviceVCPU = CreateFile( devfs_path,
    338       GENERIC_READ | GENERIC_WRITE,
    339       0,
    340       NULL,
    341       CREATE_ALWAYS,
    342       FILE_ATTRIBUTE_NORMAL,
    343       NULL);
    344 
    345     if (hDeviceVCPU == INVALID_HANDLE_VALUE)
    346         dprint("Failed to open the vcpu devfs\n");
    347     qemu_free(devfs_path);
    348     return hDeviceVCPU;
    349 }
    350 
    351 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
    352 {
    353     hax_fd hDeviceVCPU = vcpu->fd;
    354     int ret;
    355     struct hax_tunnel_info info;
    356     DWORD dSize = 0;
    357 
    358     ret = DeviceIoControl(hDeviceVCPU,
    359       HAX_VCPU_IOCTL_SETUP_TUNNEL,
    360       NULL, 0,
    361       &info, sizeof(info),
    362       &dSize,
    363       (LPOVERLAPPED) NULL);
    364     if (!ret)
    365     {
    366         dprint("Failed to setup the hax tunnel\n");
    367         return -1;
    368     }
    369 
    370     if (!valid_hax_tunnel_size(info.size))
    371     {
    372         dprint("Invalid hax tunnel size %x\n", info.size);
    373         ret = -EINVAL;
    374         return ret;
    375     }
    376     vcpu->tunnel = (struct hax_tunnel *)(info.va);
    377     vcpu->iobuf = (unsigned char *)(info.io_va);
    378     return 0;
    379 }
    380 
    381 int hax_vcpu_run(struct hax_vcpu_state* vcpu)
    382 {
    383     int ret;
    384     HANDLE hDeviceVCPU = vcpu->fd;
    385     DWORD dSize = 0;
    386 
    387     ret = DeviceIoControl(hDeviceVCPU,
    388       HAX_VCPU_IOCTL_RUN,
    389       NULL, 0,
    390       NULL, 0,
    391       &dSize,
    392       (LPOVERLAPPED) NULL);
    393     if (!ret)
    394         return -EFAULT;
    395     else
    396         return 0;
    397 }
    398 
    399 int hax_sync_fpu(CPUState *env, struct fx_layout *fl, int set)
    400 {
    401     int ret;
    402     hax_fd fd;
    403     HANDLE hDeviceVCPU;
    404     DWORD dSize = 0;
    405 
    406     fd = hax_vcpu_get_fd(env);
    407     if (hax_invalid_fd(fd))
    408         return -1;
    409 
    410     hDeviceVCPU = fd;
    411 
    412     if (set)
    413         ret = DeviceIoControl(hDeviceVCPU,
    414           HAX_VCPU_IOCTL_SET_FPU,
    415           fl, sizeof(*fl),
    416           NULL, 0,
    417           &dSize,
    418           (LPOVERLAPPED) NULL);
    419     else
    420         ret = DeviceIoControl(hDeviceVCPU,
    421           HAX_VCPU_IOCTL_GET_FPU,
    422           NULL, 0,
    423           fl, sizeof(*fl),
    424           &dSize,
    425           (LPOVERLAPPED) NULL);
    426     if (!ret)
    427         return -EFAULT;
    428     else
    429         return 0;
    430 }
    431 
    432 int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set)
    433 {
    434     int ret;
    435     hax_fd fd;
    436     HANDLE hDeviceVCPU;
    437     DWORD dSize = 0;
    438 
    439     fd = hax_vcpu_get_fd(env);
    440     if (hax_invalid_fd(fd))
    441         return -1;
    442     hDeviceVCPU = fd;
    443 
    444     if (set)
    445         ret = DeviceIoControl(hDeviceVCPU,
    446           HAX_VCPU_IOCTL_SET_MSRS,
    447           msrs, sizeof(*msrs),
    448           msrs, sizeof(*msrs),
    449           &dSize,
    450           (LPOVERLAPPED) NULL);
    451     else
    452         ret = DeviceIoControl(hDeviceVCPU,
    453           HAX_VCPU_IOCTL_GET_MSRS,
    454           msrs, sizeof(*msrs),
    455           msrs, sizeof(*msrs),
    456           &dSize,
    457           (LPOVERLAPPED) NULL);
    458     if (!ret)
    459         return -EFAULT;
    460     else
    461         return 0;
    462 }
    463 
    464 int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set)
    465 {
    466     int ret;
    467     hax_fd fd;
    468     HANDLE hDeviceVCPU;
    469     DWORD dSize;
    470 
    471     fd = hax_vcpu_get_fd(env);
    472     if (hax_invalid_fd(fd))
    473         return -1;
    474 
    475     hDeviceVCPU = fd;
    476 
    477     if (set)
    478         ret = DeviceIoControl(hDeviceVCPU,
    479           HAX_VCPU_SET_REGS,
    480           state, sizeof(*state),
    481           NULL, 0,
    482           &dSize,
    483           (LPOVERLAPPED) NULL);
    484     else
    485         ret = DeviceIoControl(hDeviceVCPU,
    486           HAX_VCPU_GET_REGS,
    487           NULL, 0,
    488           state, sizeof(*state),
    489           &dSize,
    490           (LPOVERLAPPED) NULL);
    491     if (!ret)
    492         return -EFAULT;
    493     else
    494         return 0;
    495 }
    496 
    497 int hax_inject_interrupt(CPUState *env, int vector)
    498 {
    499     int ret;
    500     hax_fd fd;
    501     HANDLE hDeviceVCPU;
    502     DWORD dSize;
    503 
    504     fd = hax_vcpu_get_fd(env);
    505     if (hax_invalid_fd(fd))
    506         return -1;
    507 
    508     hDeviceVCPU = fd;
    509 
    510     ret = DeviceIoControl(hDeviceVCPU,
    511       HAX_VCPU_IOCTL_INTERRUPT,
    512       &vector, sizeof(vector),
    513       NULL, 0,
    514       &dSize,
    515       (LPOVERLAPPED) NULL);
    516     if (!ret)
    517         return -EFAULT;
    518     else
    519         return 0;
    520 }
    521