All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions
@ 2019-05-23 20:43 Jan Bobek
  2019-05-23 20:43 ` [Qemu-devel] [RISU v3 01/11] Makefile: undefine the arch name symbol Jan Bobek
                   ` (12 more replies)
  0 siblings, 13 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

This patch series adds support for i386 and x86_64 architectures to
RISU. Notably, vector registers (SSE, AVX, AVX-512) are supported for
verification of the apprentice. This is V3 of the series posted in [1]
and [2].

Changes is V3:
  - fix a matching bug caused by misplaced index multiplication [3]
  - print an error and exit when parse of the --xfeatures option fails [4]

References:
  1. https://lists.nongnu.org/archive/html/qemu-devel/2019-04/msg01294.html
  2. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04089.html
  3. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04922.html
  4. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04903.html

Jan Bobek (10):
  Makefile: undefine the arch name symbol
  risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h
  risu_i386: move reginfo-related code to risu_reginfo_i386.c
  risu_reginfo_i386: implement arch-specific reginfo interface
  risu_i386: implement missing CPU-specific functions
  risu_i386: remove old unused code
  test_i386: change syntax from nasm to gas
  configure: add i386/x86_64 architectures
  risu_reginfo_i386: replace xfeature constants with symbolic names
  risu_reginfo_i386: rework --xfeatures value parsing

Richard Henderson (1):
  i386: Add avx512 state to reginfo_t

 configure           |  10 +-
 Makefile            |   5 +-
 risu_reginfo_i386.h |  49 ++++++
 risu_i386.c         | 142 ++--------------
 risu_reginfo_i386.c | 400 ++++++++++++++++++++++++++++++++++++++++++++
 test_i386.S         |  80 +++++++++
 test_i386.s         |  27 ---
 7 files changed, 556 insertions(+), 157 deletions(-)
 create mode 100644 risu_reginfo_i386.h
 create mode 100644 risu_reginfo_i386.c
 create mode 100644 test_i386.S
 delete mode 100644 test_i386.s

-- 
2.20.1



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

* [Qemu-devel] [RISU v3 01/11] Makefile: undefine the arch name symbol
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
@ 2019-05-23 20:43 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 02/11] risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h Jan Bobek
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

At least GCC defines the symbol "i386" to 1 to signal the target
platform. We need to use "i386" as an undefined symbol in order to
correctly include risu_reginfo_i386.h from risu.h. Add an -U option to
the build command to make sure the symbol remains undefined.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 4aad448..b362dbe 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ VPATH=$(SRCDIR)
 
 CFLAGS ?= -g
 
-ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) $(BUILD_INC) $(CFLAGS) $(EXTRA_CFLAGS)
+ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) -U$(ARCH) $(BUILD_INC) $(CFLAGS) $(EXTRA_CFLAGS)
 
 PROG=risu
 SRCS=risu.c comms.c reginfo.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 02/11] risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
  2019-05-23 20:43 ` [Qemu-devel] [RISU v3 01/11] Makefile: undefine the arch name symbol Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 03/11] risu_i386: move reginfo-related code to risu_reginfo_i386.c Jan Bobek
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

In order to build risu successfully for i386, we need files
risu_reginfo_i386.{h,c}; this patch adds the former by extracting the
relevant code from risu_i386.c.

This patch is pure code motion; no functional changes were made.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_reginfo_i386.h | 37 +++++++++++++++++++++++++++++++++++++
 risu_i386.c         | 23 +----------------------
 2 files changed, 38 insertions(+), 22 deletions(-)
 create mode 100644 risu_reginfo_i386.h

diff --git a/risu_reginfo_i386.h b/risu_reginfo_i386.h
new file mode 100644
index 0000000..5bba439
--- /dev/null
+++ b/risu_reginfo_i386.h
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Peter Maydell (Linaro) - initial implementation
+ ******************************************************************************/
+
+#ifndef RISU_REGINFO_I386_H
+#define RISU_REGINFO_I386_H
+
+/* This is the data structure we pass over the socket.
+ * It is a simplified and reduced subset of what can
+ * be obtained with a ucontext_t*
+ */
+struct reginfo {
+    uint32_t faulting_insn;
+    gregset_t gregs;
+};
+
+#ifndef REG_GS
+/* Assume that either we get all these defines or none */
+#   define REG_GS      0
+#   define REG_FS      1
+#   define REG_ES      2
+#   define REG_DS      3
+#   define REG_ESP     7
+#   define REG_TRAPNO 12
+#   define REG_EIP    14
+#   define REG_EFL    16
+#   define REG_UESP   17
+#endif /* !defined(REG_GS) */
+
+#endif /* RISU_REGINFO_I386_H */
diff --git a/risu_i386.c b/risu_i386.c
index 5e7e01d..6798a78 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -14,28 +14,7 @@
 #include <string.h>
 
 #include "risu.h"
-
-/* This is the data structure we pass over the socket.
- * It is a simplified and reduced subset of what can
- * be obtained with a ucontext_t*
- */
-struct reginfo {
-    uint32_t faulting_insn;
-    gregset_t gregs;
-};
-
-#ifndef REG_GS
-/* Assume that either we get all these defines or none */
-#define REG_GS 0
-#define REG_FS 1
-#define REG_ES 2
-#define REG_DS 3
-#define REG_ESP 7
-#define REG_TRAPNO 12
-#define REG_EIP 14
-#define REG_EFL 16
-#define REG_UESP 17
-#endif
+#include "risu_reginfo_i386.h"
 
 struct reginfo master_ri, apprentice_ri;
 
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 03/11] risu_i386: move reginfo-related code to risu_reginfo_i386.c
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
  2019-05-23 20:43 ` [Qemu-devel] [RISU v3 01/11] Makefile: undefine the arch name symbol Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 02/11] risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 04/11] risu_reginfo_i386: implement arch-specific reginfo interface Jan Bobek
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

In order to build risu successfully for i386, we need files
risu_reginfo_i386.{h,c}; this patch adds the latter by extracting the
relevant code from risu_i386.c.

This patch is pure code motion; no functional changes were made.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_i386.c         | 54 -----------------------------------
 risu_reginfo_i386.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 54 deletions(-)
 create mode 100644 risu_reginfo_i386.c

diff --git a/risu_i386.c b/risu_i386.c
index 6798a78..2d2f325 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -33,43 +33,6 @@ void advance_pc(void *vuc)
     uc->uc_mcontext.gregs[REG_EIP] += 2;
 }
 
-static void fill_reginfo(struct reginfo *ri, ucontext_t * uc)
-{
-    int i;
-    for (i = 0; i < NGREG; i++) {
-        switch (i) {
-        case REG_ESP:
-        case REG_UESP:
-        case REG_GS:
-        case REG_FS:
-        case REG_ES:
-        case REG_DS:
-        case REG_TRAPNO:
-        case REG_EFL:
-            /* Don't store these registers as it results in mismatches.
-             * In particular valgrind has different values for some
-             * segment registers, and they're boring anyway.
-             * We really shouldn't be ignoring EFL but valgrind doesn't
-             * seem to set it right and I don't care to investigate.
-             */
-            ri->gregs[i] = 0xDEADBEEF;
-            break;
-        case REG_EIP:
-            /* Store the offset from the start of the test image */
-            ri->gregs[i] = uc->uc_mcontext.gregs[i] - image_start_address;
-            break;
-        default:
-            ri->gregs[i] = uc->uc_mcontext.gregs[i];
-            break;
-        }
-    }
-    /* x86 insns aren't 32 bit but we're not really testing x86 so
-     * this is just to distinguish 'do compare' from 'stop'
-     */
-    ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.gregs[REG_EIP]);
-}
-
-
 int send_register_info(int sock, void *uc)
 {
     struct reginfo ri;
@@ -100,23 +63,6 @@ int recv_and_compare_register_info(int sock, void *uc)
     return resp;
 }
 
-static char *regname[] = {
-    "GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP",
-    "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP",
-    "CS", "EFL", "UESP", "SS", 0
-};
-
-static void dump_reginfo(struct reginfo *ri)
-{
-    int i;
-    fprintf(stderr, "  faulting insn %x\n", ri->faulting_insn);
-    for (i = 0; i < NGREG; i++) {
-        fprintf(stderr, "  %s: %x\n", regname[i] ? regname[i] : "???",
-                ri->gregs[i]);
-    }
-}
-
-
 /* Print a useful report on the status of the last comparison
  * done in recv_and_compare_register_info(). This is called on
  * exit, so need not restrict itself to signal-safe functions.
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
new file mode 100644
index 0000000..e8d671f
--- /dev/null
+++ b/risu_reginfo_i386.c
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Peter Maydell (Linaro) - initial implementation
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <ucontext.h>
+
+#include "risu.h"
+#include "risu_reginfo_i386.h"
+
+static void fill_reginfo(struct reginfo *ri, ucontext_t * uc)
+{
+    int i;
+    for (i = 0; i < NGREG; i++) {
+        switch (i) {
+        case REG_ESP:
+        case REG_UESP:
+        case REG_GS:
+        case REG_FS:
+        case REG_ES:
+        case REG_DS:
+        case REG_TRAPNO:
+        case REG_EFL:
+            /* Don't store these registers as it results in mismatches.
+             * In particular valgrind has different values for some
+             * segment registers, and they're boring anyway.
+             * We really shouldn't be ignoring EFL but valgrind doesn't
+             * seem to set it right and I don't care to investigate.
+             */
+            ri->gregs[i] = 0xDEADBEEF;
+            break;
+        case REG_EIP:
+            /* Store the offset from the start of the test image */
+            ri->gregs[i] = uc->uc_mcontext.gregs[i] - image_start_address;
+            break;
+        default:
+            ri->gregs[i] = uc->uc_mcontext.gregs[i];
+            break;
+        }
+    }
+    /* x86 insns aren't 32 bit but we're not really testing x86 so
+     * this is just to distinguish 'do compare' from 'stop'
+     */
+    ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.gregs[REG_EIP]);
+}
+
+static char *regname[] = {
+    "GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP",
+    "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP",
+    "CS", "EFL", "UESP", "SS", 0
+};
+
+static void dump_reginfo(struct reginfo *ri)
+{
+    int i;
+    fprintf(stderr, "  faulting insn %x\n", ri->faulting_insn);
+    for (i = 0; i < NGREG; i++) {
+        fprintf(stderr, "  %s: %x\n", regname[i] ? regname[i] : "???",
+                ri->gregs[i]);
+    }
+}
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 04/11] risu_reginfo_i386: implement arch-specific reginfo interface
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (2 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 03/11] risu_i386: move reginfo-related code to risu_reginfo_i386.c Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 05/11] risu_i386: implement missing CPU-specific functions Jan Bobek
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

