[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86emul/test: wrap libc functions with FPU save/restore code



Currently with the native tool chain on Debian Jessie ./test_x86_emulator
yields:

  Testing AVX2 256bit single native execution...okay
  Testing AVX2 256bit single 64-bit code sequence...[line 933] failed!

The bug is that libc's memcpy() in read() uses %xmm8 (specifically, in
__memcpy_sse2_unaligned()), which corrupts %ymm8 behind the back of the AVX2
test code.

Introduce wrappers (and machinery to forward calls to those wrappers)
saving/restoring FPU state around certain library calls.

Reported-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
Obviously requires Andrew's "tests/x86emul: Helpers to save and restore
FPU state" as a prereq.

--- a/tools/fuzz/x86_instruction_emulator/Makefile
+++ b/tools/fuzz/x86_instruction_emulator/Makefile
@@ -18,7 +18,7 @@ asm:
 
 asm/%: asm ;
 
-x86-emulate.c x86-emulate.h: %:
+x86-emulate.c x86-emulate.h wrappers.c: %:
        [ -L $* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/$*
 
 CFLAGS += $(CFLAGS_xeninclude) -D__XEN_TOOLS__ -I.
@@ -38,10 +38,10 @@ fuzz-emul.o fuzz-emulate-cov.o: $(x86_em
 x86-insn-fuzzer.a: fuzz-emul.o x86-emulate.o
        $(AR) rc $@ $^
 
-afl-harness: afl-harness.o fuzz-emul.o x86-emulate.o
+afl-harness: afl-harness.o fuzz-emul.o x86-emulate.o wrappers.o
        $(CC) $(CFLAGS) $^ -o $@
 
-afl-harness-cov: afl-harness-cov.o fuzz-emul-cov.o x86-emulate-cov.o
+afl-harness-cov: afl-harness-cov.o fuzz-emul-cov.o x86-emulate-cov.o wrappers.o
        $(CC) $(CFLAGS) $(GCOV_FLAGS) $^ -o $@
 
 # Common targets
--- a/tools/tests/x86_emulator/Makefile
+++ b/tools/tests/x86_emulator/Makefile
@@ -103,7 +103,7 @@ $(addsuffix .o,$(SIMD) $(FMA) $(SG)): si
 
 xop.o: simd-fma.c
 
-$(TARGET): x86-emulate.o test_x86_emulator.o
+$(TARGET): x86-emulate.o test_x86_emulator.o wrappers.o
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
 
 .PHONY: clean
@@ -133,8 +133,10 @@ HOSTCFLAGS += $(CFLAGS_xeninclude) -I. $
 x86.h := asm/x86-vendors.h asm/x86-defns.h asm/msr-index.h
 x86_emulate.h := x86-emulate.h x86_emulate/x86_emulate.h $(x86.h)
 
-x86-emulate.o: x86-emulate.c x86_emulate/x86_emulate.c $(x86_emulate.h)
-       $(HOSTCC) $(HOSTCFLAGS) -D__XEN_TOOLS__ -c -g -o $@ $<
-
-test_x86_emulator.o: test_x86_emulator.c $(addsuffix .h,$(TESTCASES)) 
$(x86_emulate.h)
+x86-emulate.o test_x86_emulator.o wrappers.o: %.o: %.c $(x86_emulate.h)
        $(HOSTCC) $(HOSTCFLAGS) -c -g -o $@ $<
+
+x86-emulate.o: x86_emulate/x86_emulate.c
+x86-emulate.o: HOSTCFLAGS += -D__XEN_TOOLS__
+
+test_x86_emulator.o: $(addsuffix .h,$(TESTCASES))
--- /dev/null
+++ b/tools/tests/x86_emulator/wrappers.c
@@ -0,0 +1,79 @@
+#include <stdarg.h>
+#include <stdio.h>
+
+#define WRAP(x) typeof(x) emul_##x
+#include "x86-emulate.h"
+
+size_t emul_fwrite(const void *src, size_t sz, size_t n, FILE *f)
+{
+    emul_save_fpu_state();
+    sz = fwrite(src, sz, n, f);
+    emul_restore_fpu_state();
+
+    return sz;
+}
+
+int emul_memcmp(const void *p1, const void *p2, size_t sz)
+{
+    int rc;
+
+    emul_save_fpu_state();
+    rc = memcmp(p1, p2, sz);
+    emul_restore_fpu_state();
+
+    return rc;
+}
+
+void *emul_memcpy(void *dst, const void *src, size_t sz)
+{
+    emul_save_fpu_state();
+    memcpy(dst, src, sz);
+    emul_restore_fpu_state();
+
+    return dst;
+}
+
+void *emul_memset(void *dst, int c, size_t sz)
+{
+    emul_save_fpu_state();
+    memset(dst, c, sz);
+    emul_restore_fpu_state();
+
+    return dst;
+}
+
+int emul_printf(const char *fmt, ...)
+{
+    va_list varg;
+    int rc;
+
+    emul_save_fpu_state();
+    va_start(varg, fmt);
+    rc = vprintf(fmt, varg);
+    va_end(varg);
+    emul_restore_fpu_state();
+
+    return rc;
+}
+
+int emul_putchar(int c)
+{
+    int rc;
+
+    emul_save_fpu_state();
+    rc = putchar(c);
+    emul_restore_fpu_state();
+
+    return rc;
+}
+
+int emul_puts(const char *str)
+{
+    int rc;
+
+    emul_save_fpu_state();
+    rc = puts(str);
+    emul_restore_fpu_state();
+
+    return rc;
+}
--- a/tools/tests/x86_emulator/x86-emulate.h
+++ b/tools/tests/x86_emulator/x86-emulate.h
@@ -56,6 +56,29 @@ bool emul_test_init(void);
 void emul_save_fpu_state(void);
 void emul_restore_fpu_state(void);
 
+/*
+ * In order to reasonably use the above, wrap library calls we use and which we
+ * think might access any of the FPU state into wrappers saving/restoring state
+ * around the actual function.
+ */
+#ifndef WRAP
+# if 0 /* This only works for explicit calls, not for compiler generated ones. 
*/
+#  define WRAP(x) typeof(x) x asm("emul_" #x)
+# else
+# define WRAP(x) asm(".equ " #x ", emul_" #x)
+# endif
+#endif
+
+WRAP(fwrite);
+WRAP(memcmp);
+WRAP(memcpy);
+WRAP(memset);
+WRAP(printf);
+WRAP(putchar);
+WRAP(puts);
+
+#undef WRAP
+
 #include "x86_emulate/x86_emulate.h"
 
 static inline uint64_t xgetbv(uint32_t xcr)



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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.