From: "poletaev" <Dmitry.Poletaev@ispras.ru>
To: qemu-devel@nongnu.org
Cc: Pavel.Dovgaluk@ispras.ru
Subject: Re: [Qemu-devel] [PATCH v2] target-i386: fix iret emulation correctness
Date: Tue, 12 Jul 2016 18:00:20 +0300 [thread overview]
Message-ID: <000301d1dc4e$1d848940$588d9bc0$@Poletaev@ispras.ru> (raw)
In-Reply-To:
ping
Best regards,
Dmitry Poletaev.
From: poletaev [mailto:Dmitry.Poletaev@ispras.ru]
Sent: Tuesday, June 07, 2016 5:12 PM
To: 'qemu-devel@nongnu.org'
Cc: 'Pavel.Dovgaluk@ispras.ru'
Subject: [PATCH v2] target-i386: fix iret emulation correctness
From: Dmitry Poletaev <Dmitry.Poletaev@ispras.ru>
Subject: [PATCH v2] target-i386: fix iret emulation correctness
According to Intel manual: "If the NMI handler is a virtual-8086 task with
an IOPL of less than 3, an IRET instruction issued from the handler
generates a general-protection
exception, the NMI is unmasked before the general-protection exception
handler is invoked."
QEMU does not reset NMI-blocking in such situation. This patch fixes it.
Signed-off-by: Dmitry Poletaev <Dmitry.Poletaev@ispras.ru>
---
v2: HF2_NMI_MASK was moved to hflags, situation from discussion leads to
NMI-blocking reset and eob generation
target-i386/cpu.h | 5 +++--
target-i386/kvm.c | 6 +++---
target-i386/seg_helper.c | 8 ++++----
target-i386/smm_helper.c | 6 +++---
target-i386/translate.c | 7 ++++++-
5 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 0426459..8857034 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -158,6 +158,7 @@
#define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */
#define HF_MPX_EN_SHIFT 25 /* MPX Enabled (CR4+XCR0+BNDCFGx) */
#define HF_MPX_IU_SHIFT 26 /* BND registers in-use */
+#define HF_NMI_SHIFT 27 /* CPU serving NMI */
#define HF_CPL_MASK (3 << HF_CPL_SHIFT)
#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
@@ -184,19 +185,19 @@
#define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT)
#define HF_MPX_EN_MASK (1 << HF_MPX_EN_SHIFT)
#define HF_MPX_IU_MASK (1 << HF_MPX_IU_SHIFT)
+#define HF_NMI_MASK (1 << HF_NMI_SHIFT)
/* hflags2 */
#define HF2_GIF_SHIFT 0 /* if set CPU takes interrupts */
#define HF2_HIF_SHIFT 1 /* value of IF_MASK when entering SVM */
-#define HF2_NMI_SHIFT 2 /* CPU serving NMI */
+/* 2 is vacant */
#define HF2_VINTR_SHIFT 3 /* value of V_INTR_MASKING bit */
#define HF2_SMM_INSIDE_NMI_SHIFT 4 /* CPU serving SMI nested inside NMI */
#define HF2_MPX_PR_SHIFT 5 /* BNDCFGx.BNDPRESERVE */
#define HF2_GIF_MASK (1 << HF2_GIF_SHIFT)
#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
-#define HF2_NMI_MASK (1 << HF2_NMI_SHIFT)
#define HF2_VINTR_MASK (1 << HF2_VINTR_SHIFT)
#define HF2_SMM_INSIDE_NMI_MASK (1 << HF2_SMM_INSIDE_NMI_SHIFT)
#define HF2_MPX_PR_MASK (1 << HF2_MPX_PR_SHIFT)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index abf50e6..3fc204a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -2357,7 +2357,7 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
events.nmi.injected = env->nmi_injected;
events.nmi.pending = env->nmi_pending;
- events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
+ events.nmi.masked = !!(env->hflags & HF_NMI_MASK);
events.nmi.pad = 0;
events.sipi_vector = env->sipi_vector;
@@ -2416,9 +2416,9 @@ static int kvm_get_vcpu_events(X86CPU *cpu)
env->nmi_injected = events.nmi.injected;
env->nmi_pending = events.nmi.pending;
if (events.nmi.masked) {
- env->hflags2 |= HF2_NMI_MASK;
+ env->hflags |= HF_NMI_MASK;
} else {
- env->hflags2 &= ~HF2_NMI_MASK;
+ env->hflags &= ~HF_NMI_MASK;
}
if (events.flags & KVM_VCPUEVENT_VALID_SMM) {
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 97aee09..acda3e9 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1333,9 +1333,9 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int
interrupt_request)
do_smm_enter(cpu);
ret = true;
} else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
- !(env->hflags2 & HF2_NMI_MASK)) {
+ !(env->hflags & HF_NMI_MASK)) {
cs->interrupt_request &= ~CPU_INTERRUPT_NMI;
- env->hflags2 |= HF2_NMI_MASK;
+ env->hflags |= HF_NMI_MASK;
do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
ret = true;
} else if (interrupt_request & CPU_INTERRUPT_MCE) {
@@ -1978,7 +1978,7 @@ void helper_iret_real(CPUX86State *env, int shift)
eflags_mask &= 0xffff;
}
cpu_load_eflags(env, new_eflags, eflags_mask);
- env->hflags2 &= ~HF2_NMI_MASK;
+ env->hflags &= ~HF_NMI_MASK;
}
static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl)
@@ -2253,7 +2253,7 @@ void helper_iret_protected(CPUX86State *env, int
shift, int next_eip)
} else {
helper_ret_protected(env, shift, 1, 0, GETPC());
}
- env->hflags2 &= ~HF2_NMI_MASK;
+ env->hflags &= ~HF_NMI_MASK;
}
void helper_lret_protected(CPUX86State *env, int shift, int addend)
diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c
index 4dd6a2c..f5bec7b 100644
--- a/target-i386/smm_helper.c
+++ b/target-i386/smm_helper.c
@@ -64,10 +64,10 @@ void do_smm_enter(X86CPU *cpu)
log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP);
env->hflags |= HF_SMM_MASK;
- if (env->hflags2 & HF2_NMI_MASK) {
+ if (env->hflags & HF_NMI_MASK) {
env->hflags2 |= HF2_SMM_INSIDE_NMI_MASK;
} else {
- env->hflags2 |= HF2_NMI_MASK;
+ env->hflags |= HF_NMI_MASK;
}
cpu_smm_update(cpu);
@@ -329,7 +329,7 @@ void helper_rsm(CPUX86State *env)
}
#endif
if ((env->hflags2 & HF2_SMM_INSIDE_NMI_MASK) == 0) {
- env->hflags2 &= ~HF2_NMI_MASK;
+ env->hflags &= ~HF_NMI_MASK;
}
env->hflags2 &= ~HF2_SMM_INSIDE_NMI_MASK;
env->hflags &= ~HF_SMM_MASK;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index f010022..fae87a2 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -6319,7 +6319,12 @@ static target_ulong disas_insn(CPUX86State *env,
DisasContext *s,
set_cc_op(s, CC_OP_EFLAGS);
} else if (s->vm86) {
if (s->iopl != 3) {
- gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ if (s->flags & HF_NMI_MASK) {
+ gen_reset_hflag(s, HF_NMI_MASK);
+ gen_jmp_im(pc_start - s->cs_base);
+ } else {
+ gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ }
} else {
gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
set_cc_op(s, CC_OP_EFLAGS);
--
1.8.4.msysgit.0
Best regards,
Dmitry Poletaev.
next reply other threads:[~2016-07-12 15:00 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-12 15:00 poletaev [this message]
-- strict thread matches above, loose matches on Subject: below --
2016-06-22 7:18 [Qemu-devel] [PATCH v2] target-i386: fix iret emulation correctness poletaev
2016-06-07 14:11 poletaev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='000301d1dc4e$1d848940$588d9bc0$@Poletaev@ispras.ru' \
--to=dmitry.poletaev@ispras.ru \
--cc=Pavel.Dovgaluk@ispras.ru \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.