1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "qemu/osdep.h"
15#include <sys/ioctl.h>
16
17#include "target/i386/hax-i386.h"
18
19hax_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
31int 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
66int 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
83int 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
96int 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
109static 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
128static 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
148int 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
166hax_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
184int 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
202
203
204int 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
216hax_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
236int 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
258int hax_vcpu_run(struct hax_vcpu_state *vcpu)
259{
260 int ret;
261
262 ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
263 return ret;
264}
265
266int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
267{
268 int ret, fd;
269
270 fd = hax_vcpu_get_fd(env);
271 if (fd <= 0) {
272 return -1;
273 }
274
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);
279 }
280 return ret;
281}
282
283int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
284{
285 int ret, fd;
286
287 fd = hax_vcpu_get_fd(env);
288 if (fd <= 0) {
289 return -1;
290 }
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);
295 }
296 return ret;
297}
298
299int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
300{
301 int ret, fd;
302
303 fd = hax_vcpu_get_fd(env);
304 if (fd <= 0) {
305 return -1;
306 }
307
308 if (set) {
309 ret = ioctl(fd, HAX_VCPU_SET_REGS, state);
310 } else {
311 ret = ioctl(fd, HAX_VCPU_GET_REGS, state);
312 }
313 return ret;
314}
315
316int hax_inject_interrupt(CPUArchState *env, int vector)
317{
318 int ret, fd;
319
320 fd = hax_vcpu_get_fd(env);
321 if (fd <= 0) {
322 return -1;
323 }
324
325 ret = ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
326 return ret;
327}
328