Beispiel #1
0
static void whpx_vcpu_process_async_events(CPUState *cpu)
{
    struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
    X86CPU *x86_cpu = X86_CPU(cpu);
    struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);

    if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
        !(env->hflags & HF_SMM_MASK)) {

        do_cpu_init(x86_cpu);
        cpu->vcpu_dirty = true;
        vcpu->interruptable = true;
    }

    if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
        apic_poll_irq(x86_cpu->apic_state);
    }

    if (((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->eflags & IF_MASK)) ||
        (cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
        cpu->halted = false;
    }

    if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) {
        if (!cpu->vcpu_dirty) {
            whpx_get_registers(cpu);
        }
        do_cpu_sipi(x86_cpu);
    }

    if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
        cpu->interrupt_request &= ~CPU_INTERRUPT_TPR;
        if (!cpu->vcpu_dirty) {
            whpx_get_registers(cpu);
        }
        apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip,
                                      env->tpr_access_type);
    }

    return;
}
Beispiel #2
0
/*
 * Ask hax kernel module to run the CPU for us till:
 * 1. Guest crash or shutdown
 * 2. Need QEMU's emulation like guest execute MMIO instruction
 * 3. Guest execute HLT
 * 4. QEMU have Signal/event pending
 * 5. An unknown VMX exit happens
 */
static int hax_vcpu_hax_exec(CPUArchState *env)
{
    int ret = 0;
    CPUState *cpu = ENV_GET_CPU(env);
    X86CPU *x86_cpu = X86_CPU(cpu);
    struct hax_vcpu_state *vcpu = cpu->hax_vcpu;
    struct hax_tunnel *ht = vcpu->tunnel;

    if (!hax_enabled()) {
        DPRINTF("Trying to vcpu execute at eip:" TARGET_FMT_lx "\n", env->eip);
        return 0;
    }

    cpu->halted = 0;

    if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
        apic_poll_irq(x86_cpu->apic_state);
    }

    if (cpu->interrupt_request & CPU_INTERRUPT_INIT) {
        DPRINTF("\nhax_vcpu_hax_exec: handling INIT for %d\n",
                cpu->cpu_index);
        do_cpu_init(x86_cpu);
        hax_vcpu_sync_state(env, 1);
    }

    if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) {
        DPRINTF("hax_vcpu_hax_exec: handling SIPI for %d\n",
                cpu->cpu_index);
        hax_vcpu_sync_state(env, 0);
        do_cpu_sipi(x86_cpu);
        hax_vcpu_sync_state(env, 1);
    }

    do {
        int hax_ret;

        if (cpu->exit_request) {
            ret = 1;
            break;
        }

        hax_vcpu_interrupt(env);

        qemu_mutex_unlock_iothread();
        cpu_exec_start(cpu);
        hax_ret = hax_vcpu_run(vcpu);
        cpu_exec_end(cpu);
        qemu_mutex_lock_iothread();

        /* Simply continue the vcpu_run if system call interrupted */
        if (hax_ret == -EINTR || hax_ret == -EAGAIN) {
            DPRINTF("io window interrupted\n");
            continue;
        }

        if (hax_ret < 0) {
            fprintf(stderr, "vcpu run failed for vcpu  %x\n", vcpu->vcpu_id);
            abort();
        }
        switch (ht->_exit_status) {
        case HAX_EXIT_IO:
            ret = hax_handle_io(env, ht->pio._df, ht->pio._port,
                            ht->pio._direction,
                            ht->pio._size, ht->pio._count, vcpu->iobuf);
            break;
        case HAX_EXIT_FAST_MMIO:
            ret = hax_handle_fastmmio(env, (struct hax_fastmmio *) vcpu->iobuf);
            break;
        /* Guest state changed, currently only for shutdown */
        case HAX_EXIT_STATECHANGE:
            fprintf(stdout, "VCPU shutdown request\n");
            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
            hax_vcpu_sync_state(env, 0);
            ret = 1;
            break;
        case HAX_EXIT_UNKNOWN_VMEXIT:
            fprintf(stderr, "Unknown VMX exit %x from guest\n",
                    ht->_exit_reason);
            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
            hax_vcpu_sync_state(env, 0);
            cpu_dump_state(cpu, stderr, fprintf, 0);
            ret = -1;
            break;
        case HAX_EXIT_HLT:
            if (!(cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
                !(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
                /* hlt instruction with interrupt disabled is shutdown */
                env->eflags |= IF_MASK;
                cpu->halted = 1;
                cpu->exception_index = EXCP_HLT;
                ret = 1;
            }
            break;
        /* these situations will continue to hax module */
        case HAX_EXIT_INTERRUPT:
        case HAX_EXIT_PAUSED:
            break;
        case HAX_EXIT_MMIO:
            /* Should not happen on UG system */
            fprintf(stderr, "HAX: unsupported MMIO emulation\n");
            ret = -1;
            break;
        case HAX_EXIT_REAL:
            /* Should not happen on UG system */
            fprintf(stderr, "HAX: unimplemented real mode emulation\n");
            ret = -1;
            break;
        default:
            fprintf(stderr, "Unknown exit %x from HAX\n", ht->_exit_status);
            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
            hax_vcpu_sync_state(env, 0);
            cpu_dump_state(cpu, stderr, fprintf, 0);
            ret = 1;
            break;
        }
    } while (!ret);

    if (cpu->exit_request) {
        cpu->exit_request = 0;
        cpu->exception_index = EXCP_INTERRUPT;
    }
    return ret < 0;
}