xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/2][XTF] FPU test improvements
       [not found]   ` <5A96AB7502000078001EEE26@prv1-mh.provo.novell.com>
@ 2018-10-05 13:28     ` Jan Beulich
  2018-10-05 13:34       ` [PATCH v5 1/2][XTF] add FPU/SIMD register state test Jan Beulich
                         ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jan Beulich @ 2018-10-05 13:28 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel

1: add FPU/SIMD register state test
2: extend FPU exception tests

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



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v5 1/2][XTF] add FPU/SIMD register state test
  2018-10-05 13:28     ` [PATCH v5 0/2][XTF] FPU test improvements Jan Beulich
@ 2018-10-05 13:34       ` Jan Beulich
  2018-10-05 13:34       ` [PATCH v5 2/2][XTF] x86: extend FPU exception tests Jan Beulich
  2018-10-05 13:39       ` [PATCH v5 0/2][XTF] FPU test improvements Andrew Cooper
  2 siblings, 0 replies; 5+ messages in thread
From: Jan Beulich @ 2018-10-05 13:34 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel

Add tests to verify that
- FPU insns leave correct (guest) values in FIP/FDP/FOP/FCS/FDS (at the
  example for FSTPS),
- FPU insns writing memory don't update FPU register state when the
  write faults (at the example of FISTPS),
- VCVTPS2PH doesn't update MXCSR if its write faults (VCVTPS2PH is one
  of the very few SIMD insns writing to memory _and_ updating register
  state; the scatter family of insns also falls into this category).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v5: Add AVX512F variant of VCVTPS2PH test. Guard FDP check with
    !cpu_has_fdp_excp_only.
v3: Re-base. Add entry to all-tests.dox.
v2: Introduce and use x87.h. Tolerate VCVTPS2PH misbehavior on Intel
    hardware. Tolerate AMD oddities in probe_fstp() and probe_fistp().

--- a/arch/x86/include/arch/cpuid.h
+++ b/arch/x86/include/arch/cpuid.h
@@ -80,6 +80,7 @@ static inline bool cpu_has(unsigned int
 #define cpu_has_x2apic          cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave           cpu_has(X86_FEATURE_XSAVE)
 #define cpu_has_avx             cpu_has(X86_FEATURE_AVX)
+#define cpu_has_f16c            cpu_has(X86_FEATURE_F16C)
 
 #define cpu_has_syscall         cpu_has(X86_FEATURE_SYSCALL)
 #define cpu_has_nx              cpu_has(X86_FEATURE_NX)
@@ -90,6 +91,8 @@ static inline bool cpu_has(unsigned int
 
 #define cpu_has_fsgsbase        cpu_has(X86_FEATURE_FSGSBASE)
 #define cpu_has_smep            cpu_has(X86_FEATURE_SMEP)
+#define cpu_has_fdp_excp_only   cpu_has(X86_FEATURE_FDP_EXCP_ONLY)
+#define cpu_has_avx512f         cpu_has(X86_FEATURE_AVX512F)
 #define cpu_has_smap            cpu_has(X86_FEATURE_SMAP)
 
 #define cpu_has_umip            cpu_has(X86_FEATURE_UMIP)
--- /dev/null
+++ b/arch/x86/include/arch/x87.h
@@ -0,0 +1,27 @@
+#ifndef XTF_X86_X87_H
+#define XTF_X86_X87_H
+
+#include <xtf/types.h>
+
+struct x87_env_pm32 {
+    uint16_t cw, :16;
+    uint16_t sw, :16;
+    uint16_t tw, :16;
+    uint32_t ip;
+    uint16_t cs;
+    uint16_t op:11, :5;
+    uint32_t dp;
+    uint16_t ds, :16;
+};
+
+#endif /* XTF_X86_X87_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- a/docs/all-tests.dox
+++ b/docs/all-tests.dox
@@ -20,6 +20,8 @@ and functionality.
 
 @subpage test-fpu-exception-emulation - FPU Exception Emulation.  Covers XSA-190.
 
+@subpage test-fpu-state - FPU state Emulation.
+
 @subpage test-invlpg - `invlpg` instruction behaviour.
 
 @subpage test-lbr-tsx-vmentry - Haswell and later LBR/TSX Vmentry failure test.
--- a/include/xen/arch-x86/cpufeatureset.h
+++ b/include/xen/arch-x86/cpufeatureset.h
@@ -134,6 +134,7 @@
 #define X86_FEATURE_NO_FPU_SEL    (5*32+13) /* FPU CS/DS stored as zero */
 #define X86_FEATURE_MPX           (5*32+14) /* Memory Protection Extensions */
 #define X86_FEATURE_PQE           (5*32+15) /* Platform QoS Enforcement */
+#define X86_FEATURE_AVX512F       (5*32+16) /* AVX-512 Foundation Instructions */
 #define X86_FEATURE_RDSEED        (5*32+18) /* RDSEED instruction */
 #define X86_FEATURE_ADX           (5*32+19) /* ADCX, ADOX instructions */
 #define X86_FEATURE_SMAP          (5*32+20) /* Supervisor Mode Access Prevention */
--- a/include/xen/arch-x86/xen.h
+++ b/include/xen/arch-x86/xen.h
@@ -15,6 +15,16 @@
 
 #include "cpuid.h"
 
+/*
+ * A number of GDT entries are reserved by Xen. These are not situated at the
+ * start of the GDT because some stupid OSes export hard-coded selector values
+ * in their ABI. These hard-coded values are always near the start of the GDT,
+ * so Xen places itself out of the way, at the far end of the GDT.
+ *
+ * NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
+ */
+#define FIRST_RESERVED_GDT_PAGE  14
+
 #ifndef __ASSEMBLY__
 typedef unsigned long xen_pfn_t;
 
--- /dev/null
+++ b/tests/fpu-state/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := fpu-state
+CATEGORY  := functional
+TEST-ENVS := hvm64 hvm32pse
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
--- /dev/null
+++ b/tests/fpu-state/main.c
@@ -0,0 +1,272 @@
+/**
+ * @file tests/fpu-state/main.c
+ * @ref test-fpu-state - Emulation of FPU state
+ *
+ * @page test-fpu-state FPU State Emulation
+ *
+ * FPU code/data pointers and opcode must not be the ones resulting
+ * from the stub execution in the hypervisor.
+ *
+ * FPU and SIMD instructions faulting during memory write must not
+ * update the respective register files.
+ *
+ * @see tests/fpu-state/main.c
+ */
+#include <xtf.h>
+
+#include <arch/exinfo.h>
+#include <arch/x87.h>
+
+const char test_title[] = "FPU State";
+
+void probe_fstp(bool force)
+{
+    const uint8_t *fstp_offs;
+    uint32_t flt;
+    struct x87_env_pm32 fenv;
+
+    fenv.cw = 0x35f; /* unmask PE */
+    asm volatile ( "fninit;"
+                   "fldcw %[cw];"
+                   "fldpi;"
+                   "mov $1f, %[offs];"
+                   "test %[fep], %[fep];"
+                   "jz 1f;"
+                   _ASM_XEN_FEP
+                   "1: fstps %[data]; 2:"
+                   : [offs] "=&g" (fstp_offs), [data] "=m" (flt)
+                   : [cw] "m" (fenv.cw), [fep] "q" (force) );
+
+    asm ( "fnstenv %0" : "=m" (fenv) );
+    if ( fenv.ip != (unsigned long)fstp_offs )
+        xtf_failure("Fail: FIP wrong (%08x)\n", fenv.ip);
+    if ( fenv.cs && fenv.cs != __KERN_CS )
+    {
+#ifdef __x86_64__
+        /*
+         * Tolerate CS being in the hypervisor reserved selector range on
+         * AMD hardware, as their 64-bit {F,}XRSTOR do not appear to clear
+         * FCS/FDS.
+         */
+        if ( vendor_is_amd && !(fenv.cs & X86_SEL_LDT) &&
+             (fenv.cs >> PAGE_SHIFT) == FIRST_RESERVED_GDT_PAGE )
+            xtf_warning("Warning: FCS wrong (%04x)\n", fenv.cs);
+        else
+#endif
+            xtf_failure("Fail: FCS wrong (%04x)\n", fenv.cs);
+    }
+    if ( !cpu_has_fdp_excp_only && fenv.dp != (unsigned long)&flt )
+        xtf_failure("Fail: FDP wrong (%08x)\n", fenv.dp);
+    if ( fenv.ds && fenv.ds != __KERN_DS )
+        xtf_failure("Fail: FDS wrong (%04x)\n", fenv.ds);
+    /* Skip possible opcode prefixes before checking the opcode. */
+    while ( (fstp_offs[0] & ~7) != 0xd8 )
+        ++fstp_offs;
+    if ( fenv.op && fenv.op != (((fstp_offs[0] & 7) << 8) | fstp_offs[1]) )
+        xtf_failure("Fail: FOP wrong (%03x)\n", fenv.op);
+}
+
+void probe_fistp(bool force)
+{
+    unsigned long fldpi_offs;
+    exinfo_t fault = 0;
+    uint16_t fsw;
+    struct x87_env_pm32 fenv;
+    typeof(xtf_failure) *diagfn;
+    const char *prefix;
+
+    asm volatile ( "fninit;"
+                   "0: fldpi;"
+                   "mov $0b, %[offs];"
+                   "test %[fep], %[fep];"
+                   "jz 1f;"
+                   _ASM_XEN_FEP
+                   "1: fistps (%[ptr]); 2:"
+                   _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                   : [offs] "=&g" (fldpi_offs), "+a" (fault)
+                   : [ptr] "r" (0), [fep] "q" (force),
+                     "X" (ex_record_fault_eax) );
+
+    if ( !fault )
+        xtf_error("Error: FISTP to NULL did not fault\n");
+
+    asm ( "fnstsw %0" : "=am" (fsw) );
+    if ( fsw != 0x3800 )
+        xtf_failure("Fail: FSW changed unexpectedly (%04x)\n", fsw);
+
+    asm ( "fnstenv %0" : "=m" (fenv) );
+    /*
+     * The AMD-specific FPU pointer leak workaround in Xen (using FISTPL,
+     * which we check for below) causes all the remaining checks to fail.
+     */
+    if ( !vendor_is_amd || (fenv.op & 0x738) != 0x300 )
+    {
+        diagfn = xtf_failure;
+        prefix = "Fail";
+    }
+    else
+    {
+        diagfn = xtf_warning;
+        prefix = "Warning";
+    }
+    if ( fenv.ip != fldpi_offs )
+        diagfn("%s: FIP changed unexpectedly (%08x)\n", prefix, fenv.ip);
+    if ( fenv.cs && fenv.cs != __KERN_CS )
+        diagfn("%s: FCS changed unexpectedly (%04x)\n", prefix, fenv.cs);
+    if ( fenv.dp )
+        diagfn("%s: FDP changed unexpectedly (%08x)\n", prefix, fenv.dp);
+    if ( fenv.ds )
+        diagfn("%s: FDS changed unexpectedly (%04x)\n", prefix, fenv.ds);
+    if ( fenv.op && fenv.op != 0x1eb )
+        diagfn("%s: FOP changed unexpectedly (%03x)\n", prefix, fenv.op);
+}
+
+void probe_vcvtps2ph_vex(bool force)
+{
+    exinfo_t fault = 0;
+    uint32_t mxcsr = 0x1f80;
+
+    asm volatile ( "vldmxcsr %[mxcsr];"
+                   "vpcmpeqb %%xmm0, %%xmm0, %%xmm0;"
+                   "vpcmpgtb %%xmm0, %%xmm0, %%xmm1;"
+                   "vpunpcklbw %%xmm1, %%xmm0, %%xmm2;"
+                   "test %[fep], %[fep];"
+                   "jz 1f;"
+                   _ASM_XEN_FEP
+                   "1: vcvtps2ph $0, %%xmm2, (%[ptr]); 2:"
+                   _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                   : "+a" (fault)
+                   : [ptr] "r" (0), [mxcsr] "m" (mxcsr), [fep] "q" (force),
+                     "X" (ex_record_fault_eax) );
+
+    if ( !fault )
+        xtf_error("Error: VCVTPS2PH (VEX) to NULL did not fault\n");
+    else if ( exinfo_vec(fault) == X86_EXC_UD )
+    {
+        if ( force )
+            xtf_skip("Emulator does not support VCVTPS2PH (VEX)\n");
+        else
+            xtf_failure("Fail: VCVTPS2PH (VEX) did #UD\n");
+    }
+
+    asm ( "vstmxcsr %0" : "=m" (mxcsr) );
+    if ( mxcsr != 0x1f80 )
+    {
+        /*
+         * Expect AMD hardware and emulation to behave correctly, but tolerate
+         * unexpected behavior on Intel hardware.
+         */
+        if ( force || vendor_is_amd )
+            xtf_failure("Fail: MXCSR changed unexpectedly (%08x)\n", mxcsr);
+        else
+            xtf_warning("Warning: MXCSR changed unexpectedly (%08x)\n", mxcsr);
+    }
+}
+
+void probe_vcvtps2ph_evex(bool force)
+{
+    exinfo_t fault = 0;
+    uint32_t mxcsr = 0x1f80;
+
+    asm volatile ( "vldmxcsr %[mxcsr];"
+                   "vpbroadcastd %[in], %%zmm7;"
+                   "kxnorw %%k0, %%k0, %%k7;"
+                   "test %[fep], %[fep];"
+                   "jz 1f;"
+                   _ASM_XEN_FEP
+                   "1: vcvtps2ph $0,%%zmm7,(%[ptr])%{%%k7%}; 2:"
+                   _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                   : "+a" (fault)
+                   : [ptr] "r" (0), [mxcsr] "m" (mxcsr), [in] "r" (0xff00ff00),
+                     [fep] "q" (force), "X" (ex_record_fault_eax) );
+
+    if ( !fault )
+        xtf_error("Error: VCVTPS2PH (EVEX) to NULL did not fault\n");
+    else if ( exinfo_vec(fault) == X86_EXC_UD )
+    {
+        if ( force )
+            xtf_skip("Emulator does not support VCVTPS2PH (EVEX)\n");
+        else
+            xtf_failure("Fail: VCVTPS2PH (EVEX) did #UD\n");
+    }
+
+    asm ( "vstmxcsr %0" : "=m" (mxcsr) );
+    if ( mxcsr != 0x1f80 )
+    {
+        /*
+         * Expect AMD hardware and emulation to behave correctly, but tolerate
+         * unexpected behavior on Intel hardware.
+         */
+        if ( force || vendor_is_amd )
+            xtf_failure("Fail: MXCSR changed unexpectedly (%08x)\n", mxcsr);
+        else
+            xtf_warning("Warning: MXCSR changed unexpectedly (%08x)\n", mxcsr);
+    }
+}
+
+void run_tests(bool force)
+{
+    if ( cpu_has_fpu )
+    {
+        printk("Testing%s FSTP\n", force ? " emulated" : "");
+        probe_fstp(force);
+
+        printk("Testing%s FISTP (to NULL)\n", force ? " emulated" : "");
+        probe_fistp(force);
+    }
+
+    if ( cpu_has_f16c )
+    {
+        unsigned long cr4 = read_cr4();
+        unsigned long xcr0;
+
+        write_cr4(cr4 | X86_CR4_OSXSAVE);
+        xcr0 = read_xcr0();
+        write_xcr0(xcr0 | XSTATE_SSE | XSTATE_YMM);
+
+        printk("Testing%s VCVTPS2PH (VEX) (to NULL)\n", force ? " emulated" : "");
+        probe_vcvtps2ph_vex(force);
+
+        write_xcr0(xcr0);
+        write_cr4(cr4);
+    }
+
+    if ( cpu_has_avx512f )
+    {
+        unsigned long cr4 = read_cr4();
+        unsigned long xcr0;
+
+        write_cr4(cr4 | X86_CR4_OSXSAVE);
+        xcr0 = read_xcr0();
+        write_xcr0(xcr0 | XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK |
+                   XSTATE_ZMM | XSTATE_HI_ZMM);
+
+        printk("Testing%s VCVTPS2PH (EVEX) (to NULL)\n", force ? " emulated" : "");
+        probe_vcvtps2ph_evex(force);
+
+        write_xcr0(xcr0);
+        write_cr4(cr4);
+    }
+}
+
+void test_main(void)
+{
+    run_tests(false);
+
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+    else
+        run_tests(true);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v5 2/2][XTF] x86: extend FPU exception tests
  2018-10-05 13:28     ` [PATCH v5 0/2][XTF] FPU test improvements Jan Beulich
  2018-10-05 13:34       ` [PATCH v5 1/2][XTF] add FPU/SIMD register state test Jan Beulich
@ 2018-10-05 13:34       ` Jan Beulich
  2018-10-05 13:39       ` [PATCH v5 0/2][XTF] FPU test improvements Andrew Cooper
  2 siblings, 0 replies; 5+ messages in thread
From: Jan Beulich @ 2018-10-05 13:34 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel

Also test #MF and #XM handling.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v4: Re-base.
v3: New.

--- /dev/null
+++ b/arch/x86/include/arch/simd.h
@@ -0,0 +1,32 @@
+#ifndef XTF_X86_SIMD_H
+#define XTF_X86_SIMD_H
+
+#define X86_MXCSR_IE      0x00000001
+#define X86_MXCSR_DE      0x00000002
+#define X86_MXCSR_ZE      0x00000004
+#define X86_MXCSR_OE      0x00000008
+#define X86_MXCSR_UE      0x00000010
+#define X86_MXCSR_PE      0x00000020
+#define X86_MXCSR_DAZ     0x00000040
+#define X86_MXCSR_IM      0x00000080
+#define X86_MXCSR_DM      0x00000100
+#define X86_MXCSR_ZM      0x00000200
+#define X86_MXCSR_OM      0x00000400
+#define X86_MXCSR_UM      0x00000800
+#define X86_MXCSR_PM      0x00001000
+#define X86_MXCSR_RC_MASK 0x00006000
+#define X86_MXCSR_FZ      0x00008000
+
+#define X86_MXCSR_DEFAULT 0x1f80
+
+#endif /* XTF_X86_SIMD_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- a/arch/x86/include/arch/x87.h
+++ b/arch/x86/include/arch/x87.h
@@ -3,6 +3,27 @@
 
 #include <xtf/types.h>
 
+#define X86_FCW_IM      0x0001
+#define X86_FCW_DM      0x0002
+#define X86_FCW_ZM      0x0004
+#define X86_FCW_OM      0x0008
+#define X86_FCW_UM      0x0010
+#define X86_FCW_PM      0x0020
+#define X86_FCW_PC_MASK 0x0300
+#define X86_FCW_RC_MASK 0x0c00
+
+#define X86_PC_SINGLE   0
+#define X86_PC_DOUBLE   2
+#define X86_PC_EXTENDED 3
+
+/* These also apply to MXCSR. */
+#define X86_RC_NEAREST  0
+#define X86_RC_DOWN     1
+#define X86_RC_UP       2
+#define X86_RC_ZERO     3
+
+#define X86_FCW_DEFAULT 0x037f
+
 struct x87_env_pm32 {
     uint16_t cw, :16;
     uint16_t sw, :16;
--- a/tests/fpu-exception-emulation/main.c
+++ b/tests/fpu-exception-emulation/main.c
@@ -22,27 +22,37 @@
  * checking that appropriate exceptions are raised (@#NM or @#UD), or that no
  * exception is raised.
  *
+ * Additionally #MF and #XM behavior is being tested.
+ *
  * Each test is run against real hardware, and forced through the x86
  * instruction emulator (if FEP is available).
  *
  * This test covers XSA-190, where @#NM was not being raised appropriately,
  * therefore interfering with lazy FPU task switching in the guest.
  *
- * @todo Extend to include unmasked pending exceptions.  There is definitely
- * work required in the instruction emulator to support this properly.
- *
  * @see tests/fpu-exception-emulation/main.c
  */
 #include <xtf.h>
+#include <arch/simd.h>
+#include <arch/x87.h>
 
 const char test_title[] = "FPU Exception Emulation";
 
 #define CR0_SYM(...) TOK_OR(X86_CR0_, ##__VA_ARGS__)
-#define CR0_MASK CR0_SYM(EM, MP, TS)
+#define CR0_MASK CR0_SYM(EM, MP, TS, NE)
+
+#define CR4_SYM(...) TOK_OR(X86_CR4_OS, ##__VA_ARGS__)
+#define CR4_MASK CR4_SYM(FXSR, XMMEXCPT, XSAVE)
+
+#define FCW_SYM(...) TOK_OR(X86_FCW_, ##__VA_ARGS__)
+
+#define MXCSR_SYM(...) TOK_OR(X86_MXCSR_, ##__VA_ARGS__)
 
 struct test_cfg
 {
     unsigned long cr0;
+    unsigned long cr4;
+    unsigned int control;
     exinfo_t fault;
 };
 
@@ -54,20 +64,27 @@ static unsigned long default_cr0;
  */
 static const struct test_cfg x87[] =
 {
-    { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM        ), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM,     TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM, MP    ), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(          ), 0, 0,           0 },
+    { CR0_SYM(        TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(    MP    ), 0, 0,           0 },
+    { CR0_SYM(    MP, TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM,     TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM, MP    ), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM, MP, TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(NE),         0, FCW_SYM(IM), EXINFO_SYM(MF, 0) },
 };
 
-exinfo_t probe_x87(bool force)
+exinfo_t probe_x87(unsigned int control, bool force)
 {
     exinfo_t fault = 0;
 
+    if ( control )
+    {
+        control = X86_FCW_DEFAULT & ~control;
+        asm volatile ("fninit; fldcw %0; faddp" :: "m" (control));
+    }
+
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
                   _ASM_XEN_FEP
@@ -77,6 +94,9 @@ exinfo_t probe_x87(bool force)
                   : [fep] "q" (force),
                     "X" (ex_record_fault_eax));
 
+    if ( control )
+        asm volatile ("fnclex");
+
     return fault;
 }
 
@@ -87,20 +107,27 @@ exinfo_t probe_x87(bool force)
  */
 static const struct test_cfg x87_wait[] =
 {
-    { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), 0 },
-    { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM        ), 0 },
-    { CR0_SYM(EM,     TS), 0 },
-    { CR0_SYM(EM, MP    ), 0 },
-    { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(          ), 0, 0,           0 },
+    { CR0_SYM(        TS), 0, 0,           0 },
+    { CR0_SYM(    MP    ), 0, 0,           0 },
+    { CR0_SYM(    MP, TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), 0, 0,           0 },
+    { CR0_SYM(EM,     TS), 0, 0,           0 },
+    { CR0_SYM(EM, MP    ), 0, 0,           0 },
+    { CR0_SYM(EM, MP, TS), 0, 0,           EXINFO_SYM(NM, 0) },
+    { CR0_SYM(NE),         0, FCW_SYM(IM), EXINFO_SYM(MF, 0) },
 };
 
-exinfo_t probe_x87_wait(bool force)
+exinfo_t probe_x87_wait(unsigned int control, bool force)
 {
     exinfo_t fault = 0;
 
+    if ( control )
+    {
+        control = X86_FCW_DEFAULT & ~control;
+        asm volatile ("fninit; fldcw %0; faddp" :: "m" (control));
+    }
+
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
                   _ASM_XEN_FEP
@@ -110,26 +137,29 @@ exinfo_t probe_x87_wait(bool force)
                   : [fep] "q" (force),
                     "X" (ex_record_fault_eax));
 
+    if ( control )
+        asm volatile ("fnclex");
+
     return fault;
 }
 
 /**
- * MMX and SSE instructions.  Emulation is unsupported (thus raising @#UD),
+ * MMX instructions.  Emulation is unsupported (thus raising @#UD),
  * but @#NM should be raised if the task has been switched.
  */
-static const struct test_cfg mmx_sse[] =
+static const struct test_cfg mmx[] =
 {
-    { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM        ), EXINFO_SYM(UD, 0) },
-    { CR0_SYM(EM,     TS), EXINFO_SYM(UD, 0) },
-    { CR0_SYM(EM, MP    ), EXINFO_SYM(UD, 0) },
-    { CR0_SYM(EM, MP, TS), EXINFO_SYM(UD, 0) },
+    { CR0_SYM(          ), 0, 0, 0 },
+    { CR0_SYM(        TS), 0, 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(    MP    ), 0, 0, 0 },
+    { CR0_SYM(    MP, TS), 0, 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), 0, 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM,     TS), 0, 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP    ), 0, 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP, TS), 0, 0, EXINFO_SYM(UD, 0) },
 };
 
-exinfo_t probe_mmx(bool force)
+exinfo_t probe_mmx(unsigned int control, bool force)
 {
     exinfo_t fault = 0;
 
@@ -145,10 +175,56 @@ exinfo_t probe_mmx(bool force)
     return fault;
 }
 
-exinfo_t probe_sse(bool force)
+/**
+ * SSE instructions.  Emulation is unsupported (thus raising @#UD),
+ * but @#NM should be raised if the task has been switched.
+ */
+static const struct test_cfg sse[] =
+{
+    { CR0_SYM(          ), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(        TS), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP    ), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP, TS), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM        ), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM,     TS), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP    ), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP, TS), 0,             0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(          ), CR4_SYM(FXSR), 0, 0 },
+    { CR0_SYM(        TS), CR4_SYM(FXSR), 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(    MP    ), CR4_SYM(FXSR), 0, 0 },
+    { CR0_SYM(    MP, TS), CR4_SYM(FXSR), 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), CR4_SYM(FXSR), 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM,     TS), CR4_SYM(FXSR), 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP    ), CR4_SYM(FXSR), 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP, TS), CR4_SYM(FXSR), 0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP    ), CR4_SYM(FXSR),
+      MXCSR_SYM(IM),                         EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP    ), CR4_SYM(FXSR, XMMEXCPT),
+      MXCSR_SYM(IM),                         EXINFO_SYM(XM, 0) },
+};
+
+exinfo_t probe_sse(unsigned int control, bool force)
 {
     exinfo_t fault = 0;
 
+    if ( control )
+    {
+        control = X86_MXCSR_DEFAULT & ~control;
+        asm volatile ("0: xorps %%xmm0, %%xmm0;"
+                      "ldmxcsr %[mxcsr];"
+                      "test %[fep], %[fep];"
+                      "jz 1f;"
+                      _ASM_XEN_FEP
+                      "1: divps %%xmm0, %%xmm0; 2:"
+                      _ASM_EXTABLE_HANDLER(0b, 2b, ex_record_fault_eax)
+                      _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                      : "+a" (fault)
+                      : [mxcsr] "m" (control),
+                        [fep] "q" (force),
+                        "X" (ex_record_fault_eax));
+        return fault;
+    }
+
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
                   _ASM_XEN_FEP
@@ -167,17 +243,25 @@ exinfo_t probe_sse(bool force)
  */
 static const struct test_cfg avx[] =
 {
-    { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM        ), 0 },
-    { CR0_SYM(EM,     TS), EXINFO_SYM(NM, 0) },
-    { CR0_SYM(EM, MP    ), 0 },
-    { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(          ), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(        TS), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP    ), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(    MP, TS), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM        ), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM,     TS), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP    ), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP, TS), 0,              0, EXINFO_SYM(UD, 0) },
+    { CR0_SYM(          ), CR4_SYM(XSAVE), 0, 0 },
+    { CR0_SYM(        TS), CR4_SYM(XSAVE), 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(    MP    ), CR4_SYM(XSAVE), 0, 0 },
+    { CR0_SYM(    MP, TS), CR4_SYM(XSAVE), 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), CR4_SYM(XSAVE), 0, 0 },
+    { CR0_SYM(EM,     TS), CR4_SYM(XSAVE), 0, EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM, MP    ), CR4_SYM(XSAVE), 0, 0 },
+    { CR0_SYM(EM, MP, TS), CR4_SYM(XSAVE), 0, EXINFO_SYM(NM, 0) },
 };
 
-static exinfo_t probe_avx(bool force)
+static exinfo_t probe_avx(unsigned int control, bool force)
 {
     exinfo_t fault = 0;
 
@@ -194,29 +278,41 @@ static exinfo_t probe_avx(bool force)
 }
 
 void run_sequence(const struct test_cfg *seq, unsigned int nr,
-                  unsigned int (*fn)(bool), bool force, exinfo_t override)
+                  unsigned int (*fn)(unsigned int, bool), bool force,
+                  exinfo_t override)
 {
     unsigned int i;
 
     for ( i = 0; i < nr; ++i )
     {
         const struct test_cfg *t = &seq[i];
+        unsigned long cr4 = read_cr4();
         exinfo_t res, exp = override ?: t->fault;
 
         write_cr0((default_cr0 & ~CR0_MASK) | t->cr0);
-        res = fn(force);
+        write_cr4((cr4 & ~CR4_MASK) | t->cr4);
+
+        res = fn(t->control, force);
+
+        write_cr4(cr4);
 
         if ( res != exp )
         {
-            char cr0str[12];
+            char cr0str[12], cr4str[24];
 
             snprintf(cr0str, sizeof(cr0str), "%s%s%s",
                      t->cr0 & X86_CR0_EM ? " EM" : "",
                      t->cr0 & X86_CR0_MP ? " MP" : "",
                      t->cr0 & X86_CR0_TS ? " TS" : "");
 
-            xtf_failure("  Expected %pe, got %pe (cr0:%s)\n",
-                        _p(exp), _p(res), cr0str[0] ? cr0str : " - ");
+            snprintf(cr4str, sizeof(cr4str), "%s%s%s",
+                     t->cr4 & X86_CR4_OSFXSR     ? " FXSR"    : "",
+                     t->cr4 & X86_CR4_OSXMMEXCPT ? " XMMXCPT" : "",
+                     t->cr4 & X86_CR4_OSXSAVE    ? " XSAVE"   : "");
+
+            xtf_failure("  Expected %pe, got %pe (cr0:%s cr4:%s ctrl:%04x)\n",
+                        _p(exp), _p(res), cr0str[0] ? cr0str : " - ",
+                        cr4str[0] ? cr4str : " - ", t->control);
         }
     }
 }
@@ -235,23 +331,13 @@ void run_tests(bool force)
     if ( cpu_has_mmx )
     {
         printk("Testing%s MMX\n", force ? " emulated" : "");
-        run_sequence(mmx_sse, ARRAY_SIZE(mmx_sse), probe_mmx, force, 0);
+        run_sequence(mmx, ARRAY_SIZE(mmx), probe_mmx, force, 0);
     }
 
     if ( cpu_has_sse )
     {
-        unsigned long cr4 = read_cr4();
-
         printk("Testing%s SSE\n", force ? " emulated" : "");
-        write_cr4(cr4 & ~X86_CR4_OSFXSR);
-        run_sequence(mmx_sse, ARRAY_SIZE(mmx_sse), probe_sse, force,
-                     EXINFO_SYM(UD, 0));
-
-        printk("Testing%s SSE (CR4.OSFXSR)\n", force ? " emulated" : "");
-        write_cr4(cr4 | X86_CR4_OSFXSR);
-        run_sequence(mmx_sse, ARRAY_SIZE(mmx_sse), probe_sse, force, 0);
-
-        write_cr4(cr4);
+        run_sequence(sse, ARRAY_SIZE(sse), probe_sse, force, 0);
     }
 
     if ( cpu_has_avx )
@@ -259,19 +345,15 @@ void run_tests(bool force)
         unsigned long cr4 = read_cr4();
         unsigned long xcr0;
 
-        printk("Testing%s AVX\n", force ? " emulated" : "");
-        write_cr4(cr4 & ~X86_CR4_OSXSAVE);
-        run_sequence(avx, ARRAY_SIZE(avx), probe_avx, force,
-                     EXINFO_SYM(UD, 0));
-
-        printk("Testing%s AVX (CR4.OSXSAVE)\n", force ? " emulated" : "");
         write_cr4(cr4 | X86_CR4_OSXSAVE);
         xcr0 = read_xcr0();
+
+        printk("Testing%s AVX\n", force ? " emulated" : "");
         write_xcr0(xcr0 & ~XSTATE_YMM);
         run_sequence(avx, ARRAY_SIZE(avx), probe_avx, force,
                      EXINFO_SYM(UD, 0));
 
-        printk("Testing%s AVX (CR4.OSXSAVE+XCR0.YMM)\n", force ? " emulated" : "");
+        printk("Testing%s AVX (XCR0.YMM)\n", force ? " emulated" : "");
         write_xcr0(xcr0 | XSTATE_SSE | XSTATE_YMM);
         run_sequence(avx, ARRAY_SIZE(avx), probe_avx, force, 0);
 




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 0/2][XTF] FPU test improvements
  2018-10-05 13:28     ` [PATCH v5 0/2][XTF] FPU test improvements Jan Beulich
  2018-10-05 13:34       ` [PATCH v5 1/2][XTF] add FPU/SIMD register state test Jan Beulich
  2018-10-05 13:34       ` [PATCH v5 2/2][XTF] x86: extend FPU exception tests Jan Beulich
