summary refs log tree commit diff stats
path: root/cpu-exec.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-04 17:02:19 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-04 17:02:19 +0000
commitdb620f46a8c8b168831812eabd7428a952964334 (patch)
tree755a1cb01456c96211ca74ca7e048811655fe9c1 /cpu-exec.c
parent3cd9acb410f313b03ad9348f36d86ad8d3bf703f (diff)
downloadfocaccia-qemu-db620f46a8c8b168831812eabd7428a952964334.tar.gz
focaccia-qemu-db620f46a8c8b168831812eabd7428a952964334.zip
reworked SVM interrupt handling logic - fixed vmrun EIP saved value - reworked cr8 handling - added CPUState.hflags2
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4662 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'cpu-exec.c')
-rw-r--r--cpu-exec.c89
1 files changed, 45 insertions, 44 deletions
diff --git a/cpu-exec.c b/cpu-exec.c
index 4751d52c8e..bf9bcd4444 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -368,11 +368,8 @@ int cpu_exec(CPUState *env1)
             next_tb = 0; /* force lookup of first TB */
             for(;;) {
                 interrupt_request = env->interrupt_request;
-                if (__builtin_expect(interrupt_request, 0)
-#if defined(TARGET_I386)
-			&& env->hflags & HF_GIF_MASK
-#endif
-            && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
+                if (__builtin_expect(interrupt_request, 0) &&
+                    likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                         env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                         env->exception_index = EXCP_DEBUG;
@@ -388,47 +385,51 @@ int cpu_exec(CPUState *env1)
                     }
 #endif
 #if defined(TARGET_I386)
-                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
-                        !(env->hflags & HF_SMM_MASK)) {
-                        svm_check_intercept(SVM_EXIT_SMI);
-                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
-                        do_smm_enter();
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
-                        !(env->hflags & HF_NMI_MASK)) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
-                        env->hflags |= HF_NMI_MASK;
-                        do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
-                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
-                        int intno;
-                        svm_check_intercept(SVM_EXIT_INTR);
-                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
-                        intno = cpu_get_pic_interrupt(env);
-                        if (loglevel & CPU_LOG_TB_IN_ASM) {
-                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
-                        }
-                        do_interrupt(intno, 0, 0, 0, 1);
-                        /* ensure that no TB jump will be modified as
-                           the program flow was changed */
-                        next_tb = 0;
+                    if (env->hflags2 & HF2_GIF_MASK) {
+                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
+                            !(env->hflags & HF_SMM_MASK)) {
+                            svm_check_intercept(SVM_EXIT_SMI);
+                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                            do_smm_enter();
+                            next_tb = 0;
+                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
+                                   !(env->hflags2 & HF2_NMI_MASK)) {
+                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+                            env->hflags2 |= HF2_NMI_MASK;
+                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
+                            next_tb = 0;
+                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                                   (((env->hflags2 & HF2_VINTR_MASK) && 
+                                     (env->hflags2 & HF2_HIF_MASK)) ||
+                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
+                                     (env->eflags & IF_MASK && 
+                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
+                            int intno;
+                            svm_check_intercept(SVM_EXIT_INTR);
+                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+                            intno = cpu_get_pic_interrupt(env);
+                            if (loglevel & CPU_LOG_TB_IN_ASM) {
+                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
+                            }
+                            do_interrupt(intno, 0, 0, 0, 1);
+                            /* ensure that no TB jump will be modified as
+                               the program flow was changed */
+                            next_tb = 0;
 #if !defined(CONFIG_USER_ONLY)
-                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
-                        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
-                         int intno;
-                         /* FIXME: this should respect TPR */
-                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
-                         svm_check_intercept(SVM_EXIT_VINTR);
-                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
-                         if (loglevel & CPU_LOG_TB_IN_ASM)
-                             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
-	                 do_interrupt(intno, 0, 0, -1, 1);
-                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
-                                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
-                        next_tb = 0;
+                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+                                   (env->eflags & IF_MASK) && 
+                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+                            int intno;
+                            /* FIXME: this should respect TPR */
+                            svm_check_intercept(SVM_EXIT_VINTR);
+                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+                            if (loglevel & CPU_LOG_TB_IN_ASM)
+                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
+                            do_interrupt(intno, 0, 0, 0, 1);
+                            next_tb = 0;
 #endif
+                        }
                     }
 #elif defined(TARGET_PPC)
 #if 0