diff options
Diffstat (limited to 'qemu-kvm.c')
-rw-r--r-- | qemu-kvm.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/qemu-kvm.c b/qemu-kvm.c index 8620e25b0..b5eee9361 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -222,6 +222,7 @@ static void load_regs(CPUState *env) perror("kvm_set_msrs FAILED"); } + static void save_regs(CPUState *env) { struct kvm_regs regs; @@ -358,34 +359,32 @@ static void save_regs(CPUState *env) #include <signal.h> -static int kvm_interrupt_pending(CPUState *env) + +static int try_push_interrupts(void *opaque) { - int i; + CPUState **envs = opaque, *env; + env = envs[0]; - for (i = 0; i < NR_IRQ_WORDS; ++i) - if (env->kvm_interrupt_bitmap[i]) - return 1; - return 0; + if (env->ready_for_interrupt_injection && + (env->interrupt_request & CPU_INTERRUPT_HARD) && + (env->eflags & IF_MASK)) { + env->interrupt_request &= ~CPU_INTERRUPT_HARD; + // for now using cpu 0 + kvm_inject_irq(kvm_context, 0, cpu_get_pic_interrupt(env)); + } + + return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0; } -static inline void push_interrupts(CPUState *env) +static void post_kvm_run(void *opaque, struct kvm_run *kvm_run) { - if (!(env->interrupt_request & CPU_INTERRUPT_HARD) || - !(env->eflags & IF_MASK) || kvm_interrupt_pending(env)) { - if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) { - env->interrupt_request &= ~CPU_INTERRUPT_EXIT; - env->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(); - } - return; - } - - do { - env->interrupt_request &= ~CPU_INTERRUPT_HARD; + CPUState **envs = opaque, *env; + env = envs[0]; - // for now using cpu 0 - kvm_inject_irq(kvm_context, 0, cpu_get_pic_interrupt(env)); - } while ( (env->interrupt_request & CPU_INTERRUPT_HARD) && (env->cr[0] & CR0_PG_MASK) ); + env->eflags = (kvm_run->if_flag) ? env->eflags | IF_MASK:env->eflags & ~IF_MASK; + env->ready_for_interrupt_injection = kvm_run->ready_for_interrupt_injection; + cpu_set_apic_tpr(env, kvm_run->cr8); + cpu_set_apic_base(env, kvm_run->apic_base); } void kvm_load_registers(CPUState *env) @@ -393,18 +392,29 @@ void kvm_load_registers(CPUState *env) load_regs(env); } +void kvm_save_registers(CPUState *env) +{ + save_regs(env); +} + int kvm_cpu_exec(CPUState *env) { + int pending = (!env->ready_for_interrupt_injection || + ((env->interrupt_request & CPU_INTERRUPT_HARD) && + (env->eflags & IF_MASK))); - push_interrupts(env); + if (!pending && (env->interrupt_request & CPU_INTERRUPT_EXIT)) { + env->interrupt_request &= ~CPU_INTERRUPT_EXIT; + env->exception_index = EXCP_INTERRUPT; + cpu_loop_exit(); + } + if (!saved_env[0]) saved_env[0] = env; kvm_run(kvm_context, 0); - save_regs(env); - return 0; } @@ -461,7 +471,6 @@ static int kvm_debug(void *opaque, int vcpu) CPUState **envs = opaque; env = envs[0]; - save_regs(env); env->exception_index = EXCP_DEBUG; return 1; } @@ -561,14 +570,12 @@ static int kvm_halt(void *opaque, int vcpu) CPUState **envs = opaque, *env; env = envs[0]; - save_regs(env); - - if (!((kvm_interrupt_pending(env) || - (env->interrupt_request & CPU_INTERRUPT_HARD)) && + if (!((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->eflags & IF_MASK))) { env->hflags |= HF_HALTED_MASK; env->exception_index = EXCP_HLT; } + return 1; } @@ -591,6 +598,8 @@ static struct kvm_callbacks qemu_kvm_ops = { .writeq = kvm_writeq, .halt = kvm_halt, .io_window = kvm_io_window, + .try_push_interrupts = try_push_interrupts, + .post_kvm_run = post_kvm_run, }; int kvm_qemu_init() |