@@ -20,7 +20,7 @@ CFLAGS ?= -g
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
+SRCS=risu.c comms.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
HDRS=risu.h risu_reginfo_$(ARCH).h
BINS=test_$(ARCH).bin
@@ -35,7 +35,6 @@ void process_arch_opt(int opt, const char *arg);
#include REGINFO_HEADER(ARCH)
extern uintptr_t image_start_address;
-extern void *memblock;
/* Ops code under test can request from risu: */
typedef enum {
@@ -83,34 +82,9 @@ void send_response_byte(int sock, int resp);
/* Functions operating on reginfo */
-/* Function prototypes for read/write helper functions. */
-RisuResult write_buffer(void *ptr, size_t bytes);
-RisuResult read_buffer(void *ptr, size_t bytes);
-void respond(RisuResult response);
-
-/*
- * Send the register information from the struct ucontext down the socket.
- * NB: called from a signal handler.
- */
-RisuResult send_register_info(void *uc);
-
-/*
- * Read register info from the socket and compare it with that from the
- * ucontext.
- * NB: called from a signal handler.
- */
-RisuResult recv_and_compare_register_info(void *uc);
-
-/*
- * Print a useful report on the status of the last reg comparison
- * done in recv_and_compare_register_info().
- */
-void report_mismatch_reg(void);
-
/* Interface provided by CPU-specific code: */
-/* Move the PC past this faulting insn by adjusting ucontext
- */
+/* Move the PC past this faulting insn by adjusting ucontext. */
void advance_pc(void *uc);
/* Set the parameter register in a ucontext_t to the specified value.
deleted file mode 100644
@@ -1,151 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2017 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 <string.h>
-#include <stdlib.h>
-#include "risu.h"
-
-static struct reginfo master_ri, apprentice_ri;
-static uint8_t master_memblock[MEMBLOCKLEN];
-
-RisuResult send_register_info(void *uc)
-{
- struct reginfo ri;
- trace_header_t header;
- RisuResult res;
- RisuOp op;
-
- reginfo_init(&ri, uc);
- op = get_risuop(&ri);
-
- /* Write a header with PC/op to keep in sync */
- header.pc = get_pc(&ri);
- header.risu_op = op;
- res = write_buffer(&header, sizeof(header));
- if (res != RES_OK) {
- return res;
- }
-
- switch (op) {
- case OP_COMPARE:
- case OP_TESTEND:
- case OP_SIGILL:
- /*
- * Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
- res = write_buffer(&ri, reginfo_size());
- /* For OP_TEST_END, force exit. */
- if (res == RES_OK && op == OP_TESTEND) {
- res = RES_END;
- }
- break;
- case OP_SETMEMBLOCK:
- memblock = (void *)(uintptr_t)get_reginfo_paramreg(&ri);
- break;
- case OP_GETMEMBLOCK:
- set_ucontext_paramreg(uc,
- get_reginfo_paramreg(&ri) + (uintptr_t)memblock);
- break;
- case OP_COMPAREMEM:
- return write_buffer(memblock, MEMBLOCKLEN);
- default:
- abort();
- }
- return res;
-}
-
-/* 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.
- *
- * We don't have any kind of identifying info in the incoming data
- * that says whether it is register or memory data, so if the two
- * sides get out of sync then we will fail obscurely.
- */
-RisuResult recv_and_compare_register_info(void *uc)
-{
- RisuResult res;
- trace_header_t header;
- RisuOp op;
-
- reginfo_init(&apprentice_ri, uc);
- op = get_risuop(&apprentice_ri);
-
- res = read_buffer(&header, sizeof(header));
- if (res != RES_OK) {
- return res;
- }
-
- if (header.risu_op != op) {
- /* We are out of sync. Tell master to exit. */
- respond(RES_END);
- return RES_BAD_IO;
- }
-
- /* send OK for the header */
- respond(RES_OK);
-
- switch (op) {
- case OP_COMPARE:
- case OP_TESTEND:
- case OP_SIGILL:
- /* Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
- res = read_buffer(&master_ri, reginfo_size());
- if (res != RES_OK) {
- /* fail */
- } else if (!reginfo_is_eq(&master_ri, &apprentice_ri)) {
- /* register mismatch */
- res = RES_MISMATCH_REG;
- } else if (op == OP_TESTEND) {
- res = RES_END;
- }
- respond(res == RES_OK ? RES_OK : RES_END);
- break;
- case OP_SETMEMBLOCK:
- memblock = (void *)(uintptr_t)get_reginfo_paramreg(&apprentice_ri);
- break;
- case OP_GETMEMBLOCK:
- set_ucontext_paramreg(uc, get_reginfo_paramreg(&apprentice_ri) +
- (uintptr_t)memblock);
- break;
- case OP_COMPAREMEM:
- res = read_buffer(master_memblock, MEMBLOCKLEN);
- if (res != RES_OK) {
- /* fail */
- } else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) {
- /* memory mismatch */
- res = RES_MISMATCH_MEM;
- }
- respond(res == RES_OK ? RES_OK : RES_END);
- break;
- default:
- abort();
- }
-
- return res;
-}
-
-/*
- * Print a useful report on the status of the last reg comparison
- * done in recv_and_compare_register_info().
- */
-void report_mismatch_reg(void)
-{
- fprintf(stderr, "master reginfo:\n");
- reginfo_dump(&master_ri, stderr);
- fprintf(stderr, "apprentice reginfo:\n");
- reginfo_dump(&apprentice_ri, stderr);
- reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr);
-}
@@ -28,7 +28,10 @@
#include "config.h"
#include "risu.h"
-void *memblock;
+static void *memblock;
+static struct reginfo master_ri, apprentice_ri;
+static uint8_t master_memblock[MEMBLOCKLEN];
+
static int comm_fd;
static bool trace;
@@ -48,7 +51,7 @@ static sigjmp_buf jmpbuf;
/* I/O functions */
-RisuResult read_buffer(void *ptr, size_t bytes)
+static RisuResult read_buffer(void *ptr, size_t bytes)
{
size_t res;
@@ -69,7 +72,7 @@ RisuResult read_buffer(void *ptr, size_t bytes)
return res == bytes ? RES_OK : RES_BAD_IO;
}
-RisuResult write_buffer(void *ptr, size_t bytes)
+static RisuResult write_buffer(void *ptr, size_t bytes)
{
size_t res;
@@ -90,13 +93,60 @@ RisuResult write_buffer(void *ptr, size_t bytes)
return res == bytes ? RES_OK : RES_BAD_IO;
}
-void respond(RisuResult r)
+static void respond(RisuResult r)
{
if (!trace) {
send_response_byte(comm_fd, r);
}
}
+static RisuResult send_register_info(void *uc)
+{
+ struct reginfo ri;
+ trace_header_t header;
+ RisuResult res;
+ RisuOp op;
+
+ reginfo_init(&ri, uc);
+ op = get_risuop(&ri);
+
+ /* Write a header with PC/op to keep in sync */
+ header.pc = get_pc(&ri);
+ header.risu_op = op;
+ res = write_buffer(&header, sizeof(header));
+ if (res != RES_OK) {
+ return res;
+ }
+
+ switch (op) {
+ case OP_COMPARE:
+ case OP_TESTEND:
+ case OP_SIGILL:
+ /*
+ * Do a simple register compare on (a) explicit request
+ * (b) end of test (c) a non-risuop UNDEF
+ */
+ res = write_buffer(&ri, reginfo_size());
+ /* For OP_TEST_END, force exit. */
+ if (res == RES_OK && op == OP_TESTEND) {
+ res = RES_END;
+ }
+ break;
+ case OP_SETMEMBLOCK:
+ memblock = (void *)(uintptr_t)get_reginfo_paramreg(&ri);
+ break;
+ case OP_GETMEMBLOCK:
+ set_ucontext_paramreg(uc,
+ get_reginfo_paramreg(&ri) + (uintptr_t)memblock);
+ break;
+ case OP_COMPAREMEM:
+ return write_buffer(memblock, MEMBLOCKLEN);
+ default:
+ abort();
+ }
+ return res;
+}
+
static void master_sigill(int sig, siginfo_t *si, void *uc)
{
RisuResult r;
@@ -110,6 +160,71 @@ static void master_sigill(int sig, siginfo_t *si, void *uc)
}
}
+static RisuResult recv_and_compare_register_info(void *uc)
+{
+ RisuResult res;
+ trace_header_t header;
+ RisuOp op;
+
+ reginfo_init(&apprentice_ri, uc);
+ op = get_risuop(&apprentice_ri);
+
+ res = read_buffer(&header, sizeof(header));
+ if (res != RES_OK) {
+ return res;
+ }
+
+ if (header.risu_op != op) {
+ /* We are out of sync. Tell master to exit. */
+ respond(RES_END);
+ return RES_BAD_IO;
+ }
+
+ /* send OK for the header */
+ respond(RES_OK);
+
+ switch (op) {
+ case OP_COMPARE:
+ case OP_TESTEND:
+ case OP_SIGILL:
+ /* Do a simple register compare on (a) explicit request
+ * (b) end of test (c) a non-risuop UNDEF
+ */
+ res = read_buffer(&master_ri, reginfo_size());
+ if (res != RES_OK) {
+ /* fail */
+ } else if (!reginfo_is_eq(&master_ri, &apprentice_ri)) {
+ /* register mismatch */
+ res = RES_MISMATCH_REG;
+ } else if (op == OP_TESTEND) {
+ res = RES_END;
+ }
+ respond(res == RES_OK ? RES_OK : RES_END);
+ break;
+ case OP_SETMEMBLOCK:
+ memblock = (void *)(uintptr_t)get_reginfo_paramreg(&apprentice_ri);
+ break;
+ case OP_GETMEMBLOCK:
+ set_ucontext_paramreg(uc, get_reginfo_paramreg(&apprentice_ri) +
+ (uintptr_t)memblock);
+ break;
+ case OP_COMPAREMEM:
+ res = read_buffer(master_memblock, MEMBLOCKLEN);
+ if (res != RES_OK) {
+ /* fail */
+ } else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) {
+ /* memory mismatch */
+ res = RES_MISMATCH_MEM;
+ }
+ respond(res == RES_OK ? RES_OK : RES_END);
+ break;
+ default:
+ abort();
+ }
+
+ return res;
+}
+
static void apprentice_sigill(int sig, siginfo_t *si, void *uc)
{
RisuResult r;
@@ -226,7 +341,11 @@ static int apprentice(void)
case RES_MISMATCH_REG:
fprintf(stderr, "mismatch reg after %zd checkpoints\n", signal_count);
- report_mismatch_reg();
+ fprintf(stderr, "master reginfo:\n");
+ reginfo_dump(&master_ri, stderr);
+ fprintf(stderr, "apprentice reginfo:\n");
+ reginfo_dump(&apprentice_ri, stderr);
+ reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr);
return EXIT_FAILURE;
case RES_MISMATCH_MEM:
The distinction between the two is artificial. Following patches will rearrange the functions involved to make it easier for dumping of the trace file. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- Makefile | 2 +- risu.h | 28 +--------- reginfo.c | 151 ------------------------------------------------------ risu.c | 129 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 126 insertions(+), 184 deletions(-) delete mode 100644 reginfo.c