aboutsummaryrefslogtreecommitdiff
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)
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