diff options
Diffstat (limited to 'target/i386/tcg')
-rw-r--r-- | target/i386/tcg/helper-tcg.h | 2 | ||||
-rw-r--r-- | target/i386/tcg/seg_helper.c | 74 | ||||
-rw-r--r-- | target/i386/tcg/sysemu/seg_helper.c | 62 | ||||
-rw-r--r-- | target/i386/tcg/tcg-cpu.c | 8 | ||||
-rw-r--r-- | target/i386/tcg/translate.c | 10 |
5 files changed, 75 insertions, 81 deletions
diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index 2510cc244e..60ca09e95e 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -38,7 +38,9 @@ QEMU_BUILD_BUG_ON(TCG_PHYS_ADDR_BITS > TARGET_PHYS_ADDR_SPACE_BITS); * @cpu: vCPU the interrupt is to be handled by. */ void x86_cpu_do_interrupt(CPUState *cpu); +#ifndef CONFIG_USER_ONLY bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req); +#endif /* helper.c */ bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c index cef68b610a..baa905a0cd 100644 --- a/target/i386/tcg/seg_helper.c +++ b/target/i386/tcg/seg_helper.c @@ -929,9 +929,7 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int, e2); env->eip = offset; } -#endif -#ifdef TARGET_X86_64 void helper_sysret(CPUX86State *env, int dflag) { int cpl, selector; @@ -984,7 +982,7 @@ void helper_sysret(CPUX86State *env, int dflag) DESC_W_MASK | DESC_A_MASK); } } -#endif +#endif /* TARGET_X86_64 */ /* real mode interrupt */ static void do_interrupt_real(CPUX86State *env, int intno, int is_int, @@ -1112,76 +1110,6 @@ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw) do_interrupt_all(env_archcpu(env), intno, 0, 0, 0, is_hw); } -bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - int intno; - - interrupt_request = x86_cpu_pending_interrupt(cs, interrupt_request); - if (!interrupt_request) { - return false; - } - - /* Don't process multiple interrupt requests in a single call. - * This is required to make icount-driven execution deterministic. - */ - switch (interrupt_request) { -#if !defined(CONFIG_USER_ONLY) - case CPU_INTERRUPT_POLL: - cs->interrupt_request &= ~CPU_INTERRUPT_POLL; - apic_poll_irq(cpu->apic_state); - break; -#endif - case CPU_INTERRUPT_SIPI: - do_cpu_sipi(cpu); - break; - case CPU_INTERRUPT_SMI: - cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0); - cs->interrupt_request &= ~CPU_INTERRUPT_SMI; -#ifdef CONFIG_USER_ONLY - cpu_abort(CPU(cpu), "SMI interrupt: cannot enter SMM in user-mode"); -#else - do_smm_enter(cpu); -#endif /* CONFIG_USER_ONLY */ - break; - case CPU_INTERRUPT_NMI: - cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); - cs->interrupt_request &= ~CPU_INTERRUPT_NMI; - env->hflags2 |= HF2_NMI_MASK; - do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); - break; - case CPU_INTERRUPT_MCE: - cs->interrupt_request &= ~CPU_INTERRUPT_MCE; - do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0); - break; - case CPU_INTERRUPT_HARD: - cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0); - cs->interrupt_request &= ~(CPU_INTERRUPT_HARD | - CPU_INTERRUPT_VIRQ); - intno = cpu_get_pic_interrupt(env); - qemu_log_mask(CPU_LOG_TB_IN_ASM, - "Servicing hardware INT=0x%02x\n", intno); - do_interrupt_x86_hardirq(env, intno, 1); - break; -#if !defined(CONFIG_USER_ONLY) - case CPU_INTERRUPT_VIRQ: - cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0); - intno = x86_ldl_phys(cs, env->vm_vmcb - + offsetof(struct vmcb, control.int_vector)); - qemu_log_mask(CPU_LOG_TB_IN_ASM, - "Servicing virtual hardware INT=0x%02x\n", intno); - do_interrupt_x86_hardirq(env, intno, 1); - cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; - env->int_ctl &= ~V_IRQ_MASK; - break; -#endif - } - - /* Ensure that no TB jump will be modified as the program flow was changed. */ - return true; -} - void helper_lldt(CPUX86State *env, int selector) { SegmentCache *dt; diff --git a/target/i386/tcg/sysemu/seg_helper.c b/target/i386/tcg/sysemu/seg_helper.c index 82c0856c41..bf3444c26b 100644 --- a/target/i386/tcg/sysemu/seg_helper.c +++ b/target/i386/tcg/sysemu/seg_helper.c @@ -125,6 +125,68 @@ void x86_cpu_do_interrupt(CPUState *cs) } } +bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + int intno; + + interrupt_request = x86_cpu_pending_interrupt(cs, interrupt_request); + if (!interrupt_request) { + return false; + } + + /* Don't process multiple interrupt requests in a single call. + * This is required to make icount-driven execution deterministic. + */ + switch (interrupt_request) { + case CPU_INTERRUPT_POLL: + cs->interrupt_request &= ~CPU_INTERRUPT_POLL; + apic_poll_irq(cpu->apic_state); + break; + case CPU_INTERRUPT_SIPI: + do_cpu_sipi(cpu); + break; + case CPU_INTERRUPT_SMI: + cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0); + cs->interrupt_request &= ~CPU_INTERRUPT_SMI; + do_smm_enter(cpu); + break; + case CPU_INTERRUPT_NMI: + cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); + cs->interrupt_request &= ~CPU_INTERRUPT_NMI; + env->hflags2 |= HF2_NMI_MASK; + do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); + break; + case CPU_INTERRUPT_MCE: + cs->interrupt_request &= ~CPU_INTERRUPT_MCE; + do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0); + break; + case CPU_INTERRUPT_HARD: + cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0); + cs->interrupt_request &= ~(CPU_INTERRUPT_HARD | + CPU_INTERRUPT_VIRQ); + intno = cpu_get_pic_interrupt(env); + qemu_log_mask(CPU_LOG_TB_IN_ASM, + "Servicing hardware INT=0x%02x\n", intno); + do_interrupt_x86_hardirq(env, intno, 1); + break; + case CPU_INTERRUPT_VIRQ: + cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0); + intno = x86_ldl_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, control.int_vector)); + qemu_log_mask(CPU_LOG_TB_IN_ASM, + "Servicing virtual hardware INT=0x%02x\n", intno); + do_interrupt_x86_hardirq(env, intno, 1); + cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; + env->int_ctl &= ~V_IRQ_MASK; + break; + } + + /* Ensure that no TB jump will be modified as the program flow was changed. */ + return true; +} + /* check if Port I/O is allowed in TSS */ void helper_check_io(CPUX86State *env, uint32_t addr, uint32_t size) { diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 93a79a5741..3ecfae34cb 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -72,10 +72,12 @@ static const struct TCGCPUOps x86_tcg_ops = { .synchronize_from_tb = x86_cpu_synchronize_from_tb, .cpu_exec_enter = x86_cpu_exec_enter, .cpu_exec_exit = x86_cpu_exec_exit, - .cpu_exec_interrupt = x86_cpu_exec_interrupt, - .do_interrupt = x86_cpu_do_interrupt, .tlb_fill = x86_cpu_tlb_fill, -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY + .fake_user_interrupt = x86_cpu_do_interrupt, +#else + .do_interrupt = x86_cpu_do_interrupt, + .cpu_exec_interrupt = x86_cpu_exec_interrupt, .debug_excp_handler = breakpoint_handler, .debug_check_breakpoint = x86_debug_check_breakpoint, #endif /* !CONFIG_USER_ONLY */ diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index aacb605eee..a46be75b00 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2028,28 +2028,28 @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes) static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s) { - return translator_ldub(env, advance_pc(env, s, 1)); + return translator_ldub(env, &s->base, advance_pc(env, s, 1)); } static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s) { - return translator_ldsw(env, advance_pc(env, s, 2)); + return translator_ldsw(env, &s->base, advance_pc(env, s, 2)); } static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s) { - return translator_lduw(env, advance_pc(env, s, 2)); + return translator_lduw(env, &s->base, advance_pc(env, s, 2)); } static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s) { - return translator_ldl(env, advance_pc(env, s, 4)); + return translator_ldl(env, &s->base, advance_pc(env, s, 4)); } #ifdef TARGET_X86_64 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s) { - return translator_ldq(env, advance_pc(env, s, 8)); + return translator_ldq(env, &s->base, advance_pc(env, s, 8)); } #endif |