aboutsummaryrefslogtreecommitdiffstats
path: root/target-i386/hax-darwin.c
diff options
context:
space:
mode:
authorJun Nakajima <jun.nakajima@intel.com>2011-12-17 19:22:12 -0800
committerJiang, Yunhong <yunhong.jiang@intel.com>2012-01-17 06:15:11 +0800
commite4a3c7801e0075a49674c79972394ad962b338f2 (patch)
treec8f2463b26574e3b07cd1d5fa1b02820575d34e1 /target-i386/hax-darwin.c
parenta381ef07088ce479610129e37bfef42538f397da (diff)
downloadexternal_qemu-e4a3c7801e0075a49674c79972394ad962b338f2.zip
external_qemu-e4a3c7801e0075a49674c79972394ad962b338f2.tar.gz
external_qemu-e4a3c7801e0075a49674c79972394ad962b338f2.tar.bz2
New files to add HAX support
QEMU emulator interacts with the HAX kernel module. A HAX (Hardware-based Accelerated eXecution) kernel module is required to use HAX support. Most guest instructions run in VMX non-root (i.e. in hardware) mode and achieve near-native (relative to the host) performance. QEMU still emulates PIO/MMIO instructions and non-PG (paging) mode operations. HAX is supported only on Mac OS X and Windows hosts when Intel VT is present. Change-Id: I8dd52a35e315437dc568f555742bb8ab7e9d8ab2 Signed-off-by: Zhang, Xiantao <xiantao.zhang@intel.com> Signed-off-by: Xin, Xiaohui <xiaohui.xin@intel.com> Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com> Signed-off-by: Nakajima, Jun <jun.nakajima@intel.com>
Diffstat (limited to 'target-i386/hax-darwin.c')
-rw-r--r--target-i386/hax-darwin.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/target-i386/hax-darwin.c b/target-i386/hax-darwin.c
new file mode 100644
index 0000000..b6d27c3
--- /dev/null
+++ b/target-i386/hax-darwin.c
@@ -0,0 +1,290 @@
+/*
+** Copyright (c) 2011, Intel Corporation
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/* HAX module interface - darwin version */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include "target-i386/hax-i386.h"
+hax_fd hax_mod_open(void)
+{
+ int fd = open("/dev/HAX", O_RDWR);
+
+ if (fd == -1)
+ {
+ dprint("Failed to open the hax module\n");
+ return -errno;
+ }
+
+ return fd;
+}
+
+int hax_populate_ram(uint64_t va, uint32_t size)
+{
+ int ret;
+ struct hax_alloc_ram_info info;
+
+ if (!hax_global.vm || !hax_global.vm->fd)
+ {
+ dprint("Allocate memory before vm create?\n");
+ return -EINVAL;
+ }
+
+ info.size = size;
+ info.va = va;
+ ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
+ if (ret < 0)
+ {
+ dprint("Failed to allocate %x memory\n", size);
+ return ret;
+ }
+ return 0;
+}
+
+int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset)
+{
+ struct hax_set_ram_info info, *pinfo = &info;
+ int ret;
+ ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+
+ /* We look for the RAM and ROM only */
+ if (flags >= IO_MEM_UNASSIGNED)
+ return 0;
+
+ if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK))
+ {
+ dprint("set_phys_mem %x %lx requires page aligned addr and size\n", start_addr, size);
+ exit(1);
+ return -1;
+ }
+
+ info.pa_start = start_addr;
+ info.size = size;
+ info.va = (uint64_t)qemu_get_ram_ptr(phys_offset);
+ info.flags = (flags & IO_MEM_ROM) ? 1 : 0;
+
+ ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, pinfo);
+ if (ret < 0)
+ {
+ dprint("has set phys mem failed\n");
+ exit(1);
+ }
+ return ret;
+}
+
+int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
+{
+ int ret;
+
+ ret = ioctl(hax->fd, HAX_IOCTL_VERSION, version);
+ if (ret == -1)
+ {
+ dprint("Failed to get HAX version\n");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static char *hax_vm_devfs_string(int vm_id)
+{
+ char *name;
+
+ if (vm_id > MAX_VM_ID)
+ {
+ dprint("Too big VM id\n");
+ return NULL;
+ }
+
+ name = qemu_strdup("/dev/hax_vm/vmxx");
+ if (!name)
+ return NULL;
+ sprintf(name, "/dev/hax_vm/vm%02d", vm_id);
+
+ return name;
+}
+
+static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
+{
+ char *name;
+
+ if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID)
+ {
+ dprint("Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
+ return NULL;
+ }
+
+ name = qemu_strdup("/dev/hax_vmxx/vcpuyy");
+ if (!name)
+ return NULL;
+
+ sprintf(name, "/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id);
+
+ return name;
+}
+
+int hax_host_create_vm(struct hax_state *hax, int vm_id)
+{
+ int ret;
+
+ if (hax_invalid_fd(hax->fd))
+ return -EINVAL;
+
+ if (hax->vm)
+ return 0;
+
+ ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
+
+ return ret;
+}
+
+hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
+{
+ hax_fd fd;
+ char *vm_name = NULL;
+
+ vm_name = hax_vm_devfs_string(vm_id);
+ if (!vm_name)
+ return -1;
+
+ fd = open(vm_name, O_RDWR);
+ qemu_free(vm_name);
+
+ return fd;
+}
+
+/*
+ * Simply assume that the size should be bigger than the hax_tunnel,
+ * since the hax_tunnel can be extended later with backward
+ * compatibility.
+ */
+int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
+{
+ int ret;
+
+ ret = ioctl(vm_fd, HAX_VM_IOCTL_VCPU_CREATE, &vcpuid);
+ if (ret < 0)
+ dprint("Failed to create vcpu %x\n", vcpuid);
+
+ return ret;
+}
+
+hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
+{
+ char *devfs_path = NULL;
+ hax_fd fd;
+
+ devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
+ if (!devfs_path)
+ {
+ dprint("Failed to get the devfs\n");
+ return -EINVAL;
+ }
+
+ fd = open(devfs_path, O_RDWR);
+ qemu_free(devfs_path);
+ if (fd < 0)
+ dprint("Failed to open the vcpu devfs\n");
+ return fd;
+}
+
+int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
+{
+ int ret;
+ struct hax_tunnel_info info;
+
+ ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_SETUP_TUNNEL, &info);
+ if (ret)
+ {
+ dprint("Failed to setup the hax tunnel\n");
+ return ret;
+ }
+
+ if (!valid_hax_tunnel_size(info.size))
+ {
+ dprint("Invalid hax tunnel size %x\n", info.size);
+ ret = -EINVAL;
+ return ret;
+ }
+
+ vcpu->tunnel = (struct hax_tunnel *)(info.va);
+ vcpu->iobuf = (unsigned char *)(info.io_va);
+ return 0;
+}
+
+int hax_vcpu_run(struct hax_vcpu_state* vcpu)
+{
+ int ret;
+
+ ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
+ return ret;
+}
+
+int hax_sync_fpu(CPUState *env, struct fx_layout *fl, int set)
+{
+ int ret, fd;
+
+ fd = hax_vcpu_get_fd(env);
+ if (fd <= 0)
+ return -1;
+
+ if (set)
+ ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
+ else
+ ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
+ return ret;
+}
+
+int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set)
+{
+ int ret, fd;
+
+ fd = hax_vcpu_get_fd(env);
+ if (fd <= 0)
+ return -1;
+ if (set)
+ ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
+ else
+ ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
+ return ret;
+}
+
+int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set)
+{
+ int ret, fd;
+
+ fd = hax_vcpu_get_fd(env);
+ if (fd <= 0)
+ return -1;
+
+ if (set)
+ ret = ioctl(fd, HAX_VCPU_SET_REGS, state);
+ else
+ ret = ioctl(fd, HAX_VCPU_GET_REGS, state);
+ return ret;
+}
+
+int hax_inject_interrupt(CPUState *env, int vector)
+{
+ int ret, fd;
+
+ fd = hax_vcpu_get_fd(env);
+ if (fd <= 0)
+ return -1;
+
+ ret = ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
+ return ret;
+}