diff mbox series

[10/11] riscv: Implement payload load interfaces

Message ID 20200711161655.2856-11-zhiwei_liu@c-sky.com
State New
Headers show
Series None | expand

Commit Message

LIU Zhiwei July 11, 2020, 4:16 p.m. UTC
When a risu op emits, the signal handler wll take over execution before
running the payload again.

The signal handler need some interfaces, such as setting struct reginfo
and the comparison of struct reginfo.

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 risu_reginfo_riscv64.c | 132 +++++++++++++++++++++++++++++++++++++++++
 risu_riscv64.c         |  47 +++++++++++++++
 2 files changed, 179 insertions(+)
 create mode 100644 risu_reginfo_riscv64.c
 create mode 100644 risu_riscv64.c
diff mbox series

Patch

diff --git a/risu_reginfo_riscv64.c b/risu_reginfo_riscv64.c
new file mode 100644
index 0000000..763001f
--- /dev/null
+++ b/risu_reginfo_riscv64.c
@@ -0,0 +1,132 @@ 
+/******************************************************************************
+ * Copyright (c) 2020 T-Head Semiconductor Co., Ltd.
+ * 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:
+ *     LIU Zhiwei (T-Head) - initial implementation
+ *     based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <string.h>
+#include <signal.h> /* for FPSIMD_MAGIC */
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <sys/prctl.h>
+
+#include "risu.h"
+#include "risu_reginfo_riscv64.h"
+
+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;
+    union __riscv_mc_fp_state *fp;
+    /* necessary to be able to compare with memcmp later */
+    memset(ri, 0, sizeof(*ri));
+
+    for (i = 0; i < 32; i++) {
+        ri->regs[i] = uc->uc_mcontext.__gregs[i];
+    }
+
+    ri->regs[2] = 0xdeadbeefdeadbeef;
+    ri->regs[3] = 0xdeadbeefdeadbeef;
+    ri->regs[4] = 0xdeadbeefdeadbeef;
+    ri->pc = uc->uc_mcontext.__gregs[0] - image_start_address;
+    ri->regs[0] = ri->pc;
+    ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.__gregs[0]);
+    fp = &uc->uc_mcontext.__fpregs;
+#if __riscv_flen == 64
+    ri->fcsr = fp->__d.__fcsr;
+
+    for (i = 0; i < 32; i++) {
+        ri->fregs[i] = fp->__d.__f[i];
+    }
+#else
+# error "Unsupported fp length"
+#endif
+}
+
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+{
+    return memcmp(r1, r2, reginfo_size()) == 0;
+}
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+int reginfo_dump(struct reginfo *ri, FILE * f)
+{
+    int i;
+    fprintf(f, "  faulting insn %08x\n", ri->faulting_insn);
+
+    for (i = 1; i < 32; i++) {
+        fprintf(f, "  X%-2d    : %016" PRIx64 "\n", i, ri->regs[i]);
+    }
+
+    fprintf(f, "  pc     : %016" PRIx64 "\n", ri->pc);
+    fprintf(f, "  fcsr   : %08x\n", ri->fcsr);
+
+    for (i = 0; i < 32; i++) {
+        fprintf(f, "  F%-2d    : %016" PRIx64 "\n", i, ri->fregs[i]);
+    }
+
+    return !ferror(f);
+}
+
+/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */
+int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
+{
+    int i;
+    fprintf(f, "mismatch detail (master : apprentice):\n");
+    if (m->faulting_insn != a->faulting_insn) {
+        fprintf(f, "  faulting insn mismatch %08x vs %08x\n",
+                m->faulting_insn, a->faulting_insn);
+    }
+    for (i = 1; i < 32; i++) {
+        if (m->regs[i] != a->regs[i]) {
+            fprintf(f, "  X%-2d    : %016" PRIx64 " vs %016" PRIx64 "\n",
+                    i, m->regs[i], a->regs[i]);
+        }
+    }
+
+    if (m->pc != a->pc) {
+        fprintf(f, "  pc     : %016" PRIx64 " vs %016" PRIx64 "\n",
+                m->pc, a->pc);
+    }
+
+    if (m->fcsr != a->fcsr) {
+        fprintf(f, "  fcsr   : %08x vs %08x\n", m->fcsr, a->fcsr);
+    }
+
+    for (i = 0; i < 32; i++) {
+        if (m->fregs[i] != a->fregs[i]) {
+            fprintf(f, "  F%-2d    : "
+                    "%016" PRIx64 " vs "
+                    "%016" PRIx64 "\n", i,
+                    (uint64_t) m->fregs[i],
+                    (uint64_t) a->fregs[i]);
+        }
+    }
+
+    return !ferror(f);
+}
diff --git a/risu_riscv64.c b/risu_riscv64.c
new file mode 100644
index 0000000..06dbb2d
--- /dev/null
+++ b/risu_riscv64.c
@@ -0,0 +1,47 @@ 
+/******************************************************************************
+ * Copyright (c) 2020 T-Head Semiconductor Co., Ltd.
+ * 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:
+ *     LIU Zhiwei(Linaro) - initial implementation
+ *     based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#include "risu.h"
+
+void advance_pc(void *vuc)
+{
+    ucontext_t *uc = vuc;
+    uc->uc_mcontext.__gregs[0] += 4;
+}
+
+void set_ucontext_paramreg(void *vuc, uint64_t value)
+{
+    ucontext_t *uc = vuc;
+    uc->uc_mcontext.__gregs[10] = value;
+}
+
+uint64_t get_reginfo_paramreg(struct reginfo *ri)
+{
+    return ri->regs[10];
+}
+
+int get_risuop(struct reginfo *ri)
+{
+    /* Return the risuop we have been asked to do
+     * (or -1 if this was a SIGILL for a non-risuop insn)
+     */
+    uint32_t insn = ri->faulting_insn;
+    uint32_t op = (insn & 0xf00) >> 8;
+    uint32_t key = insn & ~0xf00;
+    uint32_t risukey = 0x0000006b;
+    return (key != risukey) ? -1 : op;
+}
+
+uintptr_t get_pc(struct reginfo *ri)
+{
+   return ri->pc;
+}