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/*
15 * HAX common code for both Windows and Darwin
16 * Some portion of code from KVM is used in this file.
17 */
18
19#include "target-i386/hax-i386.h"
20
21#define HAX_EMUL_ONE    0x1
22#define HAX_EMUL_REAL   0x2
23#define HAX_EMUL_HLT    0x4
24#define HAX_EMUL_EXITLOOP    0x5
25
26#define HAX_EMULATE_STATE_MMIO  0x1
27#define HAX_EMULATE_STATE_REAL  0x2
28#define HAX_EMULATE_STATE_NONE  0x3
29#define HAX_EMULATE_STATE_INITIAL       0x4
30
31struct hax_state hax_global;
32
33int hax_support = -1;
34
35/* Called after hax_init */
36int hax_enabled()
37{
38    return (!hax_disabled && hax_support);
39}
40
41/* Currently non-PG modes are emulated by QEMU */
42int hax_vcpu_emulation_mode(CPUState *env)
43{
44    return !(env->cr[0] & CR0_PG_MASK);
45}
46
47static int hax_prepare_emulation(CPUState *env)
48{
49    /* Flush all emulation states */
50    tlb_flush(env, 1);
51    tb_flush(env);
52    /* Sync the vcpu state from hax kernel module */
53    hax_vcpu_sync_state(env, 0);
54    return 0;
55}
56
57/*
58 * Check whether to break the translation block loop
59 * Break tbloop after one MMIO emulation, or after finish emulation mode
60 */
61static int hax_stop_tbloop(CPUState *env)
62{
63    switch (env->hax_vcpu->emulation_state)
64    {
65        case HAX_EMULATE_STATE_MMIO:
66            return 1;
67        case HAX_EMULATE_STATE_INITIAL:
68        case HAX_EMULATE_STATE_REAL:
69            if (!hax_vcpu_emulation_mode(env))
70                return 1;
71            break;
72        default:
73            dprint("Invalid emulation state in hax_sto_tbloop state %x\n",
74              env->hax_vcpu->emulation_state);
75            break;
76    }
77
78    return 0;
79}
80
81int hax_stop_emulation(CPUState *env)
82{
83    if (hax_stop_tbloop(env))
84    {
85        env->hax_vcpu->emulation_state =  HAX_EMULATE_STATE_NONE;
86        /*
87         * QEMU emulation changes vcpu state,
88         * Sync the vcpu state to HAX kernel module
89         */
90        hax_vcpu_sync_state(env, 1);
91        return 1;
92    }
93
94    return 0;
95}
96
97int hax_stop_translate(CPUState *env)
98{
99    struct hax_vcpu_state *vstate;
100
101    vstate = env->hax_vcpu;
102    assert(vstate->emulation_state);
103    if (vstate->emulation_state == HAX_EMULATE_STATE_MMIO )
104        return 1;
105
106    return 0;
107}
108
109int valid_hax_tunnel_size(uint16_t size)
110{
111    return size >= sizeof(struct hax_tunnel);
112}
113
114hax_fd hax_vcpu_get_fd(CPUState *env)
115{
116    struct hax_vcpu_state *vcpu = env->hax_vcpu;
117    if (!vcpu)
118        return HAX_INVALID_FD;
119    return vcpu->fd;
120}
121
122/* Current version */
123uint32_t hax_cur_version = 0x2;
124/* Least HAX kernel version */
125uint32_t hax_lest_version = 0x1;
126
127static int hax_get_capability(struct hax_state *hax)
128{
129    int ret;
130    struct hax_capabilityinfo capinfo, *cap = &capinfo;
131
132    ret = hax_capability(hax, cap);
133    if (ret)
134        return -ENOSYS;
135
136    if ( ((cap->wstatus & HAX_CAP_WORKSTATUS_MASK) ==
137          HAX_CAP_STATUS_NOTWORKING ))
138    {
139        if (cap->winfo & HAX_CAP_FAILREASON_VT)
140            dprint("VT feature is not enabled, HAXM not working.\n");
141        else if (cap->winfo & HAX_CAP_FAILREASON_NX)
142            dprint("NX feature is not enabled, HAXM not working.\n");
143        return -ENXIO;
144    }
145
146    if (cap->wstatus & HAX_CAP_MEMQUOTA)
147    {
148        if (cap->mem_quota < hax->mem_quota)
149        {
150            dprint("The memory needed by this VM exceeds the driver limit.\n");
151            return -ENOSPC;
152        }
153    }
154
155    return 0;
156}
157
158static int hax_version_support(struct hax_state *hax)
159{
160    int ret;
161    struct hax_module_version version;
162
163    ret = hax_mod_version(hax, &version);
164    if (ret < 0)
165        return 0;
166
167    if ( (hax_lest_version > version.cur_version) ||
168         (hax_cur_version < version.compat_version) )
169        return 0;
170
171    return 1;
172}
173
174int hax_vcpu_create(int id)
175{
176    struct hax_vcpu_state *vcpu = NULL;
177    int ret;
178
179    if (!hax_global.vm)
180    {
181        dprint("vcpu %x created failed, vm is null\n", id);
182        return -1;
183    }
184
185    if (hax_global.vm->vcpus[id])
186    {
187        dprint("vcpu %x allocated already\n", id);
188        return 0;
189    }
190
191    vcpu = qemu_malloc(sizeof(struct hax_vcpu_state));
192    if (!vcpu)
193    {
194        dprint("Failed to alloc vcpu state\n");
195        return -ENOMEM;
196    }
197
198    memset(vcpu, 0, sizeof(struct hax_vcpu_state));
199
200    ret = hax_host_create_vcpu(hax_global.vm->fd, id);
201    if (ret)
202    {
203        dprint("Failed to create vcpu %x\n", id);
204        goto error;
205    }
206
207    vcpu->fd = hax_host_open_vcpu(hax_global.vm->id, id);
208    if (hax_invalid_fd(vcpu->fd))
209    {
210        dprint("Failed to open the vcpu\n");
211        ret = -ENODEV;
212        goto error;
213    }
214
215    hax_global.vm->vcpus[id] = vcpu;
216
217    ret = hax_host_setup_vcpu_channel(vcpu);
218    if (ret)
219    {
220        dprint("Invalid HAX tunnel size \n");
221        ret = -EINVAL;
222        goto error;
223    }
224    return 0;
225
226error:
227    /* vcpu and tunnel will be closed automatically */
228    if (vcpu && !hax_invalid_fd(vcpu->fd))
229        hax_close_fd(vcpu->fd);
230
231    hax_global.vm->vcpus[id] = NULL;
232    qemu_free(vcpu);
233    return -1;
234}
235
236int hax_vcpu_destroy(CPUState *env)
237{
238    struct hax_vcpu_state *vcpu = env->hax_vcpu;
239
240    if (!hax_global.vm)
241    {
242        dprint("vcpu %x destroy failed, vm is null\n", vcpu->vcpu_id);
243        return -1;
244    }
245
246    if (!vcpu)
247        return 0;
248
249    /*
250     * 1. The hax_tunnel is also destroyed at vcpu_destroy
251     * 2. hax_close_fd will require the HAX kernel module to free vcpu
252     */
253    hax_close_fd(vcpu->fd);
254    hax_global.vm->vcpus[vcpu->vcpu_id] = NULL;
255    qemu_free(vcpu);
256    return 0;
257}
258
259int hax_init_vcpu(CPUState *env)
260{
261    int ret;
262
263    ret = hax_vcpu_create(env->cpu_index);
264    if (ret < 0)
265    {
266        dprint("Failed to create HAX vcpu\n");
267        exit(-1);
268    }
269
270    env->hax_vcpu = hax_global.vm->vcpus[env->cpu_index];
271    env->hax_vcpu->emulation_state = HAX_EMULATE_STATE_INITIAL;
272
273    return ret;
274}
275
276struct hax_vm *hax_vm_create(struct hax_state *hax)
277{
278    struct hax_vm *vm;
279    int vm_id = 0, ret;
280    char *vm_name = NULL;
281
282    if (hax_invalid_fd(hax->fd))
283        return NULL;
284
285    if (hax->vm)
286        return hax->vm;
287
288    vm = qemu_malloc(sizeof(struct hax_vm));
289    if (!vm)
290        return NULL;
291    memset(vm, 0, sizeof(struct hax_vm));
292    ret = hax_host_create_vm(hax, &vm_id);
293    if (ret) {
294        dprint("Failed to create vm %x\n", ret);
295        goto error;
296    }
297    vm->id = vm_id;
298    vm->fd = hax_host_open_vm(hax, vm_id);
299    if (hax_invalid_fd(vm->fd))
300    {
301        dprint("Open vm device error:%s\n", vm_name);
302        goto error;
303    }
304
305    hax->vm = vm;
306    return vm;
307
308error:
309    qemu_free(vm);
310    hax->vm = NULL;
311    return NULL;
312}
313
314int hax_vm_destroy(struct hax_vm *vm)
315{
316    int i;
317
318    for (i = 0; i < HAX_MAX_VCPU; i++)
319        if (vm->vcpus[i])
320        {
321            dprint("VCPU should be cleaned before vm clean\n");
322            return -1;
323        }
324    hax_close_fd(vm->fd);
325    qemu_free(vm);
326    hax_global.vm = NULL;
327    return 0;
328}
329
330int hax_set_ramsize(uint64_t ramsize)
331{
332    struct hax_state *hax = &hax_global;
333
334    memset(hax, 0, sizeof(struct hax_state));
335    hax->mem_quota = ram_size;
336
337    return 0;
338}
339
340int hax_init(int smp_cpus)
341{
342    struct hax_state *hax = NULL;
343    struct hax_qemu_version qversion;
344    int ret;
345
346    hax_support = 0;
347
348    hax = &hax_global;
349
350    hax->fd = hax_mod_open();
351    if (hax_invalid_fd(hax->fd))
352    {
353        hax->fd = 0;
354        ret = -ENODEV;
355        goto error;
356    }
357
358    ret = hax_get_capability(hax);
359    /* In case HAXM have no such capability support */
360    if (ret && (ret != -ENOSYS))
361    {
362        ret = -EINVAL;
363        goto error;
364    }
365
366    if (!hax_version_support(hax))
367    {
368        dprint("Incompatible HAX version. Qemu current version %x ", hax_cur_version );
369        dprint("requires least HAX version %x\n", hax_lest_version);
370        ret = -EINVAL;
371        goto error;
372    }
373
374    hax->vm = hax_vm_create(hax);
375    if (!hax->vm)
376    {
377        dprint("Failed to create HAX VM\n");
378        ret = -EINVAL;
379        goto error;
380    }
381
382    qversion.cur_version = hax_cur_version;
383    qversion.least_version = hax_lest_version;
384    hax_notify_qemu_version(hax->vm->fd, &qversion);
385    hax_support = 1;
386    qemu_register_reset( hax_reset_vcpu_state, 0, NULL);
387
388    return 0;
389error:
390    if (hax->vm)
391        hax_vm_destroy(hax->vm);
392    if (hax->fd)
393        hax_mod_close(hax);
394
395    return ret;
396}
397
398int  hax_handle_fastmmio(CPUState *env, struct hax_fastmmio *hft)
399{
400    uint64_t buf = 0;
401
402    /*
403     * With fast MMIO, QEMU need not sync vCPU state with HAXM
404     * driver because it will only invoke MMIO handler
405     * However, some MMIO operations utilize virtual address like qemu_pipe
406     * Thus we need to sync the CR0, CR3 and CR4 so that QEMU
407     * can translate the guest virtual address to guest physical
408     * address
409     */
410    env->cr[0] = hft->_cr0;
411    env->cr[2] = hft->_cr2;
412    env->cr[3] = hft->_cr3;
413    env->cr[4] = hft->_cr4;
414
415    buf = hft->value;
416    cpu_physical_memory_rw(hft->gpa, &buf, hft->size, hft->direction);
417    if (hft->direction == 0)
418        hft->value = buf;
419
420    return 0;
421}
422
423int hax_handle_io(CPUState *env, uint32_t df, uint16_t port, int direction,
424  int size, int count, void *buffer)
425{
426    uint8_t *ptr;
427    int i;
428
429    if (!df)
430        ptr = (uint8_t *)buffer;
431    else
432        ptr = buffer + size * count - size;
433    for (i = 0; i < count; i++)
434    {
435        if (direction == HAX_EXIT_IO_IN) {
436            switch (size) {
437                case 1:
438                    stb_p(ptr, cpu_inb(port));
439                    break;
440                case 2:
441                    stw_p(ptr, cpu_inw(port));
442                    break;
443                case 4:
444                    stl_p(ptr, cpu_inl(port));
445                    break;
446            }
447        } else {
448            switch (size) {
449                case 1:
450                    cpu_outb(port, ldub_p(ptr));
451                    break;
452                case 2:
453                    cpu_outw(port, lduw_p(ptr));
454                    break;
455                case 4:
456                    cpu_outl(port, ldl_p(ptr));
457                    break;
458            }
459        }
460        if (!df)
461            ptr += size;
462        else
463            ptr -= size;
464    }
465
466    return 0;
467}
468
469static int hax_vcpu_interrupt(CPUState *env)
470{
471    struct hax_vcpu_state *vcpu = env->hax_vcpu;
472    struct hax_tunnel *ht = vcpu->tunnel;
473
474    /*
475     * Try to inject an interrupt if the guest can accept it
476     * Unlike KVM, the HAX kernel module checks the eflags, instead.
477     */
478    if (ht->ready_for_interrupt_injection &&
479      (env->interrupt_request & CPU_INTERRUPT_HARD))
480    {
481        int irq;
482
483        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
484        irq = cpu_get_pic_interrupt(env);
485        if (irq >= 0) {
486            hax_inject_interrupt(env, irq);
487        }
488    }
489
490    /*
491     * If we have an interrupt pending but the guest is not ready to
492     * receive it, request an interrupt window exit.  This will cause
493     * a return to userspace as soon as the guest is ready to receive
494     * an interrupt.
495     */
496    if ((env->interrupt_request & CPU_INTERRUPT_HARD))
497        ht->request_interrupt_window = 1;
498    else
499        ht->request_interrupt_window = 0;
500    return 0;
501}
502
503void hax_raise_event(CPUState *env)
504{
505    struct hax_vcpu_state *vcpu = env->hax_vcpu;
506
507    if (!vcpu)
508        return;
509    vcpu->tunnel->user_event_pending = 1;
510}
511
512/*
513 * Request the HAX kernel module to run the CPU for us until one of
514 * the following occurs:
515 * 1. Guest crashes or is shut down
516 * 2. We need QEMU's emulation like when the guest executes a MMIO
517 *    instruction or guest enters emulation mode (non-PG mode)
518 * 3. Guest executes HLT
519 * 4. Qemu has Signal/event pending
520 * 5. An unknown VMX-exit happens
521 */
522extern void qemu_system_reset_request(void);
523static int hax_vcpu_hax_exec(CPUState *env)
524{
525    int ret = 0;
526    struct hax_vcpu_state *vcpu = env->hax_vcpu;
527    struct hax_tunnel *ht = vcpu->tunnel;
528
529    if (hax_vcpu_emulation_mode(env))
530    {
531        dprint("Trying to vcpu execute at eip:%lx\n", env->eip);
532        return  HAX_EMUL_EXITLOOP;
533    }
534
535    do {
536        int hax_ret;
537
538        if (env->exit_request) {
539            ret = HAX_EMUL_EXITLOOP ;
540            break;
541        }
542
543        hax_vcpu_interrupt(env);
544
545        hax_ret = hax_vcpu_run(vcpu);
546
547        /* Simply continue the vcpu_run if system call interrupted */
548        if (hax_ret == -EINTR || hax_ret == -EAGAIN) {
549            dprint("io window interrupted\n");
550            continue;
551        }
552
553        if (hax_ret < 0)
554        {
555            dprint("vcpu run failed for vcpu  %x\n", vcpu->vcpu_id);
556            abort();
557        }
558        switch (ht->_exit_status)
559        {
560            case HAX_EXIT_IO:
561                {
562                    ret = hax_handle_io(env, ht->pio._df, ht->pio._port,
563                      ht->pio._direction,
564                      ht->pio._size, ht->pio._count, vcpu->iobuf);
565                }
566                break;
567            case HAX_EXIT_MMIO:
568                ret = HAX_EMUL_ONE;
569                break;
570            case HAX_EXIT_FAST_MMIO:
571                ret = hax_handle_fastmmio(env,
572                        (struct hax_fastmmio *)vcpu->iobuf);
573                break;
574            case HAX_EXIT_REAL:
575                ret = HAX_EMUL_REAL;
576                break;
577                /* Guest state changed, currently only for shutdown */
578            case HAX_EXIT_STATECHANGE:
579                dprint("VCPU shutdown request\n");
580                qemu_system_reset_request();
581                hax_prepare_emulation(env);
582                cpu_dump_state(env, stderr, fprintf, 0);
583                ret = HAX_EMUL_EXITLOOP;
584                break;
585            case HAX_EXIT_UNKNOWN_VMEXIT:
586                dprint("Unknown VMX exit %x from guest\n", ht->_exit_reason);
587                qemu_system_reset_request();
588                hax_prepare_emulation(env);
589                cpu_dump_state(env, stderr, fprintf, 0);
590                ret = HAX_EMUL_EXITLOOP;
591                break;
592            case HAX_EXIT_HLT:
593                if (!(env->interrupt_request & CPU_INTERRUPT_HARD) &&
594                  !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
595                    /* hlt instruction with interrupt disabled is shutdown */
596                    env->eflags |= IF_MASK;
597                    env->halted = 1;
598                    env->exception_index = EXCP_HLT;
599                    ret = HAX_EMUL_HLT;
600                }
601                break;
602                /* these situation will continue to hax module */
603            case HAX_EXIT_INTERRUPT:
604            case HAX_EXIT_PAUSED:
605                break;
606            default:
607                dprint("Unknow exit %x from hax\n", ht->_exit_status);
608                qemu_system_reset_request();
609                hax_prepare_emulation(env);
610                cpu_dump_state(env, stderr, fprintf, 0);
611                ret = HAX_EMUL_EXITLOOP;
612                break;
613        }
614    }while (!ret);
615
616    if (env->exit_request) {
617        env->exit_request = 0;
618        env->exception_index = EXCP_INTERRUPT;
619    }
620    return ret;
621}
622
623/*
624 * return 1 when need to emulate, 0 when need to exit loop
625 */
626int hax_vcpu_exec(CPUState *env)
627{
628    int next = 0, ret = 0;
629    struct hax_vcpu_state *vcpu;
630
631    if (env->hax_vcpu->emulation_state != HAX_EMULATE_STATE_NONE)
632        return 1;
633
634    vcpu = env->hax_vcpu;
635    next = hax_vcpu_hax_exec(env);
636    switch (next)
637    {
638        case HAX_EMUL_ONE:
639            ret = 1;
640            env->hax_vcpu->emulation_state = HAX_EMULATE_STATE_MMIO;
641            hax_prepare_emulation(env);
642            break;
643        case HAX_EMUL_REAL:
644            ret = 1;
645            env->hax_vcpu->emulation_state =
646              HAX_EMULATE_STATE_REAL;
647            hax_prepare_emulation(env);
648            break;
649        case HAX_EMUL_HLT:
650        case HAX_EMUL_EXITLOOP:
651            break;
652        default:
653            dprint("Unknown hax vcpu exec return %x\n", next);
654            abort();
655    }
656
657    return ret;
658}
659
660#define HAX_RAM_INFO_ROM 0x1
661
662static void set_v8086_seg(struct segment_desc_t *lhs, const SegmentCache *rhs)
663{
664    memset(lhs, 0, sizeof(struct segment_desc_t ));
665    lhs->selector = rhs->selector;
666    lhs->base = rhs->base;
667    lhs->limit = rhs->limit;
668    lhs->type = 3;
669    lhs->present = 1;
670    lhs->dpl = 3;
671    lhs->operand_size = 0;
672    lhs->desc = 1;
673    lhs->long_mode = 0;
674    lhs->granularity = 0;
675    lhs->available = 0;
676}
677
678static void get_seg(SegmentCache *lhs, const struct segment_desc_t *rhs)
679{
680    lhs->selector = rhs->selector;
681    lhs->base = rhs->base;
682    lhs->limit = rhs->limit;
683    lhs->flags =
684      (rhs->type << DESC_TYPE_SHIFT)
685      | (rhs->present * DESC_P_MASK)
686      | (rhs->dpl << DESC_DPL_SHIFT)
687      | (rhs->operand_size << DESC_B_SHIFT)
688      | (rhs->desc * DESC_S_MASK)
689      | (rhs->long_mode << DESC_L_SHIFT)
690      | (rhs->granularity * DESC_G_MASK)
691      | (rhs->available * DESC_AVL_MASK);
692}
693
694static void set_seg(struct segment_desc_t *lhs, const SegmentCache *rhs)
695{
696    unsigned flags = rhs->flags;
697
698    memset(lhs, 0, sizeof(struct segment_desc_t));
699    lhs->selector = rhs->selector;
700    lhs->base = rhs->base;
701    lhs->limit = rhs->limit;
702    lhs->type = (flags >> DESC_TYPE_SHIFT) & 15;
703    lhs->present = (flags & DESC_P_MASK) != 0;
704    lhs->dpl = rhs->selector & 3;
705    lhs->operand_size = (flags >> DESC_B_SHIFT) & 1;
706    lhs->desc = (flags & DESC_S_MASK) != 0;
707    lhs->long_mode = (flags >> DESC_L_SHIFT) & 1;
708    lhs->granularity = (flags & DESC_G_MASK) != 0;
709    lhs->available = (flags & DESC_AVL_MASK) != 0;
710}
711
712static void hax_getput_reg(uint64_t *hax_reg, target_ulong *qemu_reg, int set)
713{
714    target_ulong reg = *hax_reg;
715
716    if (set)
717        *hax_reg = *qemu_reg;
718    else
719        *qemu_reg = reg;
720}
721
722/* The sregs has been synced with HAX kernel already before this call */
723static int hax_get_segments(CPUState *env, struct vcpu_state_t *sregs)
724{
725    get_seg(&env->segs[R_CS], &sregs->_cs);
726    get_seg(&env->segs[R_DS], &sregs->_ds);
727    get_seg(&env->segs[R_ES], &sregs->_es);
728    get_seg(&env->segs[R_FS], &sregs->_fs);
729    get_seg(&env->segs[R_GS], &sregs->_gs);
730    get_seg(&env->segs[R_SS], &sregs->_ss);
731
732    get_seg(&env->tr, &sregs->_tr);
733    get_seg(&env->ldt, &sregs->_ldt);
734    env->idt.limit = sregs->_idt.limit;
735    env->idt.base = sregs->_idt.base;
736    env->gdt.limit = sregs->_gdt.limit;
737    env->gdt.base = sregs->_gdt.base;
738    return 0;
739}
740
741static int hax_set_segments(CPUState *env, struct vcpu_state_t *sregs)
742{
743    if ((env->eflags & VM_MASK)) {
744        set_v8086_seg(&sregs->_cs, &env->segs[R_CS]);
745        set_v8086_seg(&sregs->_ds, &env->segs[R_DS]);
746        set_v8086_seg(&sregs->_es, &env->segs[R_ES]);
747        set_v8086_seg(&sregs->_fs, &env->segs[R_FS]);
748        set_v8086_seg(&sregs->_gs, &env->segs[R_GS]);
749        set_v8086_seg(&sregs->_ss, &env->segs[R_SS]);
750    } else {
751        set_seg(&sregs->_cs, &env->segs[R_CS]);
752        set_seg(&sregs->_ds, &env->segs[R_DS]);
753        set_seg(&sregs->_es, &env->segs[R_ES]);
754        set_seg(&sregs->_fs, &env->segs[R_FS]);
755        set_seg(&sregs->_gs, &env->segs[R_GS]);
756        set_seg(&sregs->_ss, &env->segs[R_SS]);
757
758        if (env->cr[0] & CR0_PE_MASK) {
759            /* force ss cpl to cs cpl */
760            sregs->_ss.selector = (sregs->_ss.selector & ~3) |
761              (sregs->_cs.selector & 3);
762            sregs->_ss.dpl = sregs->_ss.selector & 3;
763        }
764    }
765
766    set_seg(&sregs->_tr, &env->tr);
767    set_seg(&sregs->_ldt, &env->ldt);
768    sregs->_idt.limit = env->idt.limit;
769    sregs->_idt.base = env->idt.base;
770    sregs->_gdt.limit = env->gdt.limit;
771    sregs->_gdt.base = env->gdt.base;
772    return 0;
773}
774
775/*
776 * After get the state from the kernel module, some
777 * qemu emulator state need be updated also
778 */
779static int hax_setup_qemu_emulator(CPUState *env)
780{
781
782#define HFLAG_COPY_MASK ~( \
783  HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
784  HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
785  HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
786  HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
787
788    uint32_t hflags;
789
790    hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
791    hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
792    hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
793      (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
794    hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
795    hflags |= (env->cr[4] & CR4_OSFXSR_MASK) <<
796      (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
797
798    if (env->efer & MSR_EFER_LMA) {
799        hflags |= HF_LMA_MASK;
800    }
801
802    if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
803        hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
804    } else {
805        hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
806          (DESC_B_SHIFT - HF_CS32_SHIFT);
807        hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
808          (DESC_B_SHIFT - HF_SS32_SHIFT);
809        if (!(env->cr[0] & CR0_PE_MASK) ||
810          (env->eflags & VM_MASK) ||
811          !(hflags & HF_CS32_MASK)) {
812            hflags |= HF_ADDSEG_MASK;
813        } else {
814            hflags |= ((env->segs[R_DS].base |
815                  env->segs[R_ES].base |
816                  env->segs[R_SS].base) != 0) <<
817              HF_ADDSEG_SHIFT;
818        }
819    }
820    env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
821    return 0;
822}
823
824static int hax_sync_vcpu_register(CPUState *env, int set)
825{
826    struct vcpu_state_t regs;
827    int ret;
828    memset(&regs, 0, sizeof(struct vcpu_state_t));
829
830    if (!set)
831    {
832        ret = hax_sync_vcpu_state(env, &regs, 0);
833        if (ret < 0)
834            return -1;
835    }
836
837    /*generic register */
838    hax_getput_reg(&regs._rax, &env->regs[R_EAX], set);
839    hax_getput_reg(&regs._rbx, &env->regs[R_EBX], set);
840    hax_getput_reg(&regs._rcx, &env->regs[R_ECX], set);
841    hax_getput_reg(&regs._rdx, &env->regs[R_EDX], set);
842    hax_getput_reg(&regs._rsi, &env->regs[R_ESI], set);
843    hax_getput_reg(&regs._rdi, &env->regs[R_EDI], set);
844    hax_getput_reg(&regs._rsp, &env->regs[R_ESP], set);
845    hax_getput_reg(&regs._rbp, &env->regs[R_EBP], set);
846
847    hax_getput_reg(&regs._rflags, &env->eflags, set);
848    hax_getput_reg(&regs._rip, &env->eip, set);
849
850    if (set)
851    {
852
853        regs._cr0 = env->cr[0];
854        regs._cr2 = env->cr[2];
855        regs._cr3 = env->cr[3];
856        regs._cr4 = env->cr[4];
857        hax_set_segments(env, &regs);
858    }
859    else
860    {
861        env->cr[0] = regs._cr0;
862        env->cr[2] = regs._cr2;
863        env->cr[3] = regs._cr3;
864        env->cr[4] = regs._cr4;
865        hax_get_segments(env, &regs);
866    }
867
868    if (set)
869    {
870        ret = hax_sync_vcpu_state(env, &regs, 1);
871        if (ret < 0)
872            return -1;
873    }
874    if (!set)
875        hax_setup_qemu_emulator(env);
876    return 0;
877}
878
879static void hax_msr_entry_set(struct vmx_msr *item,
880  uint32_t index, uint64_t value)
881{
882    item->entry = index;
883    item->value = value;
884}
885
886static int hax_get_msrs(CPUState *env)
887{
888    struct hax_msr_data md;
889    struct vmx_msr *msrs = md.entries;
890    int ret, i, n;
891
892    n = 0;
893    msrs[n++].entry = MSR_IA32_SYSENTER_CS;
894    msrs[n++].entry = MSR_IA32_SYSENTER_ESP;
895    msrs[n++].entry = MSR_IA32_SYSENTER_EIP;
896    msrs[n++].entry = MSR_IA32_TSC;
897    md.nr_msr = n;
898    ret = hax_sync_msr(env, &md, 0);
899    if (ret < 0)
900        return ret;
901
902    for (i = 0; i < md.done; i++) {
903        switch (msrs[i].entry) {
904            case MSR_IA32_SYSENTER_CS:
905                env->sysenter_cs = msrs[i].value;
906                break;
907            case MSR_IA32_SYSENTER_ESP:
908                env->sysenter_esp = msrs[i].value;
909                break;
910            case MSR_IA32_SYSENTER_EIP:
911                env->sysenter_eip = msrs[i].value;
912                break;
913            case MSR_IA32_TSC:
914                env->tsc = msrs[i].value;
915                break;
916        }
917    }
918
919    return 0;
920}
921
922static int hax_set_msrs(CPUState *env)
923{
924    struct hax_msr_data md;
925    struct vmx_msr *msrs;
926    msrs = md.entries;
927    int n = 0;
928
929    memset(&md, 0, sizeof(struct hax_msr_data));
930    hax_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
931    hax_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
932    hax_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
933    hax_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
934    md.nr_msr = n;
935    md.done = 0;
936
937    return hax_sync_msr(env, &md, 1);
938
939}
940
941static int hax_get_fpu(CPUState *env)
942{
943    struct fx_layout fpu;
944    int i, ret;
945
946    ret = hax_sync_fpu(env, &fpu, 0);
947    if (ret < 0)
948        return ret;
949
950    env->fpstt = (fpu.fsw >> 11) & 7;
951    env->fpus = fpu.fsw;
952    env->fpuc = fpu.fcw;
953    for (i = 0; i < 8; ++i)
954        env->fptags[i] = !((fpu.ftw >> i) & 1);
955    memcpy(env->fpregs, fpu.st_mm, sizeof(env->fpregs));
956
957    memcpy(env->xmm_regs, fpu.mmx_1, sizeof(fpu.mmx_1));
958    memcpy((XMMReg *)(env->xmm_regs) + 8, fpu.mmx_2, sizeof(fpu.mmx_2));
959    env->mxcsr = fpu.mxcsr;
960
961    return 0;
962}
963
964static int hax_set_fpu(CPUState *env)
965{
966    struct fx_layout fpu;
967    int i;
968
969    memset(&fpu, 0, sizeof(fpu));
970    fpu.fsw = env->fpus & ~(7 << 11);
971    fpu.fsw |= (env->fpstt & 7) << 11;
972    fpu.fcw = env->fpuc;
973
974    for (i = 0; i < 8; ++i)
975        fpu.ftw |= (!env->fptags[i]) << i;
976
977    memcpy(fpu.st_mm, env->fpregs, sizeof (env->fpregs));
978    memcpy(fpu.mmx_1, env->xmm_regs, sizeof (fpu.mmx_1));
979    memcpy(fpu.mmx_2, (XMMReg *)(env->xmm_regs) + 8, sizeof (fpu.mmx_2));
980
981    fpu.mxcsr = env->mxcsr;
982
983    return hax_sync_fpu(env, &fpu, 1);
984}
985
986int hax_arch_get_registers(CPUState *env)
987{
988    int ret;
989
990    ret = hax_sync_vcpu_register(env, 0);
991    if (ret < 0)
992        return ret;
993
994    ret = hax_get_fpu(env);
995    if (ret < 0)
996        return ret;
997
998    ret = hax_get_msrs(env);
999    if (ret < 0)
1000        return ret;
1001
1002    return 0;
1003}
1004
1005static int hax_arch_set_registers(CPUState *env)
1006{
1007    int ret;
1008    ret = hax_sync_vcpu_register(env, 1);
1009
1010    if (ret < 0)
1011    {
1012        dprint("Failed to sync vcpu reg\n");
1013        return ret;
1014    }
1015    ret = hax_set_fpu(env);
1016    if (ret < 0)
1017    {
1018        dprint("FPU failed\n");
1019        return ret;
1020    }
1021    ret = hax_set_msrs(env);
1022    if (ret < 0)
1023    {
1024        dprint("MSR failed\n");
1025        return ret;
1026    }
1027
1028    return 0;
1029}
1030
1031void hax_vcpu_sync_state(CPUState *env, int modified)
1032{
1033    if (hax_enabled()) {
1034        if (modified)
1035            hax_arch_set_registers(env);
1036        else
1037            hax_arch_get_registers(env);
1038    }
1039}
1040
1041/*
1042 * This is simpler than the one for KVM because we don't support
1043 * direct I/O device assignment at this point.
1044 */
1045int hax_sync_vcpus(void)
1046{
1047    if (hax_enabled())
1048    {
1049        CPUState *env;
1050
1051        env = first_cpu;
1052        if (!env)
1053            return 0;
1054
1055        for (; env != NULL; env = env->next_cpu) {
1056            int ret;
1057
1058            ret = hax_arch_set_registers(env);
1059            if (ret < 0)
1060            {
1061                dprint("Failed to sync HAX vcpu context\n");
1062                exit(1);
1063            }
1064        }
1065    }
1066
1067    return 0;
1068}
1069
1070void hax_reset_vcpu_state(void *opaque)
1071{
1072    CPUState *env;
1073    for (env = first_cpu; env != NULL; env = env->next_cpu)
1074    {
1075        if (env->hax_vcpu)
1076        {
1077            env->hax_vcpu->emulation_state  = HAX_EMULATE_STATE_INITIAL;
1078            env->hax_vcpu->tunnel->user_event_pending = 0;
1079            env->hax_vcpu->tunnel->ready_for_interrupt_injection = 0;
1080        }
1081    }
1082}
1083