diff mbox

[Risu,3/3] Initial implemention for ppc64le

Message ID 1477676782-21378-4-git-send-email-joserz@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jose Ricardo Ziviani Oct. 28, 2016, 5:46 p.m. UTC
From: Jose Ricardo Ziviani <joserz@br.ibm.com>

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

Signed-off-by: Jose Ricardo Ziviani <joserz@br.ibm.com>
---
 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

Comments

Peter Maydell Oct. 31, 2016, 2:42 p.m. UTC | #1
On 28 October 2016 at 18:46, Jose Ricardo Ziviani
<joserz@linux.vnet.ibm.com> wrote:
> From: Jose Ricardo Ziviani <joserz@br.ibm.com>
>
>  - This commit adds the initial implementation of ppc64le support
>    (client and server) for Risu.
>
> Signed-off-by: Jose Ricardo Ziviani <joserz@br.ibm.com>
> ---
>  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

Wrong copyright info again.

> + * 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;
> +}

This doesn't look right. You should be doing something to
get the "which risu op is this?" info out of the faulting
instruction and then handling it appropriately -- look at
the code in risu_aarch64.c. This is what lets us do memory
comparisons as well as register comparisons.


> --- /dev/null
> +++ b/risu_reginfo_ppc64le.c
> @@ -0,0 +1,175 @@
> +/******************************************************************************
> + * Copyright (c) 2013 Linaro Limited

Wrong copyright...

> + * 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;

PC-type values should subtract image_start_address so that
they are kept as offsets from the start of the test code block.
Otherwise you get spurious mismatches when the master and
apprentice ends happen to allocate the code block at different
addresses.

Stack pointers also usually need some special handling.

> +
> +    int i;
> +    for (i = 0; i < NGREG; i++)
> +    {
> +        ri->gregs[i] = uc->uc_mcontext.gp_regs[i];
> +    }

I know the risu C code is a mess of different coding styles (my
fault primarily), but I think we should probably settle on using
the QEMU coding style here (four-space indent, always braces,
open-brace on same line as if/for, etc).

> +
> +    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);

Please don't get fancy with escape sequences in the output.
If we want that as a feature we should add it separately from
PPC support and work out how to do it cleanly for all supported
target architectures.

thanks
-- PMM
diff mbox

Patch

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