From patchwork Tue Feb 7 18:33:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 9560851 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 53D4060547 for ; Tue, 7 Feb 2017 18:43:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 45B8428450 for ; Tue, 7 Feb 2017 18:43:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3A70728460; Tue, 7 Feb 2017 18:43:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 45F2E2845E for ; Tue, 7 Feb 2017 18:43:01 +0000 (UTC) Received: from localhost ([::1]:55875 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cbAjE-0003gX-CF for patchwork-qemu-devel@patchwork.kernel.org; Tue, 07 Feb 2017 13:43:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60152) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cbAaf-0004ty-0G for qemu-devel@nongnu.org; Tue, 07 Feb 2017 13:34:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cbAaY-0001UB-1v for qemu-devel@nongnu.org; Tue, 07 Feb 2017 13:34:08 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:59604) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cbAaX-0001Sx-KF for qemu-devel@nongnu.org; Tue, 07 Feb 2017 13:34:02 -0500 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue005 [212.227.15.167]) with ESMTPSA (Nemesis) id 0LodLS-1buwwf1CUk-00gVTz; Tue, 07 Feb 2017 19:33:59 +0100 From: Laurent Vivier To: Peter Maydell Date: Tue, 7 Feb 2017 19:33:53 +0100 Message-Id: <20170207183356.17840-3-laurent@vivier.eu> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170207183356.17840-1-laurent@vivier.eu> References: <20170207183356.17840-1-laurent@vivier.eu> X-Provags-ID: V03:K0:6TZeZHsvsW4ZzWrqVLDzL/RFftPahSneFSD1UV0yQugnnlT/PWb u9ofGAt3wfCXz0LLMnN55nUDbvDUtW5OQY80lvUS1TLfN+shOXQJBRlsVW0lkU2o/8OAsWR DDH6X+30CEn5m6olXs3SQNctmF9n5kcA2Rypi10+cabVSkweXMLT7DdnbmwKfY12IndFOvW L0Fqmy/3l/r/jepd6wUtQ== X-UI-Out-Filterresults: notjunk:1; V01:K0:hClONqKCoMs=:4hYend31226I/ShnzKz19Q WmCIBAs/iw3zLBRqRU17w4uEh7UjfUuuk91ELusTiJaq1offcfiMhhMj1rSuy9zBww1G5UpVV s6jRrAgGoMHlHJ+i8YcWByQTFRjUYIZzxtyllHDVHPaoEPD6SfvEaRoFsaRub+fIOUQpdfAkT +XXg+ciFFdT2P2S4L1bA8aNoyoZj4yFcF2lBafnak5A9zwU/lBUDyO/tVpeEnfyvGeoH1sfqo XLy/sJK29FCe7AHJStOSHHWfugo4S3IFksWxrGslwG1MgZyGskUvGS2c4TnChaDMiz9FDXOme wDBjjCoXYrtZ9gE+bWksyEBS/BUfvqR1TlGaG4AX1J8EHhO3+P4WrXzAD3r825i99zjxpDqrr 68rPR9Gt3VjnRN2rj3hEKsd2Icj/TbgBvAUtj+LM4++YdghOSBr3FupQvlje0/hJ0336joCuH ep9eJrZ2C8uzJPKac2wEtzDOBzKXsH0oO4yNWWcHXZ2YpavNfgThntAr15VeorMJo58OJmqdP 32CdokHcZuVu34pdshn8Km9DtRkdpmHJArCnsUw37lOPrXMfWy4bkSrbK0RHxDckg7NTPnTe+ qLbnNDzZCgaPEH8+9KR43/5LS2KQIfA9ufyne1/PmqmiRoNrShm4R4ElvPIJQL5ZU1HFQ/G4x H2QAt1cnARCEbimwqfA4Ir+U1XvgVDB03flYLWsET0UoS8HLuN+m4n/2nj8iIoFogilo= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.126.134 Subject: [Qemu-devel] [PATCH 2/5] m68k: implement server and client side X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, Laurent Vivier Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This also adds the basic test file and the configuration update. This implementation can only test instructions with values in register and no memory access. Signed-off-by: Laurent Vivier --- configure | 6 ++- risu_m68k.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ risu_reginfo_m68k.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++ risu_reginfo_m68k.h | 32 +++++++++++ test_m68k.s | 28 ++++++++++ 5 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 risu_m68k.c create mode 100644 risu_reginfo_m68k.c create mode 100644 risu_reginfo_m68k.h create mode 100644 test_m68k.s diff --git a/configure b/configure index f81bdb5..f5921ee 100755 --- a/configure +++ b/configure @@ -18,7 +18,9 @@ EOF } guess_arch() { - if check_define __arm__ ; then + if check_define __m68k__ ; then + ARCH="m68k" + elif check_define __arm__ ; then ARCH="arm" elif check_define __aarch64__ ; then ARCH="aarch64" @@ -63,7 +65,7 @@ Some influential environment variables: prefixed with the given string. ARCH force target architecture instead of trying to detect it. - Valid values=[arm|aarch64|ppc64|ppc64le] + Valid values=[arm|aarch64|ppc64|ppc64le|m68k] CC C compiler command CFLAGS C compiler flags diff --git a/risu_m68k.c b/risu_m68k.c new file mode 100644 index 0000000..15e30b1 --- /dev/null +++ b/risu_m68k.c @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2016 Laurent Vivier + * 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 + ******************************************************************************/ + +#include +#include +#include + +#include "risu.h" +#include "risu_reginfo_m68k.h" + +struct reginfo master_ri, apprentice_ri; +static int mem_used = 0; +static int packet_mismatch = 0; + +uint8_t apprentice_memblock[MEMBLOCKLEN]; + +void advance_pc(void *vuc) +{ + ucontext_t *uc = (ucontext_t*)vuc; + uc->uc_mcontext.gregs[R_PC] += 4; +} + +void set_a0(void *vuc, uint32_t a0) +{ + ucontext_t *uc = vuc; + uc->uc_mcontext.gregs[R_A0] = a0; +} + +static int get_risuop(uint32_t insn) +{ + uint32_t op = insn & 0xf; + uint32_t key = insn & ~0xf; + uint32_t risukey = 0x4afc7000; + return (key != risukey) ? -1 : op; +} + +int send_register_info(int sock, void *uc) +{ + struct reginfo ri; + int op; + + reginfo_init(&ri, uc); + op = get_risuop(ri.faulting_insn); + + switch (op) { + case OP_COMPARE: + case OP_TESTEND: + default: + return send_data_pkt(sock, &ri, sizeof(ri)); + case OP_SETMEMBLOCK: + memblock = (void*)ri.gregs[R_A0]; + break; + case OP_GETMEMBLOCK: + set_a0(uc, ri.gregs[R_A0] + (uintptr_t)memblock); + break; + case OP_COMPAREMEM: + return send_data_pkt(sock, memblock, MEMBLOCKLEN); + break; + } + return 0; +} + +/* 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; + int op; + + reginfo_init(&master_ri, uc); + op = get_risuop(master_ri.faulting_insn); + + switch (op) { + case OP_COMPARE: + case OP_TESTEND: + default: + if (recv_data_pkt(sock, &apprentice_ri, sizeof(apprentice_ri))) { + packet_mismatch = 1; + resp = 2; + } else if (!reginfo_is_eq(&master_ri, &apprentice_ri, uc)) { + resp = 2; + } + else if (op == OP_TESTEND) { + resp = 1; + } + send_response_byte(sock, resp); + break; + case OP_SETMEMBLOCK: + memblock = (void*)master_ri.gregs[R_A0]; + break; + case OP_GETMEMBLOCK: + set_a0(uc, master_ri.gregs[R_A0] + (uintptr_t)memblock); + break; + case OP_COMPAREMEM: + mem_used = 1; + if (recv_data_pkt(sock, apprentice_memblock, MEMBLOCKLEN)) { + packet_mismatch = 1; + resp = 2; + } else if (memcmp(memblock, apprentice_memblock, MEMBLOCKLEN) != 0) { + resp = 2; + } + send_response_byte(sock, resp); + break; + } + 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) +{ + int resp = 0; + fprintf(stderr, "match status...\n"); + + if (packet_mismatch) { + fprintf(stderr, "packet mismatch (probably disagreement " + "about UNDEF on load/store)\n"); + fprintf(stderr, "master reginfo:\n"); + reginfo_dump(&master_ri, 0); + } + if (!reginfo_is_eq(&master_ri, &apprentice_ri, NULL)) { + fprintf(stderr, "mismatch on regs!\n"); + resp = 1; + } + if (mem_used && memcmp(memblock, &apprentice_memblock, MEMBLOCKLEN) != 0) { + fprintf(stderr, "mismatch on memory!\n"); + resp = 1; + } + if (!resp) { + fprintf(stderr, "match!\n"); + return 0; + } + + fprintf(stderr, "master reginfo:\n"); + reginfo_dump(&master_ri, 1); + + fprintf(stderr, "apprentice reginfo:\n"); + reginfo_dump(&apprentice_ri, 0); + + reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr); + return resp; +} diff --git a/risu_reginfo_m68k.c b/risu_reginfo_m68k.c new file mode 100644 index 0000000..c9d21cc --- /dev/null +++ b/risu_reginfo_m68k.c @@ -0,0 +1,151 @@ +/***************************************************************************** + * Copyright (c) 2016 Laurent Vivier + * 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 + *****************************************************************************/ + +#include +#include +#include +#include + +#include "risu.h" +#include "risu_reginfo_m68k.h" + +/* reginfo_init: initialize with a ucontext */ +void reginfo_init(struct reginfo *ri, ucontext_t *uc) +{ + int i; + memset(ri, 0, sizeof(*ri)); + + ri->faulting_insn = *((uint32_t *)uc->uc_mcontext.gregs[R_PC]); + ri->pc = uc->uc_mcontext.gregs[R_PC] - image_start_address; + + for (i = 0; i < NGREG; i++) { + ri->gregs[i] = uc->uc_mcontext.gregs[i]; + } + + ri->fpregs.f_pcr = uc->uc_mcontext.fpregs.f_pcr; + ri->fpregs.f_psr = uc->uc_mcontext.fpregs.f_psr; + ri->fpregs.f_fpiaddr = uc->uc_mcontext.fpregs.f_fpiaddr; + for (i = 0; i < 8; i++) { + memcpy(&ri->fpregs.f_fpregs[i * 3], + &uc->uc_mcontext.fpregs.f_fpregs[i * 3], + 3 * sizeof(int)); + } +} + +/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */ +int reginfo_is_eq(struct reginfo *m, struct reginfo *a, ucontext_t *uc) +{ + int i; + + if (m->gregs[R_PS] != a->gregs[R_PS]) { + return 0; + } + + for (i = 0; i < 16; i++) { + if (i == R_SP || i == R_A6) { + continue; + } + if (m->gregs[i] != a->gregs[i]) { + return 0; + } + } + + if (m->fpregs.f_pcr != a->fpregs.f_pcr) { + return 0; + } + + if (m->fpregs.f_psr != a->fpregs.f_psr) { + return 0; + } + + for (i = 0; i < 8; i++) { + if (m->fpregs.f_fpregs[i * 3] != a->fpregs.f_fpregs[i * 3] || + m->fpregs.f_fpregs[i * 3 + 1] != a->fpregs.f_fpregs[i * 3 + 1] || + m->fpregs.f_fpregs[i * 3 + 2] != a->fpregs.f_fpregs[i * 3 + 2]) { + 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, " pc \e[1;101;37m0x%08x\e[0m\n", + ri->pc); + } + fprintf(stderr, "\tPC: %08x\n", ri->gregs[R_PC]); + fprintf(stderr, "\tPS: %04x\n", ri->gregs[R_PS]); + + for (i = 0; i < 8; i++) { + fprintf(stderr, "\tD%d: %8x\tA%d: %8x\n", i, ri->gregs[i], + i, ri->gregs[i + 8]); + } + + + for (i = 0; i < 8; i++) { + fprintf(stderr, "\tFP%d: %08x %08x %08x\n", i, + ri->fpregs.f_fpregs[i * 3], ri->fpregs.f_fpregs[i * 3 + 1], + ri->fpregs.f_fpregs[i * 3 + 2]); + } + + fprintf(stderr, "\n"); +} + +int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f) +{ + int i; + + if (m->gregs[R_PS] != a->gregs[R_PS]) { + fprintf(f, "Mismatch: Register PS\n"); + fprintf(f, "master: [%x] - apprentice: [%x]\n", + m->gregs[R_PS], a->gregs[R_PS]); + } + + for (i = 0; i < 16; i++) { + if (i == R_SP || i == R_A6) { + continue; + } + if (m->gregs[i] != a->gregs[i]) { + fprintf(f, "Mismatch: Register %c%d\n", i < 8 ? 'D' : 'A', i % 8); + fprintf(f, "master: [%x] - apprentice: [%x]\n", + m->gregs[i], a->gregs[i]); + } + } + + if (m->fpregs.f_pcr != a->fpregs.f_pcr) { + fprintf(f, "Mismatch: Register FPCR\n"); + fprintf(f, "m: [%04x] != a: [%04x]\n", + m->fpregs.f_pcr, a->fpregs.f_pcr); + } + + if (m->fpregs.f_psr != a->fpregs.f_psr) { + fprintf(f, "Mismatch: Register FPSR\n"); + fprintf(f, "m: [%08x] != a: [%08x]\n", + m->fpregs.f_psr, a->fpregs.f_psr); + } + + for (i = 0; i < 8; i++) { + if (m->fpregs.f_fpregs[i * 3] != a->fpregs.f_fpregs[i * 3] || + m->fpregs.f_fpregs[i * 3 + 1] != a->fpregs.f_fpregs[i * 3 + 1] || + m->fpregs.f_fpregs[i * 3 + 2] != a->fpregs.f_fpregs[i * 3 + 2]) { + fprintf(f, "Mismatch: Register FP%d\n", i); + fprintf(f, "m: [%08x %08x %08x] != a: [%08x %08x %08x]\n", + m->fpregs.f_fpregs[i * 3], m->fpregs.f_fpregs[i * 3 + 1], + m->fpregs.f_fpregs[i * 3 + 2], a->fpregs.f_fpregs[i * 3], + a->fpregs.f_fpregs[i * 3 + 1], + a->fpregs.f_fpregs[i * 3 + 2]); + } + } + + + return !ferror(f); +} diff --git a/risu_reginfo_m68k.h b/risu_reginfo_m68k.h new file mode 100644 index 0000000..9dd8f32 --- /dev/null +++ b/risu_reginfo_m68k.h @@ -0,0 +1,32 @@ +/***************************************************************************** + * Copyright (c) 2016 Laurent Vivier + * 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 + *****************************************************************************/ + +#ifndef RISU_REGINFO_M68K_H +#define RISU_REGINFO_M68K_H + +struct reginfo +{ + uint32_t faulting_insn; + uint32_t pc; + gregset_t gregs; + fpregset_t fpregs; +}; + +/* 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); + +/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */ +int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f); + +#endif /* RISU_REGINFO_M68K_H */ diff --git a/test_m68k.s b/test_m68k.s new file mode 100644 index 0000000..6ca8a92 --- /dev/null +++ b/test_m68k.s @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2016 Laurent Vivier + * 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 + ******************************************************************************* + +/* Initialise the gp regs */ +moveq.l #0, %d0 +move.l %d0, %d1 +move.l %d0, %d2 +move.l %d0, %d3 +move.l %d0, %d4 +move.l %d0, %d5 +move.l %d0, %d6 +move.l %d0, %d7 +move.l %d0, %a0 +move.l %d0, %a1 +move.l %d0, %a2 +move.l %d0, %a3 +move.l %d0, %a4 +move.l %d0, %a5 + +/* do compare */ +.int 0x4afc7000 +/* exit test */ +.int 0x4afc7001