* [PATCH] x86 emulator: Add IRET instruction
@ 2010-07-25 19:18 Mohammed Gamal
0 siblings, 0 replies; 17+ messages in thread
From: Mohammed Gamal @ 2010-07-25 19:18 UTC (permalink / raw)
To: avi; +Cc: mtosatti, kvm, Mohammed Gamal
Ths patch adds IRET instruction (opcode 0xcf).
Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
---
arch/x86/kvm/emulate.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b38bd8b..ddc1da3 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * emulate.c
+ i emulate.c
*
* Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
*
@@ -1778,6 +1778,61 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
return rc;
}
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ struct decode_cache *c = &ctxt->decode;
+ int rc = X86EMUL_CONTINUE;
+ unsigned long temp_eip = 0;
+ unsigned long temp_eflags = 0;
+ /* TODO: Add stack limit check */
+
+ rc = emulate_pop(ctxt, ops, &temp_eip, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (temp_eip & ~0xffff) {
+ emulate_gp(ctxt, 0);
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ c->eip = temp_eip;
+
+ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_CS);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ rc = emulate_pop(ctxt, ops, &temp_eflags, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (c->op_bytes == 4)
+ temp_eflags = ((temp_eflags & 0x257fd5) | (ctxt->eflags & 0x1a0000));
+
+ ctxt->eflags = temp_eflags;
+
+ return rc;
+}
+
+static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops* ops)
+{
+ switch(ctxt->mode) {
+ case X86EMUL_MODE_REAL:
+ return emulate_iret_real(ctxt, ops);
+ case X86EMUL_MODE_VM86:
+ case X86EMUL_MODE_PROT16:
+ case X86EMUL_MODE_PROT32:
+ case X86EMUL_MODE_PROT64:
+ default:
+ /* iret from protected mode unimplemented yet */
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
@@ -2910,6 +2965,12 @@ special_insn:
if (rc != X86EMUL_CONTINUE)
goto done;
break;
+ case 0xcf: /* iret */
+ rc = emulate_iret(ctxt, ops);
+
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ break;
case 0xd0 ... 0xd1: /* Grp2 */
c->src.val = 1;
emulate_grp2(ctxt);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH] x86 emulator: Add IRET instruction
@ 2010-07-25 19:20 Mohammed Gamal
2010-07-25 23:59 ` Paolo Bonzini
2010-07-26 11:38 ` Avi Kivity
0 siblings, 2 replies; 17+ messages in thread
From: Mohammed Gamal @ 2010-07-25 19:20 UTC (permalink / raw)
To: avi; +Cc: mtosatti, kvm, Mohammed Gamal
Ths patch adds IRET instruction (opcode 0xcf).
Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
[Fixed a typo]
---
arch/x86/kvm/emulate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b38bd8b..4f18b9d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1778,6 +1778,61 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
return rc;
}
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ struct decode_cache *c = &ctxt->decode;
+ int rc = X86EMUL_CONTINUE;
+ unsigned long temp_eip = 0;
+ unsigned long temp_eflags = 0;
+ /* TODO: Add stack limit check */
+
+ rc = emulate_pop(ctxt, ops, &temp_eip, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (temp_eip & ~0xffff) {
+ emulate_gp(ctxt, 0);
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ c->eip = temp_eip;
+
+ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_CS);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ rc = emulate_pop(ctxt, ops, &temp_eflags, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (c->op_bytes == 4)
+ temp_eflags = ((temp_eflags & 0x257fd5) | (ctxt->eflags & 0x1a0000));
+
+ ctxt->eflags = temp_eflags;
+
+ return rc;
+}
+
+static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops* ops)
+{
+ switch(ctxt->mode) {
+ case X86EMUL_MODE_REAL:
+ return emulate_iret_real(ctxt, ops);
+ case X86EMUL_MODE_VM86:
+ case X86EMUL_MODE_PROT16:
+ case X86EMUL_MODE_PROT32:
+ case X86EMUL_MODE_PROT64:
+ default:
+ /* iret from protected mode unimplemented yet */
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
@@ -2910,6 +2965,12 @@ special_insn:
if (rc != X86EMUL_CONTINUE)
goto done;
break;
+ case 0xcf: /* iret */
+ rc = emulate_iret(ctxt, ops);
+
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ break;
case 0xd0 ... 0xd1: /* Grp2 */
c->src.val = 1;
emulate_grp2(ctxt);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-25 19:20 Mohammed Gamal
@ 2010-07-25 23:59 ` Paolo Bonzini
2010-07-26 0:07 ` Mohammed Gamal
2010-07-26 11:38 ` Avi Kivity
1 sibling, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-25 23:59 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: avi, mtosatti, kvm
On 07/25/2010 09:20 PM, Mohammed Gamal wrote:
> + if (c->op_bytes == 4)
> + temp_eflags = ((temp_eflags& 0x257fd5) | (ctxt->eflags& 0x1a0000));
Should this do also
if (c->op_bytes == 2)
temp_eflags = ((temp_eflags & 0x7fd5) | (ctxt->eflags & ~0xffffL));
?
Or better, extract a new function computing the mask from emulate_popf,
which would do something similar to what I wrote above.
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-25 23:59 ` Paolo Bonzini
@ 2010-07-26 0:07 ` Mohammed Gamal
2010-07-26 3:09 ` Wei Yongjun
2010-07-26 8:47 ` Paolo Bonzini
0 siblings, 2 replies; 17+ messages in thread
From: Mohammed Gamal @ 2010-07-26 0:07 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: avi, mtosatti, kvm
On Mon, Jul 26, 2010 at 2:59 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> On 07/25/2010 09:20 PM, Mohammed Gamal wrote:
>>
>> + if (c->op_bytes == 4)
>> + temp_eflags = ((temp_eflags& 0x257fd5) | (ctxt->eflags&
>> 0x1a0000));
>
> Should this do also
>
> if (c->op_bytes == 2)
> temp_eflags = ((temp_eflags & 0x7fd5) | (ctxt->eflags & ~0xffffL));
>
> ?
I don't think this is needed. The temp_eflags value is assigned
directly to eflags if we're operand size is 16 bits. At least that's
what the Intel manual says!
>
> Or better, extract a new function computing the mask from emulate_popf,
> which would do something similar to what I wrote above.
>
> Paolo
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-26 0:07 ` Mohammed Gamal
@ 2010-07-26 3:09 ` Wei Yongjun
2010-07-26 8:47 ` Paolo Bonzini
1 sibling, 0 replies; 17+ messages in thread
From: Wei Yongjun @ 2010-07-26 3:09 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: Paolo Bonzini, avi, mtosatti, kvm
> On Mon, Jul 26, 2010 at 2:59 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>> On 07/25/2010 09:20 PM, Mohammed Gamal wrote:
>>
>>> + if (c->op_bytes == 4)
>>> + temp_eflags = ((temp_eflags& 0x257fd5) | (ctxt->eflags&
>>> 0x1a0000));
>>>
>> Should this do also
>>
>> if (c->op_bytes == 2)
>> temp_eflags = ((temp_eflags & 0x7fd5) | (ctxt->eflags & ~0xffffL));
>>
>> ?
>>
> I don't think this is needed. The temp_eflags value is assigned
> directly to eflags if we're operand size is 16 bits. At least that's
> what the Intel manual says!
>
Intel manual says:
EFLAGS[15:0] ← Pop();
>
>> Or better, extract a new function computing the mask from emulate_popf,
>> which would do something similar to what I wrote above.
>>
>> Paolo
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-26 0:07 ` Mohammed Gamal
2010-07-26 3:09 ` Wei Yongjun
@ 2010-07-26 8:47 ` Paolo Bonzini
2010-07-26 9:00 ` Avi Kivity
1 sibling, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-26 8:47 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: avi, mtosatti, kvm
On 07/26/2010 02:07 AM, Mohammed Gamal wrote:
> On Mon, Jul 26, 2010 at 2:59 AM, Paolo Bonzini<pbonzini@redhat.com> wrote:
>> On 07/25/2010 09:20 PM, Mohammed Gamal wrote:
>>>
>>> + if (c->op_bytes == 4)
>>> + temp_eflags = ((temp_eflags & 0x257fd5) | (ctxt->eflags&
>>> 0x1a0000));
>>
>> Should this do also
>>
>> if (c->op_bytes == 2)
>> temp_eflags = ((temp_eflags & 0x7fd5) | (ctxt->eflags & ~0xffffL));
>>
>> ?
>
> I don't think this is needed. The temp_eflags value is assigned
> directly to eflags if we're operand size is 16 bits. At least that's
> what the Intel manual says!
That's fine, but please make sure that
mov %sp, %bp
orw $2, 4(%bp)
iret
followed at return site by
pushf
popw %ax
does not set bit 1 in %ax. That's the important point (also see how
emulate_popf avoids magic hex constants).
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-26 8:47 ` Paolo Bonzini
@ 2010-07-26 9:00 ` Avi Kivity
2010-07-26 9:31 ` Paolo Bonzini
2010-07-26 9:32 ` Paolo Bonzini
0 siblings, 2 replies; 17+ messages in thread
From: Avi Kivity @ 2010-07-26 9:00 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Mohammed Gamal, mtosatti, kvm
On 07/26/2010 11:47 AM, Paolo Bonzini wrote:
>> I don't think this is needed. The temp_eflags value is assigned
>> directly to eflags if we're operand size is 16 bits. At least that's
>> what the Intel manual says!
>
>
> That's fine, but please make sure that
>
> mov %sp, %bp
> orw $2, 4(%bp)
> iret
>
> followed at return site by
>
> pushf
> popw %ax
>
> does not set bit 1 in %ax. That's the important point (also see how
> emulate_popf avoids magic hex constants).
Moreover, vmx will fail the next entry if this is not done. 23.3.1.4 says:
> RFLAGS.
> — Reserved bits 63:22 (bits 31:22 on processors that do not support
> Intel 64
> architecture), bit 15, bit 5 and bit 3 must be 0 in the field, and
> reserved bit 1
> must be 1.
Looks like a note is missing in the manual. I'll alert the authors.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-26 9:00 ` Avi Kivity
@ 2010-07-26 9:31 ` Paolo Bonzini
2010-07-26 9:32 ` Paolo Bonzini
1 sibling, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-26 9:31 UTC (permalink / raw)
To: Avi Kivity; +Cc: Mohammed Gamal, mtosatti, kvm
On 07/26/2010 11:00 AM, Avi Kivity wrote:
> On 07/26/2010 11:47 AM, Paolo Bonzini wrote:
>>> I don't think this is needed. The temp_eflags value is assigned
>>> directly to eflags if we're operand size is 16 bits. At least
>>> that's what the Intel manual says!
>>
>> That's fine, but please make sure that
>>
>> mov %sp, %bp
>> orw $2, 4(%bp)
>> iret
>>
>> followed at return site by
>>
>> pushf
>> popw %ax
>>
>> does not set bit 1 in %ax. That's the important point (also see how
>> emulate_popf avoids magic hex constants).
>
> Moreover, vmx will fail the next entry if this is not done. 23.3.1.4
> says:
>
>> RFLAGS. — Reserved bits 63:22 (bits 31:22 on processors that do not
>> support Intel 64 architecture), bit 15, bit 5 and bit 3 must be 0
>> in the field, and reserved bit 1 must be 1.
(I remembered one bit had to be 1, but failed to recall which one. I
should have looked up SAHF in the manual). This means that my code
actually should be
mov %sp, %bp
orw $8, 4(%bp)
iret
followed by testing bit 3.
The emulate_popf approach that explicitly lists bits taken from the
stack seems more robust. For example, Mohammed's "if (c->op_bytes ==
4)" code leaves bit 1 cleared:
temp_eflags = ((temp_eflags & 0x257fd5)
| (ctxt->eflags & 0x1a0000));
(But then it is probably never used since only a 32-bit code segment in
unreal mode would trigger it).
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-26 9:00 ` Avi Kivity
2010-07-26 9:31 ` Paolo Bonzini
@ 2010-07-26 9:32 ` Paolo Bonzini
1 sibling, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-26 9:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: Mohammed Gamal, mtosatti, kvm
On 07/26/2010 11:00 AM, Avi Kivity wrote:
> On 07/26/2010 11:47 AM, Paolo Bonzini wrote:
>>> I don't think this is needed. The temp_eflags value is assigned
>>> directly to eflags if we're operand size is 16 bits. At least
>>> that's what the Intel manual says!
>>
>> That's fine, but please make sure that
>>
>> mov %sp, %bp
>> orw $2, 4(%bp)
>> iret
>>
>> followed at return site by
>>
>> pushf
>> popw %ax
>>
>> does not set bit 1 in %ax. That's the important point (also see how
>> emulate_popf avoids magic hex constants).
>
> Moreover, vmx will fail the next entry if this is not done. 23.3.1.4
> says:
>
>> RFLAGS. — Reserved bits 63:22 (bits 31:22 on processors that do not
>> support Intel 64 architecture), bit 15, bit 5 and bit 3 must be 0
>> in the field, and reserved bit 1 must be 1.
(I remembered one bit had to be 1, but failed to recall which one. I
should have looked up SAHF in the manual). This means that my code
actually should be
mov %sp, %bp
orw $8, 4(%bp)
iret
followed by testing bit 3.
The emulate_popf approach that explicitly lists bits taken from the
stack seems more robust. For example, Mohammed's "if (c->op_bytes ==
4)" code leaves bit 1 cleared:
temp_eflags = ((temp_eflags & 0x257fd5)
| (ctxt->eflags & 0x1a0000));
(But then it is probably never used since only a 32-bit code segment in
unreal mode would trigger it).
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-25 19:20 Mohammed Gamal
2010-07-25 23:59 ` Paolo Bonzini
@ 2010-07-26 11:38 ` Avi Kivity
1 sibling, 0 replies; 17+ messages in thread
From: Avi Kivity @ 2010-07-26 11:38 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: mtosatti, kvm
On 07/25/2010 10:20 PM, Mohammed Gamal wrote:
> Ths patch adds IRET instruction (opcode 0xcf).
> Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
>
Please post a unit test with the next iteration.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] x86 emulator: Add IRET instruction
@ 2010-07-27 23:06 Mohammed Gamal
2010-07-28 4:20 ` Avi Kivity
0 siblings, 1 reply; 17+ messages in thread
From: Mohammed Gamal @ 2010-07-27 23:06 UTC (permalink / raw)
To: avi; +Cc: kvm, mtosatti, Mohammed Gamal
Ths patch adds IRET instruction (opcode 0xcf).
Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
----
Changes from v1:
- Corrected handling of eflags
---
arch/x86/kvm/emulate.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b38bd8b..e45fd28 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1778,6 +1778,69 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
return rc;
}
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ struct decode_cache *c = &ctxt->decode;
+ int rc = X86EMUL_CONTINUE;
+ unsigned long temp_eip = 0;
+ unsigned long temp_eflags = 0;
+ unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
+ EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
+ EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
+ unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
+
+ /* TODO: Add stack limit check */
+
+ rc = emulate_pop(ctxt, ops, &temp_eip, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (temp_eip & ~0xffff) {
+ emulate_gp(ctxt, 0);
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ c->eip = temp_eip;
+
+ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_CS);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ rc = emulate_pop(ctxt, ops, &temp_eflags, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (c->op_bytes == 4) {
+ temp_eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
+ ctxt->eflags = temp_eflags;
+ } else if (c->op_bytes == 2) {
+ temp_eflags &= ~0xfffd; /* Do not clear reserved bit 1 */
+ ctxt->eflags |= temp_eflags;
+ }
+
+ return rc;
+}
+
+static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops* ops)
+{
+ switch(ctxt->mode) {
+ case X86EMUL_MODE_REAL:
+ return emulate_iret_real(ctxt, ops);
+ case X86EMUL_MODE_VM86:
+ case X86EMUL_MODE_PROT16:
+ case X86EMUL_MODE_PROT32:
+ case X86EMUL_MODE_PROT64:
+ default:
+ /* iret from protected mode unimplemented yet */
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
@@ -2910,6 +2973,12 @@ special_insn:
if (rc != X86EMUL_CONTINUE)
goto done;
break;
+ case 0xcf: /* iret */
+ rc = emulate_iret(ctxt, ops);
+
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ break;
case 0xd0 ... 0xd1: /* Grp2 */
c->src.val = 1;
emulate_grp2(ctxt);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-27 23:06 [PATCH] x86 emulator: Add IRET instruction Mohammed Gamal
@ 2010-07-28 4:20 ` Avi Kivity
0 siblings, 0 replies; 17+ messages in thread
From: Avi Kivity @ 2010-07-28 4:20 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: kvm, mtosatti
On 07/28/2010 02:06 AM, Mohammed Gamal wrote:
> Ths patch adds IRET instruction (opcode 0xcf).
> Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
>
> @@ -1778,6 +1778,69 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
> return rc;
> }
>
> +static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
> + struct x86_emulate_ops *ops)
> +{
> + struct decode_cache *c =&ctxt->decode;
> + int rc = X86EMUL_CONTINUE;
> + unsigned long temp_eip = 0;
> + unsigned long temp_eflags = 0;
> + unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
> + EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
> + EFLG_AC | EFLG_ID | (1<< 1); /* Last one is the reserved bit */
> + unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
> +
> + /* TODO: Add stack limit check */
> +
> + rc = emulate_pop(ctxt, ops,&temp_eip, c->op_bytes);
> +
> + if (rc != X86EMUL_CONTINUE)
> + return rc;
> +
> + if (temp_eip& ~0xffff) {
> + emulate_gp(ctxt, 0);
> + return X86EMUL_PROPAGATE_FAULT;
> + }
> +
> + c->eip = temp_eip;
> +
> + rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_CS);
> +
> + if (rc != X86EMUL_CONTINUE)
> + return rc;
> +
> + rc = emulate_pop(ctxt, ops,&temp_eflags, c->op_bytes);
If this pop fails, the emulate_pop_sreg() will already have been
committed and the cs will be corrupted. That's a preexisting problem,
however, we can fix it later.
> +
> + if (rc != X86EMUL_CONTINUE)
> + return rc;
> +
> + if (c->op_bytes == 4) {
> + temp_eflags = ((temp_eflags& mask) | (ctxt->eflags& vm86_mask));
> + ctxt->eflags = temp_eflags;
Can combine to a single assignment instead of two.
> + } else if (c->op_bytes == 2) {
> + temp_eflags&= ~0xfffd; /* Do not clear reserved bit 1 */
> + ctxt->eflags |= temp_eflags;
If temp_eflags has CF clear, but ctxt->eflags has CF set, we end up with
CF set, incorrectly. Need to drop the low 16 bits from ctxt->eflags.
> + }
> +
Need also to ensure reserved bits are set to their required values,
something like
ctxt->eflags &= ~EFLG_RESERVED_0_MASK; (0xffc0802a)
ctxt->eflags |= EFLG_RESERVERD_1_MASK; (0x2)
> + return rc;
> +}
> +
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] x86 emulator: Add IRET instruction
@ 2010-07-28 9:38 Mohammed Gamal
2010-07-28 10:30 ` Avi Kivity
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Mohammed Gamal @ 2010-07-28 9:38 UTC (permalink / raw)
To: avi; +Cc: mtosatti, kvm, Mohammed Gamal
Ths patch adds IRET instruction (opcode 0xcf).
Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
----
Changes from v2:
- Delay committing cs until all pop operation are ensured to be successful
- Corrected handling for eflags
---
arch/x86/kvm/emulate.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 81 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b38bd8b..620f609 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -392,6 +392,9 @@ static u32 group2_table[] = {
#define EFLG_PF (1<<2)
#define EFLG_CF (1<<0)
+#define EFLG_RESERVED_ZEROS_MASK 0xffc0802a
+#define EFLG_RESERVED_ONE_MASK 2
+
/*
* Instruction emulation:
* Most instructions are emulated directly via a fragment of inline assembly
@@ -1778,6 +1781,78 @@ static int emulate_popa(struct x86_emulate_ctxt *ctxt,
return rc;
}
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ struct decode_cache *c = &ctxt->decode;
+ int rc = X86EMUL_CONTINUE;
+ unsigned long temp_eip = 0;
+ unsigned long temp_eflags = 0;
+ unsigned long cs = 0;
+ unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
+ EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
+ EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
+ unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
+
+ /* TODO: Add stack limit check */
+
+ rc = emulate_pop(ctxt, ops, &temp_eip, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ if (temp_eip & ~0xffff) {
+ emulate_gp(ctxt, 0);
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ rc = emulate_pop(ctxt, ops, &temp_eflags, c->op_bytes);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
+
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ c->eip = temp_eip;
+
+
+ if (c->op_bytes == 4)
+ ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
+ else if (c->op_bytes == 2) {
+ ctxt->eflags &= ~0xffff;
+ ctxt->eflags |= temp_eflags;
+ }
+
+ ctxt->eflags &= ~EFLG_RESERVED_ZEROS_MASK; /* Clear reserved zeros */
+ ctxt->eflags |= EFLG_RESERVED_ONE_MASK;
+
+ return rc;
+}
+
+static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops* ops)
+{
+ switch(ctxt->mode) {
+ case X86EMUL_MODE_REAL:
+ return emulate_iret_real(ctxt, ops);
+ case X86EMUL_MODE_VM86:
+ case X86EMUL_MODE_PROT16:
+ case X86EMUL_MODE_PROT32:
+ case X86EMUL_MODE_PROT64:
+ default:
+ /* iret from protected mode unimplemented yet */
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
@@ -2910,6 +2985,12 @@ special_insn:
if (rc != X86EMUL_CONTINUE)
goto done;
break;
+ case 0xcf: /* iret */
+ rc = emulate_iret(ctxt, ops);
+
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ break;
case 0xd0 ... 0xd1: /* Grp2 */
c->src.val = 1;
emulate_grp2(ctxt);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-28 9:38 Mohammed Gamal
@ 2010-07-28 10:30 ` Avi Kivity
2010-07-28 13:30 ` Paolo Bonzini
2010-07-28 17:15 ` Marcelo Tosatti
2 siblings, 0 replies; 17+ messages in thread
From: Avi Kivity @ 2010-07-28 10:30 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: mtosatti, kvm
On 07/28/2010 12:38 PM, Mohammed Gamal wrote:
> Ths patch adds IRET instruction (opcode 0xcf).
> Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
Looks good.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-28 9:38 Mohammed Gamal
2010-07-28 10:30 ` Avi Kivity
@ 2010-07-28 13:30 ` Paolo Bonzini
2010-07-28 13:49 ` Paolo Bonzini
2010-07-28 17:15 ` Marcelo Tosatti
2 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-28 13:30 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: avi, mtosatti, kvm
On 07/28/2010 11:38 AM, Mohammed Gamal wrote:
> + unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
> + EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
> + EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
> + unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
> ...
> + if (c->op_bytes == 4)
> + ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
> + else if (c->op_bytes == 2) {
> + ctxt->eflags &= ~0xffff;
> + ctxt->eflags |= temp_eflags;
> + }
I think that's still not it. You can set reserved bits for c->op_bytes
== 2, and you can clear bit 1 for both 16- and 32-bit IRET.
IOW you need something like this:
mask = ...; /* without (1 << 1); */
ctxt_mask = (1 << 1) | EFLG_VM | EFLG_VIF | EFLG_VIP;
if (c->op_bytes == 2) {
mask &= 0xffff;
ctxt_mask |= ~0xffff;
}
ctxt->eflags = (temp_eflags & mask) | (ctxt->eflags & ctxt_mask);
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-28 13:30 ` Paolo Bonzini
@ 2010-07-28 13:49 ` Paolo Bonzini
0 siblings, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2010-07-28 13:49 UTC (permalink / raw)
Cc: Mohammed Gamal, avi, mtosatti, kvm
On 07/28/2010 03:30 PM, Paolo Bonzini wrote:
> On 07/28/2010 11:38 AM, Mohammed Gamal wrote:
>> + unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF
>> | EFLG_TF |
>> + EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
>> + EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
>> + unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
>> ...
>> + if (c->op_bytes == 4)
>> + ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
>> + else if (c->op_bytes == 2) {
>> + ctxt->eflags &= ~0xffff;
>> + ctxt->eflags |= temp_eflags;
>> + }
>
> I think that's still not it. You can set reserved bits for c->op_bytes
> == 2, and you can clear bit 1 for both 16- and 32-bit IRET.
>
> IOW you need something like this:
>
> mask = ...; /* without (1 << 1); */
> ctxt_mask = (1 << 1) | EFLG_VM | EFLG_VIF | EFLG_VIP;
>
> if (c->op_bytes == 2) {
> mask &= 0xffff;
> ctxt_mask |= ~0xffff;
> }
>
> ctxt->eflags = (temp_eflags & mask) | (ctxt->eflags & ctxt_mask);
Sorry, I replied to v3 of the patch while reviewing v2.
Looks good indeed.
Thanks!
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] x86 emulator: Add IRET instruction
2010-07-28 9:38 Mohammed Gamal
2010-07-28 10:30 ` Avi Kivity
2010-07-28 13:30 ` Paolo Bonzini
@ 2010-07-28 17:15 ` Marcelo Tosatti
2 siblings, 0 replies; 17+ messages in thread
From: Marcelo Tosatti @ 2010-07-28 17:15 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: avi, kvm
On Wed, Jul 28, 2010 at 12:38:40PM +0300, Mohammed Gamal wrote:
> Ths patch adds IRET instruction (opcode 0xcf).
> Currently, only IRET in real mode is emulated. Protected mode support is to be added later if needed.
>
> Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
>
> ----
> Changes from v2:
> - Delay committing cs until all pop operation are ensured to be successful
> - Corrected handling for eflags
> ---
> arch/x86/kvm/emulate.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 81 insertions(+), 0 deletions(-)
Applied, thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2010-07-28 17:16 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-27 23:06 [PATCH] x86 emulator: Add IRET instruction Mohammed Gamal
2010-07-28 4:20 ` Avi Kivity
-- strict thread matches above, loose matches on Subject: below --
2010-07-28 9:38 Mohammed Gamal
2010-07-28 10:30 ` Avi Kivity
2010-07-28 13:30 ` Paolo Bonzini
2010-07-28 13:49 ` Paolo Bonzini
2010-07-28 17:15 ` Marcelo Tosatti
2010-07-25 19:20 Mohammed Gamal
2010-07-25 23:59 ` Paolo Bonzini
2010-07-26 0:07 ` Mohammed Gamal
2010-07-26 3:09 ` Wei Yongjun
2010-07-26 8:47 ` Paolo Bonzini
2010-07-26 9:00 ` Avi Kivity
2010-07-26 9:31 ` Paolo Bonzini
2010-07-26 9:32 ` Paolo Bonzini
2010-07-26 11:38 ` Avi Kivity
2010-07-25 19:18 Mohammed Gamal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox