diff mbox

[8/8] x86/emul: Implement the STAC and CLAC instructions

Message ID 1480932571-23547-9-git-send-email-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Cooper Dec. 5, 2016, 10:09 a.m. UTC
Note that unlike most privilege restricted instructions, STAC and CLAC are
documented to raise #UD rather than #GP[0], and indeed do so.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
---
 xen/arch/x86/x86_emulate/x86_emulate.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

Comments

Jan Beulich Dec. 5, 2016, 1:45 p.m. UTC | #1
>>> On 05.12.16 at 11:09, <andrew.cooper3@citrix.com> wrote:
> @@ -4362,11 +4363,27 @@ x86_emulate(
>  
>          switch( modrm )
>          {
> -#ifdef __XEN__
> -        case 0xd1: /* xsetbv */
> -        {
>              unsigned long cr4;
>  
> +        case 0xca: /* clac */
> +        case 0xcb: /* stac */
> +            generate_exception_if(
> +                lock_prefix || (_regs.eflags & EFLG_VM), EXC_UD);
> +            if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
> +                cr4 = 0;
> +            /*
> +             * Contrary to expectation (i.e. #GP[0]), #UD for the CPL check is
> +             * the documented and observed behaviour.
> +             */
> +            generate_exception_if(!(cr4 & CR4_SMAP) || !mode_ring0(), EXC_UD);

If documentation is to be trusted, then there's no CR4.SMAP check
supposed to be here, but just a CPUID one.

Otoh I assume documentation can't be trusted regarding the use of
prefixes 66, F2, and F3: Just like they're apparently illegal to use with
VMFUNC (thread still pending with Intel) and like documented for e.g.
XGETBV and XSETBV, I would think you need a vex.pfx check here
despite the SDM not explicitly saying so.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index 67495eb..111bb91 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -429,6 +429,7 @@  typedef union {
 #define CR4_OSXMMEXCPT (1<<10)
 #define CR4_UMIP       (1<<11)
 #define CR4_OSXSAVE    (1<<18)
+#define CR4_SMAP       (1<<21)
 
 /* EFLAGS bit definitions. */
 #define EFLG_VIP  (1<<20)
@@ -4362,11 +4363,27 @@  x86_emulate(
 
         switch( modrm )
         {
-#ifdef __XEN__
-        case 0xd1: /* xsetbv */
-        {
             unsigned long cr4;
 
+        case 0xca: /* clac */
+        case 0xcb: /* stac */
+            generate_exception_if(
+                lock_prefix || (_regs.eflags & EFLG_VM), EXC_UD);
+            if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
+                cr4 = 0;
+            /*
+             * Contrary to expectation (i.e. #GP[0]), #UD for the CPL check is
+             * the documented and observed behaviour.
+             */
+            generate_exception_if(!(cr4 & CR4_SMAP) || !mode_ring0(), EXC_UD);
+
+            _regs.eflags &= ~EFLG_AC;
+            if ( modrm == 0xcb )
+                _regs.eflags |= EFLG_AC;
+            goto no_writeback;
+
+#ifdef __XEN__
+        case 0xd1: /* xsetbv */
             generate_exception_if(vex.pfx, EXC_UD);
             if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
                 cr4 = 0;
@@ -4376,7 +4393,6 @@  x86_emulate(
                                                 _regs._eax | (_regs.rdx << 32)),
                                   EXC_GP, 0);
             goto no_writeback;
-        }
 #endif
 
         case 0xd4: /* vmfunc */