qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH Risu 3/3] Initial implemention for ppc64le


From: Jose Ricardo Ziviani
Subject: [Qemu-devel] [PATCH Risu 3/3] Initial implemention for ppc64le
Date: Fri, 28 Oct 2016 15:46:22 -0200

From: Jose Ricardo Ziviani <address@hidden>

 - This commit adds the initial implementation of ppc64le support
   (client and server) for Risu.

Signed-off-by: Jose Ricardo Ziviani <address@hidden>
---
 configure              |   6 ++
 risu_ppc64le.c         |  92 ++++++++++++++++++++++++++
 risu_reginfo_ppc64le.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++
 risu_reginfo_ppc64le.h |  36 ++++++++++
 test_ppc64le.s         |  52 +++++++++++++++
 5 files changed, 361 insertions(+)
 create mode 100644 risu_ppc64le.c
 create mode 100644 risu_reginfo_ppc64le.c
 create mode 100644 risu_reginfo_ppc64le.h
 create mode 100644 test_ppc64le.s

diff --git a/configure b/configure
index 748b48a..3e239f3 100755
--- a/configure
+++ b/configure
@@ -22,6 +22,12 @@ guess_arch() {
         ARCH="arm"
     elif check_define __aarch64__ ; then
         ARCH="aarch64"
+    elif check_define __powerpc64__ ; then
+        if check_define __BIG_ENDIAN__; then
+            ARCH="ppc64"
+        else
+            ARCH="ppc64le"
+        fi
     else
         echo "This cpu is not supported by risu. Try -h. " >&2
         exit 1
diff --git a/risu_ppc64le.c b/risu_ppc64le.c
new file mode 100644
index 0000000..811dd77
--- /dev/null
+++ b/risu_ppc64le.c
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * Copyright (c) 2013 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:
+ *     Jose Ricardo Ziviani - initial implementation
+ *     based on Claudio Fontana's risu_aarch64.c
+ *     based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <string.h>
+
+#include "risu.h"
+#include "risu_reginfo_ppc64le.h"
+
+struct reginfo master_ri, apprentice_ri;
+
+void advance_pc(void *vuc)
+{
+    ucontext_t *uc = (ucontext_t*)vuc;
+    uc->uc_mcontext.regs->nip += 4;
+}
+
+int send_register_info(int sock, void *uc)
+{
+    struct reginfo ri;
+    reginfo_init(&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 = 0;
+    reginfo_init(&master_ri, uc);
+    if (recv_data_pkt(sock, &apprentice_ri, sizeof(apprentice_ri))) {
+        printf("Packed mismatch\n");
+        resp = 2;
+
+    } else if (!reginfo_is_eq(&master_ri, &apprentice_ri, uc))
+    {
+        /* mismatch */
+        resp = 2;
+    }
+    else if (master_ri.faulting_insn == 0x5af1)
+    {
+        /* 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");
+    int resp = reginfo_is_eq(&master_ri, &apprentice_ri, NULL);
+    if (resp) {
+        fprintf(stderr, "\e[1;34mTest passed successfuly\e[0m\n");
+        return 0;
+    }
+
+    fprintf(stderr, "\n******************** [master reginfo]\n");
+    reginfo_dump(&master_ri, 1);
+
+    fprintf(stderr, "\n******************* [apprentice reginfo]\n");
+    reginfo_dump(&apprentice_ri, 0);
+
+    fprintf(stderr, "\e[1;31mmismatch!\e[0m\n");
+
+    return resp;
+}
diff --git a/risu_reginfo_ppc64le.c b/risu_reginfo_ppc64le.c
new file mode 100644
index 0000000..b79ecfc
--- /dev/null
+++ b/risu_reginfo_ppc64le.c
@@ -0,0 +1,175 @@
+/******************************************************************************
+ * Copyright (c) 2013 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:
+ *     Jose Ricardo Ziviani - initial implementation
+ *     based on Claudio Fontana's risu_aarch64.c
+ *     based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <string.h>
+#include <math.h>
+
+#include "risu.h"
+#include "risu_reginfo_ppc64le.h"
+
+#define XER 37
+#define CCR 38
+
+/* reginfo_init: initialize with a ucontext */
+void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+{
+    ri->faulting_insn = *((uint32_t *)uc->uc_mcontext.regs->nip);
+    ri->prev_insn = *((uint32_t *)(uc->uc_mcontext.regs->nip - 4));
+    ri->prev_addr = uc->uc_mcontext.regs->nip - 4;
+
+    int i;
+    for (i = 0; i < NGREG; i++)
+    {
+        ri->gregs[i] = uc->uc_mcontext.gp_regs[i];
+    }
+
+    for (i = 0; i < NFPREG; i++)
+    {
+        ri->fpregs[i] = uc->uc_mcontext.fp_regs[i];
+    }
+
+    for (i = 0; i < 32; i++)
+    {
+        ri->vrregs.vrregs[i][0] = uc->uc_mcontext.v_regs->vrregs[i][0];
+        ri->vrregs.vrregs[i][1] = uc->uc_mcontext.v_regs->vrregs[i][1];
+        ri->vrregs.vrregs[i][2] = uc->uc_mcontext.v_regs->vrregs[i][2];
+        ri->vrregs.vrregs[i][3] = uc->uc_mcontext.v_regs->vrregs[i][3];
+    }
+    ri->vrregs.vscr = uc->uc_mcontext.v_regs->vscr;
+    ri->vrregs.vrsave = uc->uc_mcontext.v_regs->vrsave;
+}
+
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+int reginfo_is_eq(struct reginfo *master, struct reginfo *apprentice, 
ucontext_t *uc)
+{
+    int i;
+    for (i = 0; i < 32; i++)
+    {
+        if (i == 1 || i == 13)
+            continue;
+
+        if (master->gregs[i] != apprentice->gregs[i])
+        {
+            fprintf(stderr, "\e[1;32mMismatch: \e[0mRegister r%d\n", i);
+            fprintf(stderr, "master: [%lx] - apprentice: [%lx]\n",
+                    master->gregs[i], apprentice->gregs[i]);
+            return 0;
+        }
+    }
+
+    if (master->gregs[XER] != apprentice->gregs[XER])
+    {
+        fprintf(stderr, "\e[1;32mMismatch: \e[0mXER\n");
+        fprintf(stderr, "master: [%lx] != apprentice: [%lx]\n",
+                    master->gregs[XER], apprentice->gregs[XER]);
+        return 0;
+    }
+
+    if ((master->gregs[CCR] & 0x10) != (apprentice->gregs[CCR] & 0x10))
+    {
+        fprintf(stderr, "\e[1;32mMismatch: \e[0mCond. Register\n");
+        fprintf(stderr, "master: [%lx] != apprentice: [%lx]\n",
+                master->gregs[CCR], apprentice->gregs[CCR]);
+        return 0;
+    }
+
+    for (i = 0; i < 32; i++)
+    {
+        if (isnan(master->fpregs[i]) && isnan(apprentice->fpregs[i]))
+            continue;
+
+        if  (master->fpregs[i] != apprentice->fpregs[i])
+        {
+            fprintf(stderr, "\e[1;32mMismatch: \e[0mRegister r%d\n", i);
+            fprintf(stderr, "master: [%f] != apprentice: [%f]\n",
+                    master->fpregs[i], apprentice->fpregs[i]);
+            return 0;
+        }
+    }
+
+    for (i = 0; i < 32; i++)
+    {
+        if (master->vrregs.vrregs[i][0] != apprentice->vrregs.vrregs[i][0] ||
+                master->vrregs.vrregs[i][1] != apprentice->vrregs.vrregs[i][1] 
||
+                master->vrregs.vrregs[i][2] != apprentice->vrregs.vrregs[i][2] 
||
+                master->vrregs.vrregs[i][3] != apprentice->vrregs.vrregs[i][3])
+        {
+            if (uc != NULL && (master->gregs[CCR] & 0x10)) {
+                uc->uc_mcontext.v_regs->vrregs[i][0] = 
apprentice->vrregs.vrregs[i][0];
+                uc->uc_mcontext.v_regs->vrregs[i][1] = 
apprentice->vrregs.vrregs[i][1];
+                uc->uc_mcontext.v_regs->vrregs[i][2] = 
apprentice->vrregs.vrregs[i][2];
+                uc->uc_mcontext.v_regs->vrregs[i][3] = 
apprentice->vrregs.vrregs[i][3];
+                return 1;
+            }
+
+            fprintf(stderr, "\e[1;32mMismatch: \e[0mRegister vr%d\n", i);
+            fprintf(stderr, "master: [%x, %x, %x, %x] != apprentice: [%x, %x, 
%x, %x]\n",
+                    master->vrregs.vrregs[i][0], master->vrregs.vrregs[i][1],
+                    master->vrregs.vrregs[i][2], master->vrregs.vrregs[i][3],
+                    apprentice->vrregs.vrregs[i][0], 
apprentice->vrregs.vrregs[i][1],
+                    apprentice->vrregs.vrregs[i][2], 
apprentice->vrregs.vrregs[i][3]);
+
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+void reginfo_dump(struct reginfo *ri, int is_master)
+{
+    int i;
+    if (is_master) {
+        fprintf(stderr, "  faulting insn \e[1;101;37m0x%x\e[0m\n", 
ri->faulting_insn);
+        fprintf(stderr, "  prev insn     \e[1;101;37m0x%x\e[0m\n", 
ri->prev_insn);
+        fprintf(stderr, "  prev addr     \e[1;101;37m0x%" PRIx64 "\e[0m\n\n", 
ri->prev_addr);
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        fprintf(stderr, "\tr%2d: %16lx\tr%2d: %16lx\n", i, ri->gregs[i],
+                i + 16, ri->gregs[i + 16]);
+    }
+
+    fprintf(stderr, "\n");
+    fprintf(stderr, "\tnip    : %16lx\n", ri->gregs[32]);
+    fprintf(stderr, "\tmsr    : %16lx\n", ri->gregs[33]);
+    fprintf(stderr, "\torig r3: %16lx\n", ri->gregs[34]);
+    fprintf(stderr, "\tctr    : %16lx\n", ri->gregs[35]);
+    fprintf(stderr, "\tlnk    : %16lx\n", ri->gregs[36]);
+    fprintf(stderr, "\txer    : %16lx\n", ri->gregs[37]);
+    fprintf(stderr, "\tccr    : %16lx\n", ri->gregs[38]);
+    fprintf(stderr, "\tmq     : %16lx\n", ri->gregs[39]);
+    fprintf(stderr, "\ttrap   : %16lx\n", ri->gregs[40]);
+    fprintf(stderr, "\tdar    : %16lx\n", ri->gregs[41]);
+    fprintf(stderr, "\tdsisr  : %16lx\n", ri->gregs[42]);
+    fprintf(stderr, "\tresult : %16lx\n", ri->gregs[43]);
+    fprintf(stderr, "\tdscr   : %16lx\n\n", ri->gregs[44]);
+
+    for (i = 0; i < 16; i++)
+    {
+        fprintf(stderr, "\tf%2d: %.4f\tr%2d: %.4f\n", i, ri->fpregs[i],
+                i + 16, ri->fpregs[i + 16]);
+    }
+    fprintf(stderr, "\tfpscr: %f\n\n", ri->fpregs[32]);
+
+    for (i = 0; i < 32; i++)
+    {
+        fprintf(stderr, "vr%02d: %8x, %8x, %8x, %8x\n", i,
+                ri->vrregs.vrregs[i][0], ri->vrregs.vrregs[i][1],
+                ri->vrregs.vrregs[i][2], ri->vrregs.vrregs[i][3]);
+    }
+}
diff --git a/risu_reginfo_ppc64le.h b/risu_reginfo_ppc64le.h
new file mode 100644
index 0000000..9049455
--- /dev/null
+++ b/risu_reginfo_ppc64le.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2013 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:
+ *     Jose Ricardo Ziviani - initial implementation
+ *     based on Claudio Fontana's risu_reginfo_aarch64
+ *     based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#ifndef RISU_REGINFO_PPC64LE_H
+#define RISU_REGINFO_PPC64LE_H
+
+struct reginfo
+{
+    uint32_t faulting_insn;
+    uint32_t prev_insn;
+    uint64_t prev_addr;
+    gregset_t gregs;
+    fpregset_t fpregs;
+    vrregset_t vrregs;
+};
+
+/* initialize structure from a ucontext */
+void reginfo_init(struct reginfo *ri, ucontext_t *uc);
+
+/* return 1 if structs are equal, 0 otherwise. */
+int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2, ucontext_t *uc);
+
+/* print reginfo state to a stream */
+void reginfo_dump(struct reginfo *ri, int is_master);
+
+#endif /* RISU_REGINFO_PPC64LE_H */
diff --git a/test_ppc64le.s b/test_ppc64le.s
new file mode 100644
index 0000000..bb30318
--- /dev/null
+++ b/test_ppc64le.s
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ *     Claudio Fontana (Linaro) - initial implementation
+ *     based on test_arm.s by Peter Maydell
+ *****************************************************************************/
+
+/* Initialise the gp regs */
+li 0,0
+li 1,1
+li 2,2
+li 3,3
+li 4,4
+li 5,5
+li 6,6
+li 7,7
+li 8,8
+li 9,9
+li 10, 10
+li 11, 11
+li 12, 12
+li 13, 13
+li 14, 14
+li 15, 15
+li 16, 16
+li 17, 17
+li 18, 18
+li 19, 19
+li 20, 20
+li 21, 21
+li 22, 22
+li 23, 23
+li 24, 24
+li 25, 25
+li 26, 26
+li 27, 27
+li 28, 28
+li 29, 29
+li 30, 30
+li 31, 31
+
+/* do compare.
+ * The manual says instr with bits (28,27) == 0 0 are UNALLOCATED
+ */
+.int 0x00005af0
+/* exit test */
+.int 0x00005af1
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]