Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.12-pull-request...
[qemu/ar7.git] / target / i386 / hax-darwin.c
blobacdde476a0585ab895cb85e4987983abf0484b58
1 /*
2 * QEMU HAXM support
4 * Copyright (c) 2011 Intel Corporation
5 * Written by:
6 * Jiang Yunhong<yunhong.jiang@intel.com>
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.
13 /* HAX module interface - darwin version */
14 #include "qemu/osdep.h"
15 #include <sys/ioctl.h>
17 #include "target/i386/hax-i386.h"
19 hax_fd hax_mod_open(void)
21 int fd = open("/dev/HAX", O_RDWR);
22 if (fd == -1) {
23 fprintf(stderr, "Failed to open the hax module\n");
26 fcntl(fd, F_SETFD, FD_CLOEXEC);
28 return fd;
31 int hax_populate_ram(uint64_t va, uint64_t size)
33 int ret;
35 if (!hax_global.vm || !hax_global.vm->fd) {
36 fprintf(stderr, "Allocate memory before vm create?\n");
37 return -EINVAL;
40 if (hax_global.supports_64bit_ramblock) {
41 struct hax_ramblock_info ramblock = {
42 .start_va = va,
43 .size = size,
44 .reserved = 0
47 ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ADD_RAMBLOCK, &ramblock);
48 } else {
49 struct hax_alloc_ram_info info = {
50 .size = (uint32_t)size,
51 .pad = 0,
52 .va = va
55 ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
57 if (ret < 0) {
58 fprintf(stderr, "Failed to register RAM block: ret=%d, va=0x%" PRIx64
59 ", size=0x%" PRIx64 ", method=%s\n", ret, va, size,
60 hax_global.supports_64bit_ramblock ? "new" : "legacy");
61 return ret;
63 return 0;
66 int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
68 struct hax_set_ram_info info;
69 int ret;
71 info.pa_start = start_pa;
72 info.size = size;
73 info.va = host_va;
74 info.flags = (uint8_t) flags;
76 ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, &info);
77 if (ret < 0) {
78 return -errno;
80 return 0;
83 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
85 int ret;
87 ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap);
88 if (ret == -1) {
89 fprintf(stderr, "Failed to get HAX capability\n");
90 return -errno;
93 return 0;
96 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
98 int ret;
100 ret = ioctl(hax->fd, HAX_IOCTL_VERSION, version);
101 if (ret == -1) {
102 fprintf(stderr, "Failed to get HAX version\n");
103 return -errno;
106 return 0;
109 static char *hax_vm_devfs_string(int vm_id)
111 char *name;
113 if (vm_id > MAX_VM_ID) {
114 fprintf(stderr, "Too big VM id\n");
115 return NULL;
118 #define HAX_VM_DEVFS "/dev/hax_vm/vmxx"
119 name = g_strdup(HAX_VM_DEVFS);
120 if (!name) {
121 return NULL;
124 snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id);
125 return name;
128 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
130 char *name;
132 if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
133 fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
134 return NULL;
137 #define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx"
138 name = g_strdup(HAX_VCPU_DEVFS);
139 if (!name) {
140 return NULL;
143 snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d",
144 vm_id, vcpu_id);
145 return name;
148 int hax_host_create_vm(struct hax_state *hax, int *vmid)
150 int ret;
151 int vm_id = 0;
153 if (hax_invalid_fd(hax->fd)) {
154 return -EINVAL;
157 if (hax->vm) {
158 return 0;
161 ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
162 *vmid = vm_id;
163 return ret;
166 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
168 hax_fd fd;
169 char *vm_name = NULL;
171 vm_name = hax_vm_devfs_string(vm_id);
172 if (!vm_name) {
173 return -1;
176 fd = open(vm_name, O_RDWR);
177 g_free(vm_name);
179 fcntl(fd, F_SETFD, FD_CLOEXEC);
181 return fd;
184 int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
186 int ret;
188 if (hax_invalid_fd(vm_fd)) {
189 return -EINVAL;
192 ret = ioctl(vm_fd, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, qversion);
194 if (ret < 0) {
195 fprintf(stderr, "Failed to notify qemu API version\n");
196 return ret;
198 return 0;
201 /* Simply assume the size should be bigger than the hax_tunnel,
202 * since the hax_tunnel can be extended later with compatibility considered
204 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
206 int ret;
208 ret = ioctl(vm_fd, HAX_VM_IOCTL_VCPU_CREATE, &vcpuid);
209 if (ret < 0) {
210 fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
213 return ret;
216 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
218 char *devfs_path = NULL;
219 hax_fd fd;
221 devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
222 if (!devfs_path) {
223 fprintf(stderr, "Failed to get the devfs\n");
224 return -EINVAL;
227 fd = open(devfs_path, O_RDWR);
228 g_free(devfs_path);
229 if (fd < 0) {
230 fprintf(stderr, "Failed to open the vcpu devfs\n");
232 fcntl(fd, F_SETFD, FD_CLOEXEC);
233 return fd;
236 int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
238 int ret;
239 struct hax_tunnel_info info;
241 ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_SETUP_TUNNEL, &info);
242 if (ret) {
243 fprintf(stderr, "Failed to setup the hax tunnel\n");
244 return ret;
247 if (!valid_hax_tunnel_size(info.size)) {
248 fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
249 ret = -EINVAL;
250 return ret;
253 vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
254 vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
255 return 0;
258 int hax_vcpu_run(struct hax_vcpu_state *vcpu)
260 int ret;
262 ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
263 return ret;
266 int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
268 int ret, fd;
270 fd = hax_vcpu_get_fd(env);
271 if (fd <= 0) {
272 return -1;
275 if (set) {
276 ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
277 } else {
278 ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
280 return ret;
283 int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
285 int ret, fd;
287 fd = hax_vcpu_get_fd(env);
288 if (fd <= 0) {
289 return -1;
291 if (set) {
292 ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
293 } else {
294 ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
296 return ret;
299 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
301 int ret, fd;
303 fd = hax_vcpu_get_fd(env);
304 if (fd <= 0) {
305 return -1;
308 if (set) {
309 ret = ioctl(fd, HAX_VCPU_SET_REGS, state);
310 } else {
311 ret = ioctl(fd, HAX_VCPU_GET_REGS, state);
313 return ret;
316 int hax_inject_interrupt(CPUArchState *env, int vector)
318 int ret, fd;
320 fd = hax_vcpu_get_fd(env);
321 if (fd <= 0) {
322 return -1;
325 ret = ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
326 return ret;