diff mbox

x86emul: correct PUSHF/POPF

Message ID 5846CA6A0200007800125B2D@prv-mh.provo.novell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Beulich Dec. 6, 2016, 1:25 p.m. UTC
Both need to raise #GP(0) when in VM86 mode with IOPL < 3.

Additionally PUSHF is documented to clear VM and RF from the value
placed onto the stack.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
x86emul: correct PUSHF/POPF

Both need to raise #GP(0) when in VM86 mode with IOPL < 3.

Additionally PUSHF is documented to clear VM and RF from the value
placed onto the stack.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -3121,13 +3121,20 @@ x86_emulate(
     }
 
     case 0x9c: /* pushf */
-        src.val = _regs.eflags;
+        generate_exception_if((_regs.eflags & EFLG_VM) &&
+                              (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
+                              EXC_GP, 0);
+        src.val = _regs.eflags & ~(EFLG_VM | EFLG_RF);
         goto push;
 
     case 0x9d: /* popf */ {
         uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
+
         if ( !mode_ring0() )
         {
+            generate_exception_if((_regs.eflags & EFLG_VM) &&
+                                  (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
+                                  EXC_GP, 0);
             mask |= EFLG_IOPL;
             if ( !mode_iopl() )
                 mask |= EFLG_IF;

Comments

Andrew Cooper Dec. 6, 2016, 3:56 p.m. UTC | #1
On 06/12/16 13:25, Jan Beulich wrote:
> Both need to raise #GP(0) when in VM86 mode with IOPL < 3.
>
> Additionally PUSHF is documented to clear VM and RF from the value
> placed onto the stack.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>
> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
> @@ -3121,13 +3121,20 @@ x86_emulate(
>      }
>  
>      case 0x9c: /* pushf */
> -        src.val = _regs.eflags;
> +        generate_exception_if((_regs.eflags & EFLG_VM) &&
> +                              (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,

How about "MASK_EXTR(_regs.eflags, EFLG_IOPL) != 3"

This would be rather clear to read, as the two EFLG_IOPL have two
different purposes in the line as presented.

Otherwise, Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

> +                              EXC_GP, 0);
> +        src.val = _regs.eflags & ~(EFLG_VM | EFLG_RF);
>          goto push;
>  
>      case 0x9d: /* popf */ {
>          uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
> +
>          if ( !mode_ring0() )
>          {
> +            generate_exception_if((_regs.eflags & EFLG_VM) &&
> +                                  (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
> +                                  EXC_GP, 0);
>              mask |= EFLG_IOPL;
>              if ( !mode_iopl() )
>                  mask |= EFLG_IF;
>
>
>
Jan Beulich Dec. 7, 2016, 8:11 a.m. UTC | #2
>>> On 06.12.16 at 16:56, <andrew.cooper3@citrix.com> wrote:
> On 06/12/16 13:25, Jan Beulich wrote:
>> Both need to raise #GP(0) when in VM86 mode with IOPL < 3.
>>
>> Additionally PUSHF is documented to clear VM and RF from the value
>> placed onto the stack.
>>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>>
>> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
>> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
>> @@ -3121,13 +3121,20 @@ x86_emulate(
>>      }
>>  
>>      case 0x9c: /* pushf */
>> -        src.val = _regs.eflags;
>> +        generate_exception_if((_regs.eflags & EFLG_VM) &&
>> +                              (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
> 
> How about "MASK_EXTR(_regs.eflags, EFLG_IOPL) != 3"
> 
> This would be rather clear to read, as the two EFLG_IOPL have two
> different purposes in the line as presented.

Done - I had simply forgotten for a moment that we can use
MASK_EXTR() here now.

> Otherwise, Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

Thanks, Jan
diff mbox

Patch

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -3121,13 +3121,20 @@  x86_emulate(
     }
 
     case 0x9c: /* pushf */
-        src.val = _regs.eflags;
+        generate_exception_if((_regs.eflags & EFLG_VM) &&
+                              (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
+                              EXC_GP, 0);
+        src.val = _regs.eflags & ~(EFLG_VM | EFLG_RF);
         goto push;
 
     case 0x9d: /* popf */ {
         uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
+
         if ( !mode_ring0() )
         {
+            generate_exception_if((_regs.eflags & EFLG_VM) &&
+                                  (_regs.eflags & EFLG_IOPL) != EFLG_IOPL,
+                                  EXC_GP, 0);
             mask |= EFLG_IOPL;
             if ( !mode_iopl() )
                 mask |= EFLG_IF;