CPU-specific code in risu_reginfo_* is expected to define and export
the following symbols:

- arch_long_opts, arch_extra_help, process_arch_opt
- reginfo_size
- reginfo_init
- reginfo_is_eq
- reginfo_dump, reginfo_dump_mismatch

Make risu_reginfo_i386.c implement this interface; and while we're at
it, expand the support to x86_64 as well.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_reginfo_i386.h |  24 ++++----
 risu_reginfo_i386.c | 147 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 127 insertions(+), 44 deletions(-)

diff --git a/risu_reginfo_i386.h b/risu_reginfo_i386.h
index 5bba439..e350f01 100644
--- a/risu_reginfo_i386.h
+++ b/risu_reginfo_i386.h
@@ -12,7 +12,8 @@
 #ifndef RISU_REGINFO_I386_H
 #define RISU_REGINFO_I386_H
 
-/* This is the data structure we pass over the socket.
+/*
+ * This is the data structure we pass over the socket.
  * It is a simplified and reduced subset of what can
  * be obtained with a ucontext_t*
  */
@@ -21,17 +22,14 @@ struct reginfo {
     gregset_t gregs;
 };
 
-#ifndef REG_GS
-/* Assume that either we get all these defines or none */
-#   define REG_GS      0
-#   define REG_FS      1
-#   define REG_ES      2
-#   define REG_DS      3
-#   define REG_ESP     7
-#   define REG_TRAPNO 12
-#   define REG_EIP    14
-#   define REG_EFL    16
-#   define REG_UESP   17
-#endif /* !defined(REG_GS) */
+/*
+ * For i386, the defines are named REG_EAX, etc.
+ * For x86_64, the defines are named REG_RAX, etc.
+ */
+#ifdef __x86_64__
+# define REG_E(X)   REG_R##X
+#else
+# define REG_E(X)   REG_E##X
+#endif
 
 #endif /* RISU_REGINFO_I386_H */
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index e8d671f..c4dc14a 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -10,59 +10,144 @@
  ******************************************************************************/
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <ucontext.h>
+#include <assert.h>
 
 #include "risu.h"
 #include "risu_reginfo_i386.h"
 
-static void fill_reginfo(struct reginfo *ri, ucontext_t * uc)
+const struct option * const arch_long_opts;
+const char * const arch_extra_help;
+
+void process_arch_opt(int opt, const char *arg)
+{
+    abort();
+}
+
+const int reginfo_size(void)
+{
+    return sizeof(struct reginfo);
+}
+
+/* reginfo_init: initialize with a ucontext */
+void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 {
     int i;
+
+    memset(ri, 0, sizeof(*ri));
+
     for (i = 0; i < NGREG; i++) {
         switch (i) {
-        case REG_ESP:
-        case REG_UESP:
-        case REG_GS:
-        case REG_FS:
-        case REG_ES:
-        case REG_DS:
-        case REG_TRAPNO:
-        case REG_EFL:
-            /* Don't store these registers as it results in mismatches.
-             * In particular valgrind has different values for some
-             * segment registers, and they're boring anyway.
-             * We really shouldn't be ignoring EFL but valgrind doesn't
-             * seem to set it right and I don't care to investigate.
-             */
-            ri->gregs[i] = 0xDEADBEEF;
-            break;
-        case REG_EIP:
-            /* Store the offset from the start of the test image */
+        case REG_E(IP):
+            /* Store the offset from the start of the test image.  */
             ri->gregs[i] = uc->uc_mcontext.gregs[i] - image_start_address;
             break;
-        default:
+        case REG_EFL:
+            /* Store only the "flaggy" bits: SF, ZF, AF, PF, CF.  */
+            ri->gregs[i] = uc->uc_mcontext.gregs[i] & 0xd5;
+            break;
+        case REG_E(SP):
+            /* Ignore the stack.  */
+            ri->gregs[i] = 0xdeadbeef;
+            break;
+        case REG_E(AX):
+        case REG_E(BX):
+        case REG_E(CX):
+        case REG_E(DX):
+        case REG_E(DI):
+        case REG_E(SI):
+        case REG_E(BP):
+#ifdef __x86_64__
+        case REG_R8:
+        case REG_R9:
+        case REG_R10:
+        case REG_R11:
+        case REG_R12:
+        case REG_R13:
+        case REG_R14:
+        case REG_R15:
+#endif
             ri->gregs[i] = uc->uc_mcontext.gregs[i];
             break;
         }
     }
-    /* x86 insns aren't 32 bit but we're not really testing x86 so
-     * this is just to distinguish 'do compare' from 'stop'
+
+    /*
+     * x86 insns aren't 32 bit but 3 bytes are sufficient to
+     * distinguish 'do compare' from 'stop'.
      */
-    ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.gregs[REG_EIP]);
+    ri->faulting_insn = *(uint32_t *)uc->uc_mcontext.gregs[REG_E(IP)];
 }
 
-static char *regname[] = {
-    "GS", "FS", "ES", "DS", "EDI", "ESI", "EBP", "ESP",
-    "EBX", "EDX", "ECX", "EAX", "TRAPNO", "ERR", "EIP",
-    "CS", "EFL", "UESP", "SS", 0
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
+{
+    return 0 == memcmp(m, a, sizeof(*m));
+}
+
+static const char *const regname[NGREG] = {
+    [REG_EFL] = "eflags",
+#ifdef __x86_64__
+    [REG_RIP] = "rip",
+    [REG_RAX] = "rax",
+    [REG_RBX] = "rbx",
+    [REG_RCX] = "rcx",
+    [REG_RDX] = "rdx",
+    [REG_RDI] = "rdi",
+    [REG_RSI] = "rsi",
+    [REG_RBP] = "rbp",
+    [REG_RSP] = "rsp",
+    [REG_R8]  = "r8",
+    [REG_R9]  = "r9",
+    [REG_R10] = "r10",
+    [REG_R11] = "r11",
+    [REG_R12] = "r12",
+    [REG_R13] = "r13",
+    [REG_R14] = "r14",
+    [REG_R15] = "r15",
+#else
+    [REG_EIP] = "eip",
+    [REG_EAX] = "eax",
+    [REG_EBX] = "ebx",
+    [REG_ECX] = "ecx",
+    [REG_EDX] = "edx",
+    [REG_EDI] = "edi",
+    [REG_ESI] = "esi",
+    [REG_EBP] = "ebp",
+    [REG_ESP] = "esp",
+#endif
 };
 
-static void dump_reginfo(struct reginfo *ri)
+#ifdef __x86_64__
+# define PRIxREG   "%016llx"
+#else
+# define PRIxREG   "%08x"
+#endif
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+int reginfo_dump(struct reginfo *ri, FILE *f)
 {
     int i;
-    fprintf(stderr, "  faulting insn %x\n", ri->faulting_insn);
+    fprintf(f, "  faulting insn %x\n", ri->faulting_insn);
     for (i = 0; i < NGREG; i++) {
-        fprintf(stderr, "  %s: %x\n", regname[i] ? regname[i] : "???",
-                ri->gregs[i]);
+        if (regname[i]) {
+            fprintf(f, "  %-6s: " PRIxREG "\n", regname[i], ri->gregs[i]);
+        }
     }
+    return !ferror(f);
+}
+
+int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
+{
+    int i;
+    for (i = 0; i < NGREG; i++) {
+        if (m->gregs[i] != a->gregs[i]) {
+            assert(regname[i]);
+            fprintf(f, "Mismatch: %s: " PRIxREG " v " PRIxREG "\n",
+                    regname[i], m->gregs[i], a->gregs[i]);
+        }
+    }
+    return !ferror(f);
 }
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 05/11] risu_i386: implement missing CPU-specific functions
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (3 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 04/11] risu_reginfo_i386: implement arch-specific reginfo interface Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 06/11] risu_i386: remove old unused code Jan Bobek
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

risu_i386.c is expected to implement the following functions:

- advance_pc
- get_reginfo_paramreg, set_ucontext_paramreg
- get_risuop
- get_pc

