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