]> git.proxmox.com Git - mirror_qemu.git/blob - target/i386/hax-posix.c
i386: Update new x86_apicid parsing rules with die_offset support
[mirror_qemu.git] / target / i386 / hax-posix.c
1 /*
2 * QEMU HAXM support
3 *
4 * Copyright (c) 2011 Intel Corporation
5 * Written by:
6 * Jiang Yunhong<yunhong.jiang@intel.com>
7 *
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.
10 *
11 */
12
13 /* HAX module interface - darwin version */
14 #include "qemu/osdep.h"
15 #include <sys/ioctl.h>
16
17 #include "target/i386/hax-i386.h"
18
19 hax_fd hax_mod_open(void)
20 {
21 int fd = open("/dev/HAX", O_RDWR);
22 if (fd == -1) {
23 fprintf(stderr, "Failed to open the hax module\n");
24 }
25
26 fcntl(fd, F_SETFD, FD_CLOEXEC);
27
28 return fd;
29 }
30
31 int hax_populate_ram(uint64_t va, uint64_t size)
32 {
33 int ret;
34
35 if (!hax_global.vm || !hax_global.vm->fd) {
36 fprintf(stderr, "Allocate memory before vm create?\n");
37 return -EINVAL;
38 }
39
40 if (hax_global.supports_64bit_ramblock) {
41 struct hax_ramblock_info ramblock = {
42 .start_va = va,
43 .size = size,
44 .reserved = 0
45 };
46
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
53 };
54
55 ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
56 }
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;
62 }
63 return 0;
64 }
65
66 int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
67 {
68 struct hax_set_ram_info info;
69 int ret;
70
71 info.pa_start = start_pa;
72 info.size = size;
73 info.va = host_va;
74 info.flags = (uint8_t) flags;
75
76 ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, &info);
77 if (ret < 0) {
78 return -errno;
79 }
80 return 0;
81 }
82
83 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
84 {
85 int ret;
86
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;
91 }
92
93 return 0;
94 }
95
96 int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
97 {
98 int ret;
99
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;
104 }
105
106 return 0;
107 }
108
109 static char *hax_vm_devfs_string(int vm_id)
110 {
111 char *name;
112
113 if (vm_id > MAX_VM_ID) {
114 fprintf(stderr, "Too big VM id\n");
115 return NULL;
116 }
117
118 #define HAX_VM_DEVFS "/dev/hax_vm/vmxx"
119 name = g_strdup(HAX_VM_DEVFS);
120 if (!name) {
121 return NULL;
122 }
123
124 snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id);
125 return name;
126 }
127
128 static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
129 {
130 char *name;
131
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;
135 }
136
137 #define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx"
138 name = g_strdup(HAX_VCPU_DEVFS);
139 if (!name) {
140 return NULL;
141 }
142
143 snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d",
144 vm_id, vcpu_id);
145 return name;
146 }
147
148 int hax_host_create_vm(struct hax_state *hax, int *vmid)
149 {
150 int ret;
151 int vm_id = 0;
152
153 if (hax_invalid_fd(hax->fd)) {
154 return -EINVAL;
155 }
156
157 if (hax->vm) {
158 return 0;
159 }
160
161 ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
162 *vmid = vm_id;
163 return ret;
164 }
165
166 hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
167 {
168 hax_fd fd;
169 char *vm_name = NULL;
170
171 vm_name = hax_vm_devfs_string(vm_id);
172 if (!vm_name) {
173 return -1;
174 }
175
176 fd = open(vm_name, O_RDWR);
177 g_free(vm_name);
178
179 fcntl(fd, F_SETFD, FD_CLOEXEC);
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
192 ret = ioctl(vm_fd, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, qversion);
193
194 if (ret < 0) {
195 fprintf(stderr, "Failed to notify qemu API version\n");
196 return ret;
197 }
198 return 0;
199 }
200
201 /* Simply assume the size should be bigger than the hax_tunnel,
202 * since the hax_tunnel can be extended later with compatibility considered
203 */
204 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
205 {
206 int ret;
207
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);
211 }
212
213 return ret;
214 }
215
216 hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
217 {
218 char *devfs_path = NULL;
219 hax_fd fd;
220
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;
225 }
226
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");
231 }
232 fcntl(fd, F_SETFD, FD_CLOEXEC);
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 fprintf(stderr, "Failed to setup the hax tunnel\n");
244 return ret;
245 }
246
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;
251 }
252
253 vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
254 vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
255 return 0;
256 }
257
258 int hax_vcpu_run(struct hax_vcpu_state *vcpu)
259 {
260 return ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
261 }
262
263 int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
264 {
265 int ret, fd;
266
267 fd = hax_vcpu_get_fd(env);
268 if (fd <= 0) {
269 return -1;
270 }
271
272 if (set) {
273 ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
274 } else {
275 ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
276 }
277 return ret;
278 }
279
280 int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
281 {
282 int ret, fd;
283
284 fd = hax_vcpu_get_fd(env);
285 if (fd <= 0) {
286 return -1;
287 }
288 if (set) {
289 ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
290 } else {
291 ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
292 }
293 return ret;
294 }
295
296 int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
297 {
298 int ret, fd;
299
300 fd = hax_vcpu_get_fd(env);
301 if (fd <= 0) {
302 return -1;
303 }
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 }
310 return ret;
311 }
312
313 int hax_inject_interrupt(CPUArchState *env, int vector)
314 {
315 int fd;
316
317 fd = hax_vcpu_get_fd(env);
318 if (fd <= 0) {
319 return -1;
320 }
321
322 return ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
323 }