This patch adds the necessary code. We use EAX as the parameter
register and opcode "UD1 %xxx,%eax" for triggering RISU actions.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_i386.c | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/risu_i386.c b/risu_i386.c
index 2d2f325..06d95e5 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -25,12 +25,37 @@ static int insn_is_ud2(uint32_t insn)
 
 void advance_pc(void *vuc)
 {
-    /* We assume that this is either UD1 or UD2.
-     * This would need tweaking if we want to test
-     * expected undefs on x86.
+    ucontext_t *uc = (ucontext_t *) vuc;
+
+    /*
+     * We assume that this is UD1 as per get_risuop below.
+     * This would need tweaking if we want to test expected undefs.
      */
-    ucontext_t *uc = vuc;
-    uc->uc_mcontext.gregs[REG_EIP] += 2;
+    uc->uc_mcontext.gregs[REG_E(IP)] += 3;
+}
+
+void set_ucontext_paramreg(void *vuc, uint64_t value)
+{
+    ucontext_t *uc = (ucontext_t *) vuc;
+    uc->uc_mcontext.gregs[REG_E(AX)] = value;
+}
+
+uint64_t get_reginfo_paramreg(struct reginfo *ri)
+{
+    return ri->gregs[REG_E(AX)];
+}
+
+int get_risuop(struct reginfo *ri)
+{
+    if ((ri->faulting_insn & 0xf8ffff) == 0xc0b90f) { /* UD1 %xxx,%eax */
+        return (ri->faulting_insn >> 16) & 7;
+    }
+    return -1;
+}
+
+uintptr_t get_pc(struct reginfo *ri)
+{
+    return ri->gregs[REG_E(IP)];
 }
 
 int send_register_info(int sock, void *uc)
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 06/11] risu_i386: remove old unused code
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (4 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 05/11] risu_i386: implement missing CPU-specific functions Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas Jan Bobek
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

The code being removed is a remnant of the past implementation; it has
since been replaced by its more powerful, architecture-independent
counterpart in reginfo.c.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_i386.c | 58 -----------------------------------------------------
 1 file changed, 58 deletions(-)

diff --git a/risu_i386.c b/risu_i386.c
index 06d95e5..9962b8f 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -16,13 +16,6 @@
 #include "risu.h"
 #include "risu_reginfo_i386.h"
 
-struct reginfo master_ri, apprentice_ri;
-
-static int insn_is_ud2(uint32_t insn)
-{
-    return ((insn & 0xffff) == 0x0b0f);
-}
-
 void advance_pc(void *vuc)
 {
     ucontext_t *uc = (ucontext_t *) vuc;
@@ -57,54 +50,3 @@ uintptr_t get_pc(struct reginfo *ri)
 {
     return ri->gregs[REG_E(IP)];
 }
-
-int send_register_info(int sock, void *uc)
-{
-    struct reginfo ri;
-    fill_reginfo(&ri, uc);
-    return send_data_pkt(sock, &ri, sizeof(ri));
-}
-
-/* Read register info from the socket and compare it with that from the
- * ucontext. Return 0 for match, 1 for end-of-test, 2 for mismatch.
- * NB: called from a signal handler.
- */
-int recv_and_compare_register_info(int sock, void *uc)
-{
-    int resp;
-    fill_reginfo(&master_ri, uc);
-    recv_data_pkt(sock, &apprentice_ri, sizeof(apprentice_ri));
-    if (memcmp(&master_ri, &apprentice_ri, sizeof(master_ri)) != 0) {
-        /* mismatch */
-        resp = 2;
-    } else if (insn_is_ud2(master_ri.faulting_insn)) {
-        /* end of test */
-        resp = 1;
-    } else {
-        /* either successful match or expected undef */
-        resp = 0;
-    }
-    send_response_byte(sock, resp);
-    return resp;
-}
-
-/* Print a useful report on the status of the last comparison
- * done in recv_and_compare_register_info(). This is called on
- * exit, so need not restrict itself to signal-safe functions.
- * Should return 0 if it was a good match (ie end of test)
- * and 1 for a mismatch.
- */
-int report_match_status(void)
-{
-    fprintf(stderr, "match status...\n");
-    fprintf(stderr, "master reginfo:\n");
-    dump_reginfo(&master_ri);
-    fprintf(stderr, "apprentice reginfo:\n");
-    dump_reginfo(&apprentice_ri);
-    if (memcmp(&master_ri, &apprentice_ri, sizeof(master_ri)) == 0) {
-        fprintf(stderr, "match!\n");
-        return 0;
-    }
-    fprintf(stderr, "mismatch!\n");
-    return 1;
-}
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (5 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 06/11] risu_i386: remove old unused code Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-24  9:28   ` Alex Bennée
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 08/11] configure: add i386/x86_64 architectures Jan Bobek
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

This allows us to drop dependency on NASM and build the test image
with GCC only. Adds support for x86_64, too.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 Makefile    |  3 +++
 test_i386.S | 41 +++++++++++++++++++++++++++++++++++++++++
 test_i386.s | 27 ---------------------------
 3 files changed, 44 insertions(+), 27 deletions(-)
 create mode 100644 test_i386.S
 delete mode 100644 test_i386.s

diff --git a/Makefile b/Makefile
index b362dbe..6ab014a 100644
--- a/Makefile
+++ b/Makefile
@@ -49,6 +49,9 @@ $(PROG): $(OBJS)
 %_$(ARCH).elf: %_$(ARCH).s
 	$(AS) -o $@ $<
 
+%_$(ARCH).elf: %_$(ARCH).S
+	$(CC) $(CPPFLAGS) -o $@ -c $<
+
 clean:
 	rm -f $(PROG) $(OBJS) $(BINS)
 
diff --git a/test_i386.S b/test_i386.S
new file mode 100644
index 0000000..456b99c
--- /dev/null
+++ b/test_i386.S
@@ -0,0 +1,41 @@
+/*#############################################################################
+ * Copyright (c) 2010 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Peter Maydell (Linaro) - initial implementation
+ *###########################################################################*/
+
+/* A trivial test image for x86 */
+
+/* Initialise the registers to avoid spurious mismatches */
+	xor	%eax, %eax
+	sahf				/* init eflags */
+
+	mov	$0x12345678, %eax
+	mov	$0x9abcdef0, %ebx
+	mov	$0x97361234, %ecx
+	mov	$0x84310284, %edx
+	mov	$0x83624173, %edi
+	mov	$0xfaebfaeb, %esi
+	mov	$0x84610123, %ebp
+
+#ifdef __x86_64__
+	movq	$0x123456789abcdef0, %r8
+	movq	$0xaaaabbbbccccdddd, %r9
+	movq	$0x1010101010101010, %r10
+	movq	$0x1111111111111111, %r11
+	movq	$0x1212121212121212, %r12
+	movq	$0x1313131313131313, %r13
+	movq	$0x1414141414141414, %r14
+	movq	$0x1515151515151515, %r15
+#endif
+
+/* do compare */
+	ud1	%eax, %eax
+
+/* exit test */
+	ud1	%ecx, %eax
diff --git a/test_i386.s b/test_i386.s
deleted file mode 100644
index a2140a0..0000000
--- a/test_i386.s
+++ /dev/null
@@ -1,27 +0,0 @@
-;###############################################################################
-;# Copyright (c) 2010 Linaro Limited
-;# All rights reserved. This program and the accompanying materials
-;# are made available under the terms of the Eclipse Public License v1.0
-;# which accompanies this distribution, and is available at
-;# http://www.eclipse.org/legal/epl-v10.html
-;#
-;# Contributors:
-;#     Peter Maydell (Linaro) - initial implementation
-;###############################################################################
-
-; A trivial test image for x86
-
-BITS 32
-; Initialise the registers to avoid spurious mismatches
-mov eax, 0x12345678
-mov ebx, 0x9abcdef0
-mov ecx, 0x97361234
-mov edx, 0x84310284
-mov edi, 0x83624173
-mov esi, 0xfaebfaeb
-mov ebp, 0x84610123
-; UD1 : do compare
-UD1
-
-; UD2 : exit test
-UD2
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 08/11] configure: add i386/x86_64 architectures
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (6 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t Jan Bobek
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

Now that i386 and x86_64 architectures are supported by RISU, we want
to detect them and build RISU for them automatically.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 configure | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index 65e1819..ca2d7db 100755
--- a/configure
+++ b/configure
@@ -48,12 +48,14 @@ EOF
 }
 
 guess_arch() {
-    if check_define __m68k__ ; then
-        ARCH="m68k"
+    if check_define __aarch64__ ; then
+        ARCH="aarch64"
     elif check_define __arm__ ; then
         ARCH="arm"
-    elif check_define __aarch64__ ; then
-        ARCH="aarch64"
+    elif check_define __i386__ || check_define __x86_64__ ; then
+        ARCH="i386"
+    elif check_define __m68k__ ; then
+        ARCH="m68k"
     elif check_define __powerpc64__ ; then
         ARCH="ppc64"
     else
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (7 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 08/11] configure: add i386/x86_64 architectures Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-24  9:29   ` Alex Bennée
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 10/11] risu_reginfo_i386: replace xfeature constants with symbolic names Jan Bobek
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée, Richard Henderson

From: Richard Henderson <richard.henderson@linaro.org>

The state expected for a given test must be specifically requested
with the --xfeatures=mask command-line argument.  This is recorded
with the saved state so that it is obvious if the apprentice is given
a different argument.  Any features beyond what are present on the
running cpu will read as zero.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 risu_reginfo_i386.h |  14 +++
 risu_reginfo_i386.c | 228 ++++++++++++++++++++++++++++++++++++++++++--
 test_i386.S         |  39 ++++++++
 3 files changed, 273 insertions(+), 8 deletions(-)

diff --git a/risu_reginfo_i386.h b/risu_reginfo_i386.h
index e350f01..b468f79 100644
--- a/risu_reginfo_i386.h
+++ b/risu_reginfo_i386.h
@@ -12,6 +12,10 @@
 #ifndef RISU_REGINFO_I386_H
 #define RISU_REGINFO_I386_H
 