@ 2018-10-05 13:39       ` Andrew Cooper
  2018-10-05 13:45         ` Jan Beulich
  2 siblings, 1 reply; 5+ messages in thread
From: Andrew Cooper @ 2018-10-05 13:39 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel

On 05/10/18 14:28, Jan Beulich wrote:
> 1: add FPU/SIMD register state test
> 2: extend FPU exception tests
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Thanks.  However, I need to get the incremental test version logic
working first, or OSSTest will block this on older versions of Xen, due
to (falsely) believing that there has been a regression.

I'll queue these changes once the requisite infrastructure is in place.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 0/2][XTF] FPU test improvements
  2018-10-05 13:39       ` [PATCH v5 0/2][XTF] FPU test improvements Andrew Cooper
@ 2018-10-05 13:45         ` Jan Beulich
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Beulich @ 2018-10-05 13:45 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel

>>> On 05.10.18 at 15:39, <andrew.cooper3@citrix.com> wrote:
> On 05/10/18 14:28, Jan Beulich wrote:
>> 1: add FPU/SIMD register state test
>> 2: extend FPU exception tests
>>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> Thanks.  However, I need to get the incremental test version logic
> working first, or OSSTest will block this on older versions of Xen, due
> to (falsely) believing that there has been a regression.

I can see why patch 2 has such a dependency, but patch 1 introduces
a brand new test.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-10-05 13:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <5A96B98502000078001ACC73@prv1-mh.provo.novell.com>
     [not found] ` <5A96AB7502000000000F6BA7@prv1-mh.provo.novell.com>
     [not found]   ` <5A96AB7502000078001EEE26@prv1-mh.provo.novell.com>
2018-10-05 13:28     ` [PATCH v5 0/2][XTF] FPU test improvements Jan Beulich
2018-10-05 13:34       ` [PATCH v5 1/2][XTF] add FPU/SIMD register state test Jan Beulich
2018-10-05 13:34       ` [PATCH v5 2/2][XTF] x86: extend FPU exception tests Jan Beulich
2018-10-05 13:39       ` [PATCH v5 0/2][XTF] FPU test improvements Andrew Cooper
2018-10-05 13:45         ` Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).