+struct avx512_reg {
+    uint64_t q[8];
+};
+
 /*
  * This is the data structure we pass over the socket.
  * It is a simplified and reduced subset of what can
@@ -19,7 +23,17 @@
  */
 struct reginfo {
     uint32_t faulting_insn;
+    uint32_t mxcsr;
+    uint64_t xfeatures;
+
     gregset_t gregs;
+
+#ifdef __x86_64__
+    struct avx512_reg vregs[32];
+#else
+    struct avx512_reg vregs[8];
+#endif
+    uint64_t kregs[8];
 };
 
 /*
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index c4dc14a..83f9541 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -11,19 +11,32 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <ucontext.h>
 #include <assert.h>
+#include <cpuid.h>
 
 #include "risu.h"
 #include "risu_reginfo_i386.h"
 
-const struct option * const arch_long_opts;
-const char * const arch_extra_help;
+#include <asm/sigcontext.h>
+
+static uint64_t xfeatures = 3;  /* SSE */
+
+static const struct option extra_ops[] = {
+    {"xfeatures", required_argument, NULL, FIRST_ARCH_OPT },
+    {0, 0, 0, 0}
+};
+
+const struct option * const arch_long_opts = extra_ops;
+const char * const arch_extra_help
+    = "  --xfeatures=<mask>  Use features in mask for XSAVE\n";
 
 void process_arch_opt(int opt, const char *arg)
 {
-    abort();
+    assert(opt == FIRST_ARCH_OPT);
+    xfeatures = strtoull(arg, 0, 0);
 }
 
 const int reginfo_size(void)
@@ -31,13 +44,37 @@ const int reginfo_size(void)
     return sizeof(struct reginfo);
 }
 
+static void *xsave_feature_buf(struct _xstate *xs, int feature)
+{
+    unsigned int eax, ebx, ecx, edx;
+    int ok;
+
+    /*
+     * Get the location of the XSAVE feature from the cpuid leaf.
+     * Given that we know the xfeature bit is set, this must succeed.
+     */
+    ok = __get_cpuid_count(0xd, feature, &eax, &ebx, &ecx, &edx);
+    assert(ok);
+
+    /* Sanity check that the frame stored by the kernel contains the data. */
+    assert(xs->fpstate.sw_reserved.extended_size >= eax + ebx);
+
+    return (void *)xs + ebx;
+}
+
 /* reginfo_init: initialize with a ucontext */
 void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 {
-    int i;
+    int i, nvecregs;
+    struct _fpstate *fp;
+    struct _xstate *xs;
+    uint64_t features;
 
     memset(ri, 0, sizeof(*ri));
 
+    /* Require master and apprentice to be given the same arguments.  */
+    ri->xfeatures = xfeatures;
+
     for (i = 0; i < NGREG; i++) {
         switch (i) {
         case REG_E(IP):
@@ -79,12 +116,89 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
      * distinguish 'do compare' from 'stop'.
      */
     ri->faulting_insn = *(uint32_t *)uc->uc_mcontext.gregs[REG_E(IP)];
+
+    /*
+     * FP state is omitted if unused (aka in init state).
+     * Use the <asm/sigcontext.h> struct for access to AVX state.
+     */
+
+    fp = (struct _fpstate *)uc->uc_mcontext.fpregs;
+    if (fp == NULL) {
+        return;
+    }
+
+#ifdef __x86_64__
+    nvecregs = 16;
+#else
+    /* We don't (currently) care about the 80387 state, only SSE+.  */
+    if (fp->magic != X86_FXSR_MAGIC) {
+        return;
+    }
+    nvecregs = 8;
+#endif
+
+    /*
+     * Now we know that _fpstate contains FXSAVE data.
+     */
+    ri->mxcsr = fp->mxcsr;
+
+    for (i = 0; i < nvecregs; ++i) {
+#ifdef __x86_64__
+        memcpy(&ri->vregs[i], &fp->xmm_space[i * 4], 16);
+#else
+        memcpy(&ri->vregs[i], &fp->_xmm[i], 16);
+#endif
+    }
+
+    if (fp->sw_reserved.magic1 != FP_XSTATE_MAGIC1) {
+        return;
+    }
+    xs = (struct _xstate *)fp;
+    features = xfeatures & xs->xstate_hdr.xfeatures;
+
+    /*
+     * Now we know that _fpstate contains XSAVE data.
+     */
+
+    if (features & (1 << 2)) {
+        /* YMM_Hi128 state */
+        void *buf = xsave_feature_buf(xs, 2);
+        for (i = 0; i < nvecregs; ++i) {
+            memcpy(&ri->vregs[i].q[2], buf + 16 * i, 16);
+        }
+    }
+
+    if (features & (1 << 5)) {
+        /* Opmask state */
+        uint64_t *buf = xsave_feature_buf(xs, 5);
+        for (i = 0; i < 8; ++i) {
+            ri->kregs[i] = buf[i];
+        }
+    }
+
+    if (features & (1 << 6)) {
+        /* ZMM_Hi256 state */
+        void *buf = xsave_feature_buf(xs, 6);
+        for (i = 0; i < nvecregs; ++i) {
+            memcpy(&ri->vregs[i].q[4], buf + 32 * i, 32);
+        }
+    }
+
+#ifdef __x86_64__
+    if (features & (1 << 7)) {
+        /* Hi16_ZMM state */
+        void *buf = xsave_feature_buf(xs, 7);
+        for (i = 0; i < 16; ++i) {
+            memcpy(&ri->vregs[i + 16], buf + 64 * i, 64);
+        }
+    }
+#endif
 }
 
 /* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
 int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 {
-    return 0 == memcmp(m, a, sizeof(*m));
+    return !memcmp(m, a, sizeof(*m));
 }
 
 static const char *const regname[NGREG] = {
@@ -126,28 +240,126 @@ static const char *const regname[NGREG] = {
 # define PRIxREG   "%08x"
 #endif
 
+static int get_nvecregs(uint64_t features)
+{
+#ifdef __x86_64__
+    return features & (1 << 7) ? 32 : 16;
+#else
+    return 8;
+#endif
+}
+
+static int get_nvecquads(uint64_t features)
+{
+    if (features & (1 << 6)) {
+        return 8;
+    } else if (features & (1 << 2)) {
+        return 4;
+    } else {
+        return 2;
+    }
+}
+
+static char get_vecletter(uint64_t features)
+{
+    if (features & (1 << 6 | 1 << 7)) {
+        return 'z';
+    } else if (features & (1 << 2)) {
+        return 'y';
+    } else {
+        return 'x';
+    }
+}
+
 /* reginfo_dump: print state to a stream, returns nonzero on success */
 int reginfo_dump(struct reginfo *ri, FILE *f)
 {
-    int i;
+    uint64_t features;
+    int i, j, n, w;
+    char r;
+
     fprintf(f, "  faulting insn %x\n", ri->faulting_insn);
     for (i = 0; i < NGREG; i++) {
         if (regname[i]) {
             fprintf(f, "  %-6s: " PRIxREG "\n", regname[i], ri->gregs[i]);
         }
     }
+
+    fprintf(f, "  mxcsr : %x\n", ri->mxcsr);
+    fprintf(f, "  xfeat : %" PRIx64 "\n", ri->xfeatures);
+
+    features = ri->xfeatures;
+    n = get_nvecregs(features);
+    w = get_nvecquads(features);
+    r = get_vecletter(features);
+
+    for (i = 0; i < n; i++) {
+        fprintf(f, "  %cmm%-3d: ", r, i);
+        for (j = w - 1; j >= 0; j--) {
+            fprintf(f, "%016" PRIx64 "%c",
+                    ri->vregs[i].q[j], j == 0 ? '\n' : ' ');
+        }
+    }
+
+    if (features & (1 << 5)) {
+        for (i = 0; i < 8; i++) {
+            fprintf(f, "  k%-5d: %016" PRIx64 "\n", i, ri->kregs[i]);
+        }
+    }
+
     return !ferror(f);
 }
 
 int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
 {
-    int i;
+    int i, j, n, w;
+    uint64_t features;
+    char r;
+
+    fprintf(f, "Mismatch (master v apprentice):\n");
+
     for (i = 0; i < NGREG; i++) {
         if (m->gregs[i] != a->gregs[i]) {
             assert(regname[i]);
-            fprintf(f, "Mismatch: %s: " PRIxREG " v " PRIxREG "\n",
+            fprintf(f, "  %-6s: " PRIxREG " v " PRIxREG "\n",
                     regname[i], m->gregs[i], a->gregs[i]);
         }
     }
+
+    if (m->mxcsr != a->mxcsr) {
+        fprintf(f, "  mxcsr : %x v %x\n", m->mxcsr, a->mxcsr);
+    }
+    if (m->xfeatures != a->xfeatures) {
+        fprintf(f, "  xfeat : %" PRIx64 " v %" PRIx64 "\n",
+                m->xfeatures, a->xfeatures);
+    }
+
+    features = m->xfeatures;
+    n = get_nvecregs(features);
+    w = get_nvecquads(features);
+    r = get_vecletter(features);
+
+    for (i = 0; i < n; i++) {
+        if (memcmp(&m->vregs[i], &a->vregs[i], w * 8)) {
+            fprintf(f, "  %cmm%-3d: ", r, i);
+            for (j = w - 1; j >= 0; j--) {
+                fprintf(f, "%016" PRIx64 "%c",
+                        m->vregs[i].q[j], j == 0 ? '\n' : ' ');
+            }
+            fprintf(f, "       v: ");
+            for (j = w - 1; j >= 0; j--) {
+                fprintf(f, "%016" PRIx64 "%c",
+                        a->vregs[i].q[j], j == 0 ? '\n' : ' ');
+            }
+        }
+    }
+
+    for (i = 0; i < 8; i++) {
+        if (m->kregs[i] != a->kregs[i]) {
+            fprintf(f, "  k%-5d: %016" PRIx64 " v %016" PRIx64 "\n",
+                    i, m->kregs[i], a->kregs[i]);
+        }
+    }
+
     return !ferror(f);
 }
diff --git a/test_i386.S b/test_i386.S
index 456b99c..05344d7 100644
--- a/test_i386.S
+++ b/test_i386.S
@@ -12,6 +12,37 @@
 /* A trivial test image for x86 */
 
 /* Initialise the registers to avoid spurious mismatches */
+
+#ifdef __x86_64__
+#define BASE	%rax
+	lea	2f(%rip), BASE
+#else
+#define BASE	%eax
+	call	1f
+1:	pop	BASE
+	add	$2f-1b, BASE
+#endif
+
+	movdqa	0(BASE), %xmm0
+	movdqa	1*16(BASE), %xmm1
+	movdqa	2*16(BASE), %xmm2
+	movdqa	3*16(BASE), %xmm3
+	movdqa	4*16(BASE), %xmm4
+	movdqa	5*16(BASE), %xmm5
+	movdqa	6*16(BASE), %xmm6
+	movdqa	7*16(BASE), %xmm7
+
+#ifdef __x86_64__
+	movdqa	8*16(BASE), %xmm8
+	movdqa	9*16(BASE), %xmm9
+	movdqa	10*16(BASE), %xmm10
+	movdqa	11*16(BASE), %xmm11
+	movdqa	12*16(BASE), %xmm12
+	movdqa	13*16(BASE), %xmm13
+	movdqa	14*16(BASE), %xmm14
+	movdqa	15*16(BASE), %xmm15
+#endif
+
 	xor	%eax, %eax
 	sahf				/* init eflags */
 
@@ -39,3 +70,11 @@
 
 /* exit test */
 	ud1	%ecx, %eax
+
+	.p2align 16
+2:
+	.set	i, 0
+	.rept	256
+	.byte	i
+	.set	i, i + 1
+	.endr
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 10/11] risu_reginfo_i386: replace xfeature constants with symbolic names
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (8 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing Jan Bobek
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

The original code used "magic numbers", which made it unclear in
some places. Include a reference to the Intel manual where the
constants' meaning is discussed.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_reginfo_i386.c | 48 +++++++++++++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index 83f9541..01ea179 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -22,7 +22,25 @@
 
 #include <asm/sigcontext.h>
 
-static uint64_t xfeatures = 3;  /* SSE */
+/*
+ * Refer to "Intel(R) 64 and IA-32 Architectures Software Developer's
+ * Manual", Volume 1, Section 13.1 "XSAVE-Supported Features and
+ * State-Component Bitmaps" for detailed discussion of these constants
+ * and their meaning.
+ */
+enum {
+    XFEAT_X87              = 1 << 0,
+    XFEAT_SSE              = 1 << 1,
+    XFEAT_AVX              = 1 << 2,
+    XFEAT_AVX512_OPMASK    = 1 << 5,
+    XFEAT_AVX512_ZMM_HI256 = 1 << 6,
+    XFEAT_AVX512_HI16_ZMM  = 1 << 7,
+    XFEAT_AVX512           = XFEAT_AVX512_OPMASK
+                           | XFEAT_AVX512_ZMM_HI256
+                           | XFEAT_AVX512_HI16_ZMM
+};
+
+static uint64_t xfeatures = XFEAT_X87 | XFEAT_SSE;
 
 static const struct option extra_ops[] = {
     {"xfeatures", required_argument, NULL, FIRST_ARCH_OPT },
@@ -160,34 +178,34 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
      * Now we know that _fpstate contains XSAVE data.
      */
 
-    if (features & (1 << 2)) {
+    if (features & XFEAT_AVX) {
         /* YMM_Hi128 state */
-        void *buf = xsave_feature_buf(xs, 2);
+        void *buf = xsave_feature_buf(xs, XFEAT_AVX);
         for (i = 0; i < nvecregs; ++i) {
             memcpy(&ri->vregs[i].q[2], buf + 16 * i, 16);
         }
     }
 
-    if (features & (1 << 5)) {
+    if (features & XFEAT_AVX512_OPMASK) {
         /* Opmask state */
-        uint64_t *buf = xsave_feature_buf(xs, 5);
+        uint64_t *buf = xsave_feature_buf(xs, XFEAT_AVX512_OPMASK);
         for (i = 0; i < 8; ++i) {
             ri->kregs[i] = buf[i];
         }
     }
 
-    if (features & (1 << 6)) {
+    if (features & XFEAT_AVX512_ZMM_HI256) {
         /* ZMM_Hi256 state */
-        void *buf = xsave_feature_buf(xs, 6);
+        void *buf = xsave_feature_buf(xs, XFEAT_AVX512_ZMM_HI256);
         for (i = 0; i < nvecregs; ++i) {
             memcpy(&ri->vregs[i].q[4], buf + 32 * i, 32);
         }
     }
 
 #ifdef __x86_64__
-    if (features & (1 << 7)) {
+    if (features & XFEAT_AVX512_HI16_ZMM) {
         /* Hi16_ZMM state */
-        void *buf = xsave_feature_buf(xs, 7);
+        void *buf = xsave_feature_buf(xs, XFEAT_AVX512_HI16_ZMM);
         for (i = 0; i < 16; ++i) {
             memcpy(&ri->vregs[i + 16], buf + 64 * i, 64);
         }
@@ -243,7 +261,7 @@ static const char *const regname[NGREG] = {
 static int get_nvecregs(uint64_t features)
 {
 #ifdef __x86_64__
-    return features & (1 << 7) ? 32 : 16;
+    return features & XFEAT_AVX512_HI16_ZMM ? 32 : 16;
 #else
     return 8;
 #endif
@@ -251,9 +269,9 @@ static int get_nvecregs(uint64_t features)
 
 static int get_nvecquads(uint64_t features)
 {
-    if (features & (1 << 6)) {
+    if (features & XFEAT_AVX512_ZMM_HI256) {
         return 8;
-    } else if (features & (1 << 2)) {
+    } else if (features & XFEAT_AVX) {
         return 4;
     } else {
         return 2;
@@ -262,9 +280,9 @@ static int get_nvecquads(uint64_t features)
 
 static char get_vecletter(uint64_t features)
 {
-    if (features & (1 << 6 | 1 << 7)) {
+    if (features & (XFEAT_AVX512_ZMM_HI256 | XFEAT_AVX512_HI16_ZMM)) {
         return 'z';
-    } else if (features & (1 << 2)) {
+    } else if (features & XFEAT_AVX) {
         return 'y';
     } else {
         return 'x';
@@ -301,7 +319,7 @@ int reginfo_dump(struct reginfo *ri, FILE *f)
         }
     }
 
-    if (features & (1 << 5)) {
+    if (features & XFEAT_AVX512_OPMASK) {
         for (i = 0; i < 8; i++) {
             fprintf(f, "  k%-5d: %016" PRIx64 "\n", i, ri->kregs[i]);
         }
-- 
2.20.1



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

* [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (9 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 10/11] risu_reginfo_i386: replace xfeature constants with symbolic names Jan Bobek
@ 2019-05-23 20:44 ` Jan Bobek
  2019-05-24  9:32   ` Alex Bennée
  2019-05-24  9:27 ` [Qemu-devel] [RISU PATCH] build-all-arches: include x86 triplets in the build Alex Bennée
  2019-05-24  9:42 ` [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Alex Bennée
  12 siblings, 1 reply; 20+ messages in thread
From: Jan Bobek @ 2019-05-23 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Bobek, Alex Bennée, Richard Henderson

Have the --xfeatures option accept "sse", "avx" and "avx512" in
addition to a plain numerical value, purely for users' convenience.
Don't fail silently when an incorrect value is specified, to avoid
confusion.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Jan Bobek <jan.bobek@gmail.com>
---
 risu_reginfo_i386.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index 01ea179..194e0ad 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -53,8 +53,25 @@ const char * const arch_extra_help
 
 void process_arch_opt(int opt, const char *arg)
 {
+    char *endptr;
+
     assert(opt == FIRST_ARCH_OPT);
-    xfeatures = strtoull(arg, 0, 0);
+
+    if (!strcmp(arg, "sse")) {
+        xfeatures = XFEAT_X87 | XFEAT_SSE;
+    } else if (!strcmp(arg, "avx")) {
+        xfeatures = XFEAT_X87 | XFEAT_SSE | XFEAT_AVX;
+    } else if (!strcmp(arg, "avx512")) {
+        xfeatures = XFEAT_X87 | XFEAT_SSE | XFEAT_AVX | XFEAT_AVX512;
+    } else {
+        xfeatures = strtoull(arg, &endptr, 0);
+        if (*endptr) {
+            fprintf(stderr,
+                    "Unable to parse '%s' in '%s' into an xfeatures integer mask\n",
+                    endptr, arg);
+            exit(1);
+        }
+    }
 }
 
 const int reginfo_size(void)
-- 
2.20.1



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

* [Qemu-devel] [RISU PATCH] build-all-arches: include x86 triplets in the build
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (10 preceding siblings ...)
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing Jan Bobek
@ 2019-05-24  9:27 ` Alex Bennée
  2019-05-24  9:42 ` [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Alex Bennée
  12 siblings, 0 replies; 20+ messages in thread
From: Alex Bennée @ 2019-05-24  9:27 UTC (permalink / raw)
  To: jan.bobek; +Cc: Alex Bennée, qemu-devel

There are a couple of minor warts:

  - 32 bit x86 can be either i386-linux-gnu or i686-linux-gnu
  - skip looking for x86_64-linux-gnu-gcc in docker cross envs

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 build-all-archs | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/build-all-archs b/build-all-archs
index a7cd7c2..e5dcfc8 100755
--- a/build-all-archs
+++ b/build-all-archs
@@ -39,7 +39,7 @@ while [[ "$1" = -* ]]; do
             ;;
         --use-docker)
             if [ -z "$arg" ]; then
-                default_tags=$(docker images qemu --format "{{.Repository}}:{{.Tag}}" | grep "\(arm\|ppc64el\|m68k\).*cross$")
+                default_tags=$(docker images qemu --format "{{.Repository}}:{{.Tag}}" | grep "\(arm\|ppc64el\|m68k\|i386\).*cross$")
                 docker_tags=$(echo $default_tags | sed 's/\n/\s/g' )
             else
                 docker_tags="$arg"
@@ -74,7 +74,7 @@ fi
 DOCKER_RUN="docker run --rm -u $(id -u) -v $(pwd):$(pwd) -w $(pwd)"
 
 program_exists() {
-    if [ ! -z "$docker_tags" ]; then
+    if [[ ! -z "$docker_tags" && ! "$1" == "x86_64-linux-gnu-gcc" ]]; then
         use_docker_tag=""
         for tag in $docker_tags; do
             if ${DOCKER_RUN} ${tag} /bin/bash -c "command -v $1 >/dev/null"; then
@@ -88,8 +88,10 @@ program_exists() {
 }
 
 # powerpc64-linux-gnu doesn't work at the moment, so not yet listed.
-for triplet in aarch64-linux-gnu arm-linux-gnueabihf m68k-linux-gnu \
-    powerpc64le-linux-gnu powerpc64-linux-gnu ; do
+for triplet in i386-linux-gnu i686-linux-gnu x86_64-linux-gnu \
+                   aarch64-linux-gnu arm-linux-gnueabihf \
+                   m68k-linux-gnu \
+                   powerpc64le-linux-gnu powerpc64-linux-gnu ; do
 
     if ! program_exists "${triplet}-gcc"; then
         echo "Skipping ${triplet}: no compiler found"
-- 
2.20.1



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

* Re: [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas Jan Bobek
@ 2019-05-24  9:28   ` Alex Bennée
  0 siblings, 0 replies; 20+ messages in thread
From: Alex Bennée @ 2019-05-24  9:28 UTC (permalink / raw)
  To: Jan Bobek; +Cc: Richard Henderson, qemu-devel


Jan Bobek <jan.bobek@gmail.com> writes:

> This allows us to drop dependency on NASM and build the test image
> with GCC only. Adds support for x86_64, too.
>
> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Jan Bobek <jan.bobek@gmail.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  Makefile    |  3 +++
>  test_i386.S | 41 +++++++++++++++++++++++++++++++++++++++++
>  test_i386.s | 27 ---------------------------
>  3 files changed, 44 insertions(+), 27 deletions(-)
>  create mode 100644 test_i386.S
>  delete mode 100644 test_i386.s
>
> diff --git a/Makefile b/Makefile
> index b362dbe..6ab014a 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -49,6 +49,9 @@ $(PROG): $(OBJS)
>  %_$(ARCH).elf: %_$(ARCH).s
>  	$(AS) -o $@ $<
>
> +%_$(ARCH).elf: %_$(ARCH).S
> +	$(CC) $(CPPFLAGS) -o $@ -c $<
> +
>  clean:
>  	rm -f $(PROG) $(OBJS) $(BINS)
>
> diff --git a/test_i386.S b/test_i386.S
> new file mode 100644
> index 0000000..456b99c
> --- /dev/null
> +++ b/test_i386.S
> @@ -0,0 +1,41 @@
> +/*#############################################################################
> + * Copyright (c) 2010 Linaro Limited
> + * All rights reserved. This program and the accompanying materials
> + * are made available under the terms of the Eclipse Public License v1.0
> + * which accompanies this distribution, and is available at
> + * http://www.eclipse.org/legal/epl-v10.html
> + *
> + * Contributors:
> + *     Peter Maydell (Linaro) - initial implementation
> + *###########################################################################*/
> +
> +/* A trivial test image for x86 */
> +
> +/* Initialise the registers to avoid spurious mismatches */
> +	xor	%eax, %eax
> +	sahf				/* init eflags */
> +
> +	mov	$0x12345678, %eax
> +	mov	$0x9abcdef0, %ebx
> +	mov	$0x97361234, %ecx
> +	mov	$0x84310284, %edx
> +	mov	$0x83624173, %edi
> +	mov	$0xfaebfaeb, %esi
> +	mov	$0x84610123, %ebp
> +
> +#ifdef __x86_64__
> +	movq	$0x123456789abcdef0, %r8
> +	movq	$0xaaaabbbbccccdddd, %r9
> +	movq	$0x1010101010101010, %r10
> +	movq	$0x1111111111111111, %r11
> +	movq	$0x1212121212121212, %r12
> +	movq	$0x1313131313131313, %r13
> +	movq	$0x1414141414141414, %r14
> +	movq	$0x1515151515151515, %r15
> +#endif
> +
> +/* do compare */
> +	ud1	%eax, %eax
> +
> +/* exit test */
> +	ud1	%ecx, %eax
> diff --git a/test_i386.s b/test_i386.s
> deleted file mode 100644
> index a2140a0..0000000
> --- a/test_i386.s
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -;###############################################################################
> -;# Copyright (c) 2010 Linaro Limited
> -;# All rights reserved. This program and the accompanying materials
> -;# are made available under the terms of the Eclipse Public License v1.0
> -;# which accompanies this distribution, and is available at
> -;# http://www.eclipse.org/legal/epl-v10.html
> -;#
> -;# Contributors:
> -;#     Peter Maydell (Linaro) - initial implementation
> -;###############################################################################
> -
> -; A trivial test image for x86
> -
> -BITS 32
> -; Initialise the registers to avoid spurious mismatches
> -mov eax, 0x12345678
> -mov ebx, 0x9abcdef0
> -mov ecx, 0x97361234
> -mov edx, 0x84310284
> -mov edi, 0x83624173
> -mov esi, 0xfaebfaeb
> -mov ebp, 0x84610123
> -; UD1 : do compare
> -UD1
> -
> -; UD2 : exit test
> -UD2


--
Alex Bennée


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

* Re: [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t Jan Bobek
@ 2019-05-24  9:29   ` Alex Bennée
  0 siblings, 0 replies; 20+ messages in thread
From: Alex Bennée @ 2019-05-24  9:29 UTC (permalink / raw)
  To: Jan Bobek; +Cc: Richard Henderson, qemu-devel


Jan Bobek <jan.bobek@gmail.com> writes:

> From: Richard Henderson <richard.henderson@linaro.org>
>
> The state expected for a given test must be specifically requested
> with the --xfeatures=mask command-line argument.  This is recorded
> with the saved state so that it is obvious if the apprentice is given
> a different argument.  Any features beyond what are present on the
> running cpu will read as zero.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>


> ---
>  risu_reginfo_i386.h |  14 +++
>  risu_reginfo_i386.c | 228 ++++++++++++++++++++++++++++++++++++++++++--
>  test_i386.S         |  39 ++++++++
>  3 files changed, 273 insertions(+), 8 deletions(-)
>
> diff --git a/risu_reginfo_i386.h b/risu_reginfo_i386.h
> index e350f01..b468f79 100644
> --- a/risu_reginfo_i386.h
> +++ b/risu_reginfo_i386.h
> @@ -12,6 +12,10 @@
>  #ifndef RISU_REGINFO_I386_H
>  #define RISU_REGINFO_I386_H
>
> +struct avx512_reg {
> +    uint64_t q[8];
> +};
> +
>  /*
>   * This is the data structure we pass over the socket.
>   * It is a simplified and reduced subset of what can
> @@ -19,7 +23,17 @@
>   */
>  struct reginfo {
>      uint32_t faulting_insn;
> +    uint32_t mxcsr;
> +    uint64_t xfeatures;
> +
>      gregset_t gregs;
> +
> +#ifdef __x86_64__
> +    struct avx512_reg vregs[32];
> +#else
> +    struct avx512_reg vregs[8];
> +#endif
> +    uint64_t kregs[8];
>  };
>
>  /*
> diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
> index c4dc14a..83f9541 100644
> --- a/risu_reginfo_i386.c
> +++ b/risu_reginfo_i386.c
> @@ -11,19 +11,32 @@
>
>  #include <stdio.h>
>  #include <stdlib.h>
> +#include <stddef.h>
>  #include <string.h>
>  #include <ucontext.h>
>  #include <assert.h>
> +#include <cpuid.h>
>
>  #include "risu.h"
>  #include "risu_reginfo_i386.h"
>
> -const struct option * const arch_long_opts;
> -const char * const arch_extra_help;
> +#include <asm/sigcontext.h>
> +
> +static uint64_t xfeatures = 3;  /* SSE */
> +
> +static const struct option extra_ops[] = {
> +    {"xfeatures", required_argument, NULL, FIRST_ARCH_OPT },
> +    {0, 0, 0, 0}
> +};
> +
> +const struct option * const arch_long_opts = extra_ops;
> +const char * const arch_extra_help
> +    = "  --xfeatures=<mask>  Use features in mask for XSAVE\n";
>
>  void process_arch_opt(int opt, const char *arg)
>  {
> -    abort();
> +    assert(opt == FIRST_ARCH_OPT);
> +    xfeatures = strtoull(arg, 0, 0);
>  }
>
>  const int reginfo_size(void)
> @@ -31,13 +44,37 @@ const int reginfo_size(void)
>      return sizeof(struct reginfo);
>  }
>
> +static void *xsave_feature_buf(struct _xstate *xs, int feature)
> +{
> +    unsigned int eax, ebx, ecx, edx;
> +    int ok;
> +
> +    /*
> +     * Get the location of the XSAVE feature from the cpuid leaf.
> +     * Given that we know the xfeature bit is set, this must succeed.
> +     */
> +    ok = __get_cpuid_count(0xd, feature, &eax, &ebx, &ecx, &edx);
> +    assert(ok);
> +
> +    /* Sanity check that the frame stored by the kernel contains the data. */
> +    assert(xs->fpstate.sw_reserved.extended_size >= eax + ebx);
> +
> +    return (void *)xs + ebx;
> +}
> +
>  /* reginfo_init: initialize with a ucontext */
>  void reginfo_init(struct reginfo *ri, ucontext_t *uc)
>  {
> -    int i;
> +    int i, nvecregs;
> +    struct _fpstate *fp;
> +    struct _xstate *xs;
> +    uint64_t features;
>
>      memset(ri, 0, sizeof(*ri));
>
> +    /* Require master and apprentice to be given the same arguments.  */
> +    ri->xfeatures = xfeatures;
> +
>      for (i = 0; i < NGREG; i++) {
>          switch (i) {
>          case REG_E(IP):
> @@ -79,12 +116,89 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
>       * distinguish 'do compare' from 'stop'.
>       */
>      ri->faulting_insn = *(uint32_t *)uc->uc_mcontext.gregs[REG_E(IP)];
> +
> +    /*
> +     * FP state is omitted if unused (aka in init state).
> +     * Use the <asm/sigcontext.h> struct for access to AVX state.
> +     */
> +
> +    fp = (struct _fpstate *)uc->uc_mcontext.fpregs;
> +    if (fp == NULL) {
> +        return;
> +    }
> +
> +#ifdef __x86_64__
> +    nvecregs = 16;
> +#else
> +    /* We don't (currently) care about the 80387 state, only SSE+.  */
> +    if (fp->magic != X86_FXSR_MAGIC) {
> +        return;
> +    }
> +    nvecregs = 8;
> +#endif
> +
> +    /*
> +     * Now we know that _fpstate contains FXSAVE data.
> +     */
> +    ri->mxcsr = fp->mxcsr;
> +
> +    for (i = 0; i < nvecregs; ++i) {
> +#ifdef __x86_64__
> +        memcpy(&ri->vregs[i], &fp->xmm_space[i * 4], 16);
> +#else
> +        memcpy(&ri->vregs[i], &fp->_xmm[i], 16);
> +#endif
> +    }
> +
> +    if (fp->sw_reserved.magic1 != FP_XSTATE_MAGIC1) {
> +        return;
> +    }
> +    xs = (struct _xstate *)fp;
> +    features = xfeatures & xs->xstate_hdr.xfeatures;
> +
> +    /*
> +     * Now we know that _fpstate contains XSAVE data.
> +     */
> +
> +    if (features & (1 << 2)) {
> +        /* YMM_Hi128 state */
> +        void *buf = xsave_feature_buf(xs, 2);
> +        for (i = 0; i < nvecregs; ++i) {
> +            memcpy(&ri->vregs[i].q[2], buf + 16 * i, 16);
> +        }
> +    }
> +
> +    if (features & (1 << 5)) {
> +        /* Opmask state */
> +        uint64_t *buf = xsave_feature_buf(xs, 5);
> +        for (i = 0; i < 8; ++i) {
> +            ri->kregs[i] = buf[i];
> +        }
> +    }
> +
> +    if (features & (1 << 6)) {
> +        /* ZMM_Hi256 state */
> +        void *buf = xsave_feature_buf(xs, 6);
> +        for (i = 0; i < nvecregs; ++i) {
> +            memcpy(&ri->vregs[i].q[4], buf + 32 * i, 32);
> +        }
> +    }
> +
> +#ifdef __x86_64__
> +    if (features & (1 << 7)) {
> +        /* Hi16_ZMM state */
> +        void *buf = xsave_feature_buf(xs, 7);
> +        for (i = 0; i < 16; ++i) {
> +            memcpy(&ri->vregs[i + 16], buf + 64 * i, 64);
> +        }
> +    }
> +#endif
>  }
>
>  /* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
>  int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
>  {
> -    return 0 == memcmp(m, a, sizeof(*m));
> +    return !memcmp(m, a, sizeof(*m));
>  }
>
>  static const char *const regname[NGREG] = {
> @@ -126,28 +240,126 @@ static const char *const regname[NGREG] = {
>  # define PRIxREG   "%08x"
>  #endif
>
> +static int get_nvecregs(uint64_t features)
> +{
> +#ifdef __x86_64__
> +    return features & (1 << 7) ? 32 : 16;
> +#else
> +    return 8;
> +#endif
> +}
> +
> +static int get_nvecquads(uint64_t features)
> +{
> +    if (features & (1 << 6)) {
> +        return 8;
> +    } else if (features & (1 << 2)) {
> +        return 4;
> +    } else {
> +        return 2;
> +    }
> +}
> +
> +static char get_vecletter(uint64_t features)
> +{
> +    if (features & (1 << 6 | 1 << 7)) {
> +        return 'z';
> +    } else if (features & (1 << 2)) {
> +        return 'y';
> +    } else {
> +        return 'x';
> +    }
> +}
> +
>  /* reginfo_dump: print state to a stream, returns nonzero on success */
>  int reginfo_dump(struct reginfo *ri, FILE *f)
>  {
> -    int i;
> +    uint64_t features;
> +    int i, j, n, w;
> +    char r;
> +
>      fprintf(f, "  faulting insn %x\n", ri->faulting_insn);
>      for (i = 0; i < NGREG; i++) {
>          if (regname[i]) {
>              fprintf(f, "  %-6s: " PRIxREG "\n", regname[i], ri->gregs[i]);
>          }
>      }
> +
> +    fprintf(f, "  mxcsr : %x\n", ri->mxcsr);
> +    fprintf(f, "  xfeat : %" PRIx64 "\n", ri->xfeatures);
> +
> +    features = ri->xfeatures;
> +    n = get_nvecregs(features);
> +    w = get_nvecquads(features);
> +    r = get_vecletter(features);
> +
> +    for (i = 0; i < n; i++) {
> +        fprintf(f, "  %cmm%-3d: ", r, i);
> +        for (j = w - 1; j >= 0; j--) {
> +            fprintf(f, "%016" PRIx64 "%c",
> +                    ri->vregs[i].q[j], j == 0 ? '\n' : ' ');
> +        }
> +    }
> +
> +    if (features & (1 << 5)) {
> +        for (i = 0; i < 8; i++) {
> +            fprintf(f, "  k%-5d: %016" PRIx64 "\n", i, ri->kregs[i]);
> +        }
> +    }
> +
>      return !ferror(f);
>  }
>
>  int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
>  {
> -    int i;
> +    int i, j, n, w;
> +    uint64_t features;
> +    char r;
> +
> +    fprintf(f, "Mismatch (master v apprentice):\n");
> +
>      for (i = 0; i < NGREG; i++) {
>          if (m->gregs[i] != a->gregs[i]) {
>              assert(regname[i]);
> -            fprintf(f, "Mismatch: %s: " PRIxREG " v " PRIxREG "\n",
> +            fprintf(f, "  %-6s: " PRIxREG " v " PRIxREG "\n",
>                      regname[i], m->gregs[i], a->gregs[i]);
>          }
>      }
> +
> +    if (m->mxcsr != a->mxcsr) {
> +        fprintf(f, "  mxcsr : %x v %x\n", m->mxcsr, a->mxcsr);
> +    }
> +    if (m->xfeatures != a->xfeatures) {
> +        fprintf(f, "  xfeat : %" PRIx64 " v %" PRIx64 "\n",
> +                m->xfeatures, a->xfeatures);
> +    }
> +
> +    features = m->xfeatures;
> +    n = get_nvecregs(features);
> +    w = get_nvecquads(features);
> +    r = get_vecletter(features);
> +
> +    for (i = 0; i < n; i++) {
> +        if (memcmp(&m->vregs[i], &a->vregs[i], w * 8)) {
> +            fprintf(f, "  %cmm%-3d: ", r, i);
> +            for (j = w - 1; j >= 0; j--) {
> +                fprintf(f, "%016" PRIx64 "%c",
> +                        m->vregs[i].q[j], j == 0 ? '\n' : ' ');
> +            }
> +            fprintf(f, "       v: ");
> +            for (j = w - 1; j >= 0; j--) {
> +                fprintf(f, "%016" PRIx64 "%c",
> +                        a->vregs[i].q[j], j == 0 ? '\n' : ' ');
> +            }
> +        }
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        if (m->kregs[i] != a->kregs[i]) {
> +            fprintf(f, "  k%-5d: %016" PRIx64 " v %016" PRIx64 "\n",
> +                    i, m->kregs[i], a->kregs[i]);
> +        }
> +    }
> +
>      return !ferror(f);
>  }
> diff --git a/test_i386.S b/test_i386.S
> index 456b99c..05344d7 100644
> --- a/test_i386.S
> +++ b/test_i386.S
> @@ -12,6 +12,37 @@
>  /* A trivial test image for x86 */
>
>  /* Initialise the registers to avoid spurious mismatches */
> +
> +#ifdef __x86_64__
> +#define BASE	%rax
> +	lea	2f(%rip), BASE
> +#else
> +#define BASE	%eax
> +	call	1f
> +1:	pop	BASE
> +	add	$2f-1b, BASE
> +#endif
> +
> +	movdqa	0(BASE), %xmm0
> +	movdqa	1*16(BASE), %xmm1
> +	movdqa	2*16(BASE), %xmm2
> +	movdqa	3*16(BASE), %xmm3
> +	movdqa	4*16(BASE), %xmm4
> +	movdqa	5*16(BASE), %xmm5
> +	movdqa	6*16(BASE), %xmm6
> +	movdqa	7*16(BASE), %xmm7
> +
> +#ifdef __x86_64__
> +	movdqa	8*16(BASE), %xmm8
> +	movdqa	9*16(BASE), %xmm9
> +	movdqa	10*16(BASE), %xmm10
> +	movdqa	11*16(BASE), %xmm11
> +	movdqa	12*16(BASE), %xmm12
> +	movdqa	13*16(BASE), %xmm13
> +	movdqa	14*16(BASE), %xmm14
> +	movdqa	15*16(BASE), %xmm15
> +#endif
> +
>  	xor	%eax, %eax
>  	sahf				/* init eflags */
>
> @@ -39,3 +70,11 @@
>
>  /* exit test */
>  	ud1	%ecx, %eax
> +
> +	.p2align 16
> +2:
> +	.set	i, 0
> +	.rept	256
> +	.byte	i
> +	.set	i, i + 1
> +	.endr


--
Alex Bennée


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

* Re: [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing
  2019-05-23 20:44 ` [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing Jan Bobek
@ 2019-05-24  9:32   ` Alex Bennée
  0 siblings, 0 replies; 20+ messages in thread
From: Alex Bennée @ 2019-05-24  9:32 UTC (permalink / raw)
  To: Jan Bobek; +Cc: Richard Henderson, qemu-devel


Jan Bobek <jan.bobek@gmail.com> writes:

> Have the --xfeatures option accept "sse", "avx" and "avx512" in
> addition to a plain numerical value, purely for users' convenience.
> Don't fail silently when an incorrect value is specified, to avoid
> confusion.
>
> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Jan Bobek <jan.bobek@gmail.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>


> ---
>  risu_reginfo_i386.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
> index 01ea179..194e0ad 100644
> --- a/risu_reginfo_i386.c
> +++ b/risu_reginfo_i386.c
> @@ -53,8 +53,25 @@ const char * const arch_extra_help
>
>  void process_arch_opt(int opt, const char *arg)
>  {
> +    char *endptr;
> +
>      assert(opt == FIRST_ARCH_OPT);
> -    xfeatures = strtoull(arg, 0, 0);
> +
> +    if (!strcmp(arg, "sse")) {
> +        xfeatures = XFEAT_X87 | XFEAT_SSE;
> +    } else if (!strcmp(arg, "avx")) {
> +        xfeatures = XFEAT_X87 | XFEAT_SSE | XFEAT_AVX;
> +    } else if (!strcmp(arg, "avx512")) {
> +        xfeatures = XFEAT_X87 | XFEAT_SSE | XFEAT_AVX | XFEAT_AVX512;
> +    } else {
> +        xfeatures = strtoull(arg, &endptr, 0);
> +        if (*endptr) {
> +            fprintf(stderr,
> +                    "Unable to parse '%s' in '%s' into an xfeatures integer mask\n",
> +                    endptr, arg);
> +            exit(1);
> +        }
> +    }
>  }
>
>  const int reginfo_size(void)


--
Alex Bennée


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

* Re: [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions
  2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
                   ` (11 preceding siblings ...)
  2019-05-24  9:27 ` [Qemu-devel] [RISU PATCH] build-all-arches: include x86 triplets in the build Alex Bennée
@ 2019-05-24  9:42 ` Alex Bennée
  2019-06-07 10:07   ` Peter Maydell
  12 siblings, 1 reply; 20+ messages in thread
From: Alex Bennée @ 2019-05-24  9:42 UTC (permalink / raw)
  To: Jan Bobek; +Cc: Peter Maydell, Richard Henderson, qemu-devel


Jan Bobek <jan.bobek@gmail.com> writes:

> This patch series adds support for i386 and x86_64 architectures to
> RISU. Notably, vector registers (SSE, AVX, AVX-512) are supported for
> verification of the apprentice. This is V3 of the series posted in [1]
> and [2].

I've sent a patch to enable x86 in the build-all-arches tests script but
otherwise I think this series looks good to merge.

>
> Changes is V3:
>   - fix a matching bug caused by misplaced index multiplication [3]
>   - print an error and exit when parse of the --xfeatures option fails [4]
>
> References:
>   1. https://lists.nongnu.org/archive/html/qemu-devel/2019-04/msg01294.html
>   2. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04089.html
>   3. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04922.html
>   4. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg04903.html
>
> Jan Bobek (10):
>   Makefile: undefine the arch name symbol
>   risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h
>   risu_i386: move reginfo-related code to risu_reginfo_i386.c
>   risu_reginfo_i386: implement arch-specific reginfo interface
>   risu_i386: implement missing CPU-specific functions
>   risu_i386: remove old unused code
>   test_i386: change syntax from nasm to gas
>   configure: add i386/x86_64 architectures
>   risu_reginfo_i386: replace xfeature constants with symbolic names
>   risu_reginfo_i386: rework --xfeatures value parsing
>
> Richard Henderson (1):
>   i386: Add avx512 state to reginfo_t
>
>  configure           |  10 +-
>  Makefile            |   5 +-
>  risu_reginfo_i386.h |  49 ++++++
>  risu_i386.c         | 142 ++--------------
>  risu_reginfo_i386.c | 400 ++++++++++++++++++++++++++++++++++++++++++++
>  test_i386.S         |  80 +++++++++
>  test_i386.s         |  27 ---
>  7 files changed, 556 insertions(+), 157 deletions(-)
>  create mode 100644 risu_reginfo_i386.h
>  create mode 100644 risu_reginfo_i386.c
>  create mode 100644 test_i386.S
>  delete mode 100644 test_i386.s


--
Alex Bennée


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

* Re: [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions
  2019-05-24  9:42 ` [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Alex Bennée
@ 2019-06-07 10:07   ` Peter Maydell
  2019-06-07 11:58     ` Alex Bennée
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Maydell @ 2019-06-07 10:07 UTC (permalink / raw)
  To: Alex Bennée; +Cc: Richard Henderson, Jan Bobek, QEMU Developers

On Fri, 24 May 2019 at 10:42, Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Jan Bobek <jan.bobek@gmail.com> writes:
>
> > This patch series adds support for i386 and x86_64 architectures to
> > RISU. Notably, vector registers (SSE, AVX, AVX-512) are supported for
> > verification of the apprentice. This is V3 of the series posted in [1]
> > and [2].
>
> I've sent a patch to enable x86 in the build-all-arches tests script but
> otherwise I think this series looks good to merge.

Alex: So should I merge this series, or does it need a respin ?

thanks
-- PMM


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

* Re: [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions
  2019-06-07 10:07   ` Peter Maydell
@ 2019-06-07 11:58     ` Alex Bennée
  2019-06-07 13:36       ` Peter Maydell
  0 siblings, 1 reply; 20+ messages in thread
From: Alex Bennée @ 2019-06-07 11:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Richard Henderson, Jan Bobek, QEMU Developers


Peter Maydell <peter.maydell@linaro.org> writes:

> On Fri, 24 May 2019 at 10:42, Alex Bennée <alex.bennee@linaro.org> wrote:
>>
>>
>> Jan Bobek <jan.bobek@gmail.com> writes:
>>
>> > This patch series adds support for i386 and x86_64 architectures to
>> > RISU. Notably, vector registers (SSE, AVX, AVX-512) are supported for
>> > verification of the apprentice. This is V3 of the series posted in [1]
>> > and [2].
>>
>> I've sent a patch to enable x86 in the build-all-arches tests script but
>> otherwise I think this series looks good to merge.
>
> Alex: So should I merge this series, or does it need a respin ?

I think this can be merged. I assume there is more to come to actually
generate the patterns but it doesn't break any of the existing stuff and
has at least one test case.

--
Alex Bennée


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

* Re: [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions
  2019-06-07 11:58     ` Alex Bennée
@ 2019-06-07 13:36       ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2019-06-07 13:36 UTC (permalink / raw)
  To: Alex Bennée; +Cc: Richard Henderson, Jan Bobek, QEMU Developers

On Fri, 7 Jun 2019 at 12:58, Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Peter Maydell <peter.maydell@linaro.org> writes:
>
> > On Fri, 24 May 2019 at 10:42, Alex Bennée <alex.bennee@linaro.org> wrote:
> >>
> >>
> >> Jan Bobek <jan.bobek@gmail.com> writes:
> >>
> >> > This patch series adds support for i386 and x86_64 architectures to
> >> > RISU. Notably, vector registers (SSE, AVX, AVX-512) are supported for
> >> > verification of the apprentice. This is V3 of the series posted in [1]
> >> > and [2].
> >>
> >> I've sent a patch to enable x86 in the build-all-arches tests script but
> >> otherwise I think this series looks good to merge.
> >
> > Alex: So should I merge this series, or does it need a respin ?
>
> I think this can be merged. I assume there is more to come to actually
> generate the patterns but it doesn't break any of the existing stuff and
> has at least one test case.

Thanks; pushed this series and your patch to add it to the
build-all-archs script to risu master.

-- PMM


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

end of thread, other threads:[~2019-06-07 13:41 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-23 20:43 [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Jan Bobek
2019-05-23 20:43 ` [Qemu-devel] [RISU v3 01/11] Makefile: undefine the arch name symbol Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 02/11] risu_i386: move reginfo_t and related defines to risu_reginfo_i386.h Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 03/11] risu_i386: move reginfo-related code to risu_reginfo_i386.c Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 04/11] risu_reginfo_i386: implement arch-specific reginfo interface Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 05/11] risu_i386: implement missing CPU-specific functions Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 06/11] risu_i386: remove old unused code Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 07/11] test_i386: change syntax from nasm to gas Jan Bobek
2019-05-24  9:28   ` Alex Bennée
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 08/11] configure: add i386/x86_64 architectures Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 09/11] i386: Add avx512 state to reginfo_t Jan Bobek
2019-05-24  9:29   ` Alex Bennée
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 10/11] risu_reginfo_i386: replace xfeature constants with symbolic names Jan Bobek
2019-05-23 20:44 ` [Qemu-devel] [RISU v3 11/11] risu_reginfo_i386: rework --xfeatures value parsing Jan Bobek
2019-05-24  9:32   ` Alex Bennée
2019-05-24  9:27 ` [Qemu-devel] [RISU PATCH] build-all-arches: include x86 triplets in the build Alex Bennée
2019-05-24  9:42 ` [Qemu-devel] [RISU v3 00/11] Support for i386/x86_64 with vector extensions Alex Bennée
2019-06-07 10:07   ` Peter Maydell
2019-06-07 11:58     ` Alex Bennée
2019-06-07 13:36       ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.