From patchwork Mon Jun 22 00:44:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitay Isaacs X-Patchwork-Id: 1314033 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49qrLL0KLXz9sRh for ; Mon, 22 Jun 2020 10:45:46 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.a=rsa-sha256 header.s=201707 header.b=F/xF/H0W; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 49qrLK6S3jzDqbv for ; Mon, 22 Jun 2020 10:45:45 +1000 (AEST) X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 49qrKj3hWQzDqWf for ; Mon, 22 Jun 2020 10:45:13 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.a=rsa-sha256 header.s=201707 header.b=F/xF/H0W; dkim-atps=neutral Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 49qrKj1Fh7z9sRR; Mon, 22 Jun 2020 10:45:13 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1592786713; bh=yXX66p3jvENDW022KywLmSG0V7faNr3ijdoCEwEoLFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F/xF/H0W/+P6Iw8hLkROLRTE19Gx4ju0LPAMHZhtapAGPhSb96JOex8A6kYOlux1Q c2CnnmqEJn6hIHSx6aGJ4AYiRxJo4DDLZoXAn0MqcL5DWlvcNOkhFJsmqr/zxy1tdG q/ZYFgx0AwP6WqsjGMlNQqdyQXlT1WdZfBWK+acEdWTJa5VUE3LYCCPrblOOrMWE7B 282cWKwZHFloWxqHSAALoVY9v8hNNaigpvAIk/LO/s6GQywN9xUVYQFem06KKD8CRi sRt9ckG28I6t2bJSdAEs/ZqVOSdrDCSoCBp9KfjecG+QJHrbRCkncjgEpnbHf7UBco TkbmrFj8mTGHw== From: Amitay Isaacs To: pdbg@lists.ozlabs.org Date: Mon, 22 Jun 2020 10:44:59 +1000 Message-Id: <20200622004501.12889-8-amitay@ozlabs.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200622004501.12889-1-amitay@ozlabs.org> References: <20200622004501.12889-1-amitay@ozlabs.org> MIME-Version: 1.0 Subject: [Pdbg] [PATCH 7/9] libpdbg: Rearrange thread procedures for register access X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "mailing list for https://github.com/open-power/pdbg development" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Amitay Isaacs Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" This moves libpdbg thread api to thread.c. Also, the implementation based ramming instructions moves to the specific thread drivers. Signed-off-by: Amitay Isaacs --- Makefile.am | 3 +- libpdbg/chip.c | 318 +++++++-------------------------------------- libpdbg/chip.h | 19 +++ libpdbg/hwunit.h | 2 - libpdbg/p8chip.c | 17 ++- libpdbg/p9chip.c | 21 ++- libpdbg/thread.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 429 insertions(+), 279 deletions(-) create mode 100644 libpdbg/thread.c diff --git a/Makefile.am b/Makefile.am index f51afb3..4247913 100644 --- a/Makefile.am +++ b/Makefile.am @@ -207,7 +207,8 @@ libpdbg_la_SOURCES = \ libpdbg/sbefifo.c \ libpdbg/sprs.h \ libpdbg/target.c \ - libpdbg/target.h + libpdbg/target.h \ + libpdbg/thread.c libpdbg_la_CFLAGS = -Wall -Werror libpdbg_la_LIBADD = libcronus.la libsbefifo.la diff --git a/libpdbg/chip.c b/libpdbg/chip.c index 58eedeb..a5afe5c 100644 --- a/libpdbg/chip.c +++ b/libpdbg/chip.c @@ -26,6 +26,7 @@ #include "bitutils.h" #include "debug.h" #include "sprs.h" +#include "chip.h" uint64_t mfspr(uint64_t reg, uint64_t spr) { @@ -107,166 +108,6 @@ static uint64_t ld(uint64_t rt, uint64_t ds, uint64_t ra) return LD_OPCODE | (rt << 21) | (ra << 16) | (ds << 2); } -struct thread_state thread_status(struct pdbg_target *target) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - return thread->status; -} - -/* - * Single step the thread count instructions. - */ -int thread_step(struct pdbg_target *target, int count) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - return thread->step(thread, count); -} - -int thread_start(struct pdbg_target *target) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - return thread->start(thread); -} - -int thread_stop(struct pdbg_target *target) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - return thread->stop(thread); -} - -int thread_sreset(struct pdbg_target *target) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - return thread->sreset(thread); -} - -int thread_step_all(void) -{ - struct pdbg_target *target, *thread; - int rc = 0, count = 0; - - pdbg_for_each_class_target("pib", target) { - struct pib *pib = target_to_pib(target); - - if (!pib->thread_step_all) - break; - - rc |= pib->thread_step_all(pib, 1); - count++; - } - - if (count > 0) - return rc; - - pdbg_for_each_class_target("thread", thread) { - if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) - continue; - - rc |= thread_step(thread, 1); - } - - return rc; -} - -int thread_start_all(void) -{ - struct pdbg_target *target, *thread; - int rc = 0, count = 0; - - pdbg_for_each_class_target("pib", target) { - struct pib *pib = target_to_pib(target); - - if (!pib->thread_start_all) - break; - - rc |= pib->thread_start_all(pib); - count++; - } - - if (count > 0) - return rc; - - pdbg_for_each_class_target("thread", thread) { - if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) - continue; - - rc |= thread_start(thread); - } - - return rc; -} - -int thread_stop_all(void) -{ - struct pdbg_target *target, *thread; - int rc = 0, count = 0; - - pdbg_for_each_class_target("pib", target) { - struct pib *pib = target_to_pib(target); - - if (!pib->thread_stop_all) - break; - - rc |= pib->thread_stop_all(pib); - count++; - } - - if (count > 0) - return rc; - - pdbg_for_each_class_target("thread", thread) { - if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) - continue; - - rc |= thread_stop(thread); - } - - return rc; -} - -int thread_sreset_all(void) -{ - struct pdbg_target *target, *thread; - int rc = 0, count = 0; - - pdbg_for_each_class_target("pib", target) { - struct pib *pib = target_to_pib(target); - - if (!pib->thread_sreset_all) - break; - - rc |= pib->thread_sreset_all(pib); - count++; - } - - if (count > 0) - return rc; - - pdbg_for_each_class_target("thread", thread) { - if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) - continue; - - rc |= thread_sreset(thread); - } - - return rc; -} - /* * RAMs the opcodes in *opcodes and store the results of each opcode * into *results. *results must point to an array the same size as @@ -336,40 +177,30 @@ int ram_instructions(struct thread *thread, uint64_t *opcodes, /* * Get gpr value. Chip must be stopped. */ -int thread_getgpr(struct pdbg_target *target, int gpr, uint64_t *value) +int ram_getgpr(struct thread *thread, int gpr, uint64_t *value) { - struct thread *thread; uint64_t opcodes[] = {mtspr(277, gpr)}; uint64_t results[] = {0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); *value = results[0]; return 0; } -int thread_putgpr(struct pdbg_target *target, int gpr, uint64_t value) +int ram_putgpr(struct thread *thread, int gpr, uint64_t value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(gpr, 277)}; uint64_t results[] = {value}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); - return 0; } -int thread_getnia(struct pdbg_target *target, uint64_t *value) +int ram_getnia(struct thread *thread, uint64_t *value) { - struct thread *thread; uint64_t opcodes[] = {mfnia(0), mtspr(277, 0)}; uint64_t results[] = {0, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); *value = results[1]; return 0; @@ -382,9 +213,8 @@ int thread_getnia(struct pdbg_target *target, uint64_t *value) * This is a hack and should be made much cleaner once we have target * specific putspr commands. */ -int thread_putnia(struct pdbg_target *target, uint64_t value) +int ram_putnia(struct thread *thread, uint64_t value) { - struct thread *thread; uint64_t opcodes[] = { mfspr(1, 8), /* mflr r1 */ mfspr(0, 277), /* value -> r0 */ mtspr(8, 0), /* mtlr r0 */ @@ -392,53 +222,41 @@ int thread_putnia(struct pdbg_target *target, uint64_t value) mtspr(8, 1), }; /* mtlr r1 */ uint64_t results[] = {0, value, 0, 0, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); return 0; } -int thread_getspr(struct pdbg_target *target, int spr, uint64_t *value) +int ram_getspr(struct thread *thread, int spr, uint64_t *value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(0, spr), mtspr(277, 0)}; uint64_t results[] = {0, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); *value = results[1]; return 0; } -int thread_putspr(struct pdbg_target *target, int spr, uint64_t value) +int ram_putspr(struct thread *thread, int spr, uint64_t value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(0, 277), mtspr(spr, 0)}; uint64_t results[] = {value, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); return 0; } -int thread_getmsr(struct pdbg_target *target, uint64_t *value) +int ram_getmsr(struct thread *thread, uint64_t *value) { - struct thread *thread; uint64_t opcodes[] = {mfmsr(0), mtspr(277, 0)}; uint64_t results[] = {0, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); *value = results[1]; return 0; } -int thread_getcr(struct pdbg_target *target, uint32_t *value) +int ram_getcr(struct thread *thread, uint32_t *value) { - struct thread *thread; uint64_t opcodes[] = {mfocrf(0, 0), mtspr(277, 0), mfocrf(0, 1), mtspr(277, 0), mfocrf(0, 2), mtspr(277, 0), mfocrf(0, 3), mtspr(277, 0), mfocrf(0, 4), mtspr(277, 0), mfocrf(0, 5), mtspr(277, 0), @@ -447,8 +265,6 @@ int thread_getcr(struct pdbg_target *target, uint32_t *value) uint32_t cr_field, cr = 0; int i; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); for (i = 1; i < 16; i += 2) { cr_field = results[i]; @@ -460,70 +276,36 @@ int thread_getcr(struct pdbg_target *target, uint32_t *value) return 0; } -int thread_putcr(struct pdbg_target *target, uint32_t value) +int ram_putcr(struct thread *thread, uint32_t value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(0, 277), mtocrf(0, 0), mtocrf(1, 0), mtocrf(2, 0), mtocrf(3, 0), mtocrf(4, 0), mtocrf(5, 0), mtocrf(6, 0), mtocrf(7, 0)}; uint64_t results[] = {value}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); - return 0; } -int thread_putmsr(struct pdbg_target *target, uint64_t value) +int ram_putmsr(struct thread *thread, uint64_t value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(0, 277), mtmsr(0)}; uint64_t results[] = {value, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); return 0; } -int thread_getmem(struct pdbg_target *target, uint64_t addr, uint64_t *value) +int ram_getmem(struct thread *thread, uint64_t addr, uint64_t *value) { - struct thread *thread; uint64_t opcodes[] = {mfspr(0, 277), mfspr(1, 277), ld(0, 0, 1), mtspr(277, 0)}; uint64_t results[] = {0xdeaddeaddeaddead, addr, 0, 0}; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); *value = results[3]; return 0; } -int thread_getxer(struct pdbg_target *target, uint64_t *value) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - - CHECK_ERR(thread->ram_getxer(thread, value)); - - return 0; -} - -int thread_putxer(struct pdbg_target *target, uint64_t value) -{ - struct thread *thread; - - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - - CHECK_ERR(thread->ram_putxer(thread, value)); - - return 0; -} - /* * Read the given ring from the given chiplet. Result must be large enough to hold ring_len bits. */ @@ -536,9 +318,8 @@ int getring(struct pdbg_target *target, uint64_t ring_addr, uint64_t ring_len, u return chiplet->getring(chiplet, ring_addr, ring_len, result); } -int thread_getregs(struct pdbg_target *target, struct thread_regs *regs) +int ram_getregs(struct thread *thread, struct thread_regs *regs) { - struct thread *thread; struct thread_regs _regs; uint64_t value = 0; int i; @@ -546,9 +327,6 @@ int thread_getregs(struct pdbg_target *target, struct thread_regs *regs) if (!regs) regs = &_regs; - assert(pdbg_target_is_class(target, "thread")); - thread = target_to_thread(target); - CHECK_ERR(thread->ram_setup(thread)); /* @@ -557,117 +335,117 @@ int thread_getregs(struct pdbg_target *target, struct thread_regs *regs) * can help to diagnose checkstop issues with ramming to print as * we go. Once it's more robust and tested, maybe. */ - thread_getnia(target, ®s->nia); + ram_getnia(thread, ®s->nia); printf("NIA : 0x%016" PRIx64 "\n", regs->nia); - thread_getspr(target, SPR_CFAR, ®s->cfar); + ram_getspr(thread, SPR_CFAR, ®s->cfar); printf("CFAR : 0x%016" PRIx64 "\n", regs->cfar); - thread_getmsr(target, ®s->msr); + ram_getmsr(thread, ®s->msr); printf("MSR : 0x%016" PRIx64 "\n", regs->msr); - thread_getspr(target, SPR_LR, ®s->lr); + ram_getspr(thread, SPR_LR, ®s->lr); printf("LR : 0x%016" PRIx64 "\n", regs->lr); - thread_getspr(target, SPR_CTR, ®s->ctr); + ram_getspr(thread, SPR_CTR, ®s->ctr); printf("CTR : 0x%016" PRIx64 "\n", regs->ctr); - thread_getspr(target, 815, ®s->tar); + ram_getspr(thread, 815, ®s->tar); printf("TAR : 0x%016" PRIx64 "\n", regs->tar); - thread_getcr(target, ®s->cr); + ram_getcr(thread, ®s->cr); printf("CR : 0x%08" PRIx32 "\n", regs->cr); - thread_getxer(target, ®s->xer); + thread->getxer(thread, ®s->xer); printf("XER : 0x%08" PRIx64 "\n", regs->xer); printf("GPRS :\n"); for (i = 0; i < 32; i++) { - thread_getgpr(target, i, ®s->gprs[i]); + ram_getgpr(thread, i, ®s->gprs[i]); printf(" 0x%016" PRIx64 "", regs->gprs[i]); if (i % 4 == 3) printf("\n"); } - thread_getspr(target, SPR_LPCR, ®s->lpcr); + ram_getspr(thread, SPR_LPCR, ®s->lpcr); printf("LPCR : 0x%016" PRIx64 "\n", regs->lpcr); - thread_getspr(target, SPR_PTCR, ®s->ptcr); + ram_getspr(thread, SPR_PTCR, ®s->ptcr); printf("PTCR : 0x%016" PRIx64 "\n", regs->ptcr); - thread_getspr(target, SPR_LPIDR, ®s->lpidr); + ram_getspr(thread, SPR_LPIDR, ®s->lpidr); printf("LPIDR : 0x%016" PRIx64 "\n", regs->lpidr); - thread_getspr(target, SPR_PIDR, ®s->pidr); + ram_getspr(thread, SPR_PIDR, ®s->pidr); printf("PIDR : 0x%016" PRIx64 "\n", regs->pidr); - thread_getspr(target, SPR_HFSCR, ®s->hfscr); + ram_getspr(thread, SPR_HFSCR, ®s->hfscr); printf("HFSCR : 0x%016" PRIx64 "\n", regs->hfscr); - thread_getspr(target, SPR_HDSISR, &value); + ram_getspr(thread, SPR_HDSISR, &value); regs->hdsisr = value; printf("HDSISR: 0x%08" PRIx32 "\n", regs->hdsisr); - thread_getspr(target, SPR_HDAR, ®s->hdar); + ram_getspr(thread, SPR_HDAR, ®s->hdar); printf("HDAR : 0x%016" PRIx64 "\n", regs->hdar); - thread_getspr(target, SPR_HEIR, &value); + ram_getspr(thread, SPR_HEIR, &value); regs->heir = value; printf("HEIR : 0x%016" PRIx32 "\n", regs->heir); - thread_getspr(target, SPR_HID, ®s->hid); + ram_getspr(thread, SPR_HID, ®s->hid); printf("HID0 : 0x%016" PRIx64 "\n", regs->hid); - thread_getspr(target, SPR_HSRR0, ®s->hsrr0); + ram_getspr(thread, SPR_HSRR0, ®s->hsrr0); printf("HSRR0 : 0x%016" PRIx64 "\n", regs->hsrr0); - thread_getspr(target, SPR_HSRR1, ®s->hsrr1); + ram_getspr(thread, SPR_HSRR1, ®s->hsrr1); printf("HSRR1 : 0x%016" PRIx64 "\n", regs->hsrr1); - thread_getspr(target, SPR_HDEC, ®s->hdec); + ram_getspr(thread, SPR_HDEC, ®s->hdec); printf("HDEC : 0x%016" PRIx64 "\n", regs->hdec); - thread_getspr(target, SPR_HSPRG0, ®s->hsprg0); + ram_getspr(thread, SPR_HSPRG0, ®s->hsprg0); printf("HSPRG0: 0x%016" PRIx64 "\n", regs->hsprg0); - thread_getspr(target, SPR_HSPRG1, ®s->hsprg1); + ram_getspr(thread, SPR_HSPRG1, ®s->hsprg1); printf("HSPRG1: 0x%016" PRIx64 "\n", regs->hsprg1); - thread_getspr(target, SPR_FSCR, ®s->fscr); + ram_getspr(thread, SPR_FSCR, ®s->fscr); printf("FSCR : 0x%016" PRIx64 "\n", regs->fscr); - thread_getspr(target, SPR_DSISR, &value); + ram_getspr(thread, SPR_DSISR, &value); regs->dsisr = value; printf("DSISR : 0x%08" PRIx32 "\n", regs->dsisr); - thread_getspr(target, SPR_DAR, ®s->dar); + ram_getspr(thread, SPR_DAR, ®s->dar); printf("DAR : 0x%016" PRIx64 "\n", regs->dar); - thread_getspr(target, SPR_SRR0, ®s->srr0); + ram_getspr(thread, SPR_SRR0, ®s->srr0); printf("SRR0 : 0x%016" PRIx64 "\n", regs->srr0); - thread_getspr(target, SPR_SRR1, ®s->srr1); + ram_getspr(thread, SPR_SRR1, ®s->srr1); printf("SRR1 : 0x%016" PRIx64 "\n", regs->srr1); - thread_getspr(target, SPR_DEC, ®s->dec); + ram_getspr(thread, SPR_DEC, ®s->dec); printf("DEC : 0x%016" PRIx64 "\n", regs->dec); - thread_getspr(target, SPR_TB, ®s->tb); + ram_getspr(thread, SPR_TB, ®s->tb); printf("TB : 0x%016" PRIx64 "\n", regs->tb); - thread_getspr(target, SPR_SPRG0, ®s->sprg0); + ram_getspr(thread, SPR_SPRG0, ®s->sprg0); printf("SPRG0 : 0x%016" PRIx64 "\n", regs->sprg0); - thread_getspr(target, SPR_SPRG1, ®s->sprg1); + ram_getspr(thread, SPR_SPRG1, ®s->sprg1); printf("SPRG1 : 0x%016" PRIx64 "\n", regs->sprg1); - thread_getspr(target, SPR_SPRG2, ®s->sprg2); + ram_getspr(thread, SPR_SPRG2, ®s->sprg2); printf("SPRG2 : 0x%016" PRIx64 "\n", regs->sprg2); - thread_getspr(target, SPR_SPRG3, ®s->sprg3); + ram_getspr(thread, SPR_SPRG3, ®s->sprg3); printf("SPRG3 : 0x%016" PRIx64 "\n", regs->sprg3); - thread_getspr(target, SPR_PPR, ®s->ppr); + ram_getspr(thread, SPR_PPR, ®s->ppr); printf("PPR : 0x%016" PRIx64 "\n", regs->ppr); CHECK_ERR(thread->ram_destroy(thread)); diff --git a/libpdbg/chip.h b/libpdbg/chip.h index b3342b8..6856c64 100644 --- a/libpdbg/chip.h +++ b/libpdbg/chip.h @@ -24,4 +24,23 @@ uint64_t mtspr(uint64_t spr, uint64_t reg) __attribute__ ((visibility("hidden")) int ram_instructions(struct thread *thread, uint64_t *opcodes, uint64_t *results, int len, unsigned int lpar) __attribute__ ((visibility("hidden"))); + +int ram_getmem(struct thread *thread, uint64_t addr, uint64_t *value); +int ram_getregs(struct thread *thread, struct thread_regs *regs); + +int ram_getgpr(struct thread *thread, int gpr, uint64_t *value); +int ram_putgpr(struct thread *thread, int gpr, uint64_t value); + +int ram_getnia(struct thread *thread, uint64_t *value); +int ram_putnia(struct thread *thread, uint64_t value); + +int ram_getspr(struct thread *thread, int spr, uint64_t *value); +int ram_putspr(struct thread *thread, int spr, uint64_t value); + +int ram_getmsr(struct thread *thread, uint64_t *value); +int ram_putmsr(struct thread *thread, uint64_t value); + +int ram_getcr(struct thread *thread, uint32_t *value); +int ram_putcr(struct thread *thread, uint32_t value); + #endif diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h index fd643b4..691689f 100644 --- a/libpdbg/hwunit.h +++ b/libpdbg/hwunit.h @@ -140,8 +140,6 @@ struct thread { int (*ram_setup)(struct thread *); int (*ram_instruction)(struct thread *, uint64_t opcode, uint64_t *scratch); int (*ram_destroy)(struct thread *); - int (*ram_getxer)(struct thread *, uint64_t *value); - int (*ram_putxer)(struct thread *, uint64_t value); int (*enable_attn)(struct thread *); int (*getmem)(struct thread *, uint64_t, uint64_t *); diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c index 50ab143..4179557 100644 --- a/libpdbg/p8chip.c +++ b/libpdbg/p8chip.c @@ -26,6 +26,7 @@ #include "bitutils.h" #include "debug.h" #include "sprs.h" +#include "chip.h" #define RAS_STATUS_TIMEOUT 100 @@ -655,9 +656,21 @@ static struct thread p8_thread = { .ram_setup = p8_ram_setup, .ram_instruction = p8_ram_instruction, .ram_destroy = p8_ram_destroy, - .ram_getxer = p8_ram_getxer, - .ram_putxer = p8_ram_putxer, .enable_attn = p8_enable_attn, + .getmem = ram_getmem, + .getregs = ram_getregs, + .getgpr = ram_getgpr, + .putgpr = ram_putgpr, + .getspr = ram_getspr, + .putspr = ram_putspr, + .getmsr = ram_getmsr, + .putmsr = ram_putmsr, + .getnia = ram_getnia, + .putnia = ram_putnia, + .getxer = p8_ram_getxer, + .putxer = p8_ram_putxer, + .getcr = ram_getcr, + .putcr = ram_putcr, }; DECLARE_HW_UNIT(p8_thread); diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c index abd2ab2..a46d053 100644 --- a/libpdbg/p9chip.c +++ b/libpdbg/p9chip.c @@ -25,6 +25,7 @@ #include "bitutils.h" #include "debug.h" #include "sprs.h" +#include "chip.h" /* * NOTE! @@ -407,14 +408,14 @@ static int p9_ram_destroy(struct thread *thread) static int p9_ram_getxer(struct thread *thread, uint64_t *value) { - CHECK_ERR(thread_getspr(&thread->target, SPR_XER, value)); + CHECK_ERR(ram_getspr(thread, SPR_XER, value)); return 0; } static int p9_ram_putxer(struct thread *thread, uint64_t value) { - CHECK_ERR(thread_putspr(&thread->target, SPR_XER, value)); + CHECK_ERR(ram_putspr(thread, SPR_XER, value)); return 0; @@ -435,8 +436,20 @@ static struct thread p9_thread = { .ram_setup = p9_ram_setup, .ram_instruction = p9_ram_instruction, .ram_destroy = p9_ram_destroy, - .ram_getxer = p9_ram_getxer, - .ram_putxer = p9_ram_putxer, + .getmem = ram_getmem, + .getregs = ram_getregs, + .getgpr = ram_getgpr, + .putgpr = ram_putgpr, + .getspr = ram_getspr, + .putspr = ram_putspr, + .getmsr = ram_getmsr, + .putmsr = ram_putmsr, + .getnia = ram_getnia, + .putnia = ram_putnia, + .getxer = p9_ram_getxer, + .putxer = p9_ram_putxer, + .getcr = ram_getcr, + .putcr = ram_putcr, }; DECLARE_HW_UNIT(p9_thread); diff --git a/libpdbg/thread.c b/libpdbg/thread.c new file mode 100644 index 0000000..193efb2 --- /dev/null +++ b/libpdbg/thread.c @@ -0,0 +1,328 @@ +/* Copyright 2020 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "libpdbg.h" +#include "hwunit.h" +#include "debug.h" + +struct thread_state thread_status(struct pdbg_target *target) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + return thread->status; +} + +/* + * Single step the thread count instructions. + */ +int thread_step(struct pdbg_target *target, int count) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + return thread->step(thread, count); +} + +int thread_start(struct pdbg_target *target) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + return thread->start(thread); +} + +int thread_stop(struct pdbg_target *target) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + return thread->stop(thread); +} + +int thread_sreset(struct pdbg_target *target) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + return thread->sreset(thread); +} + +int thread_step_all(void) +{ + struct pdbg_target *target, *thread; + int rc = 0, count = 0; + + pdbg_for_each_class_target("pib", target) { + struct pib *pib = target_to_pib(target); + + if (!pib->thread_step_all) + break; + + rc |= pib->thread_step_all(pib, 1); + count++; + } + + if (count > 0) + return rc; + + pdbg_for_each_class_target("thread", thread) { + if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) + continue; + + rc |= thread_step(thread, 1); + } + + return rc; +} + +int thread_start_all(void) +{ + struct pdbg_target *target, *thread; + int rc = 0, count = 0; + + pdbg_for_each_class_target("pib", target) { + struct pib *pib = target_to_pib(target); + + if (!pib->thread_start_all) + break; + + rc |= pib->thread_start_all(pib); + count++; + } + + if (count > 0) + return rc; + + pdbg_for_each_class_target("thread", thread) { + if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) + continue; + + rc |= thread_start(thread); + } + + return rc; +} + +int thread_stop_all(void) +{ + struct pdbg_target *target, *thread; + int rc = 0, count = 0; + + pdbg_for_each_class_target("pib", target) { + struct pib *pib = target_to_pib(target); + + if (!pib->thread_stop_all) + break; + + rc |= pib->thread_stop_all(pib); + count++; + } + + if (count > 0) + return rc; + + pdbg_for_each_class_target("thread", thread) { + if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) + continue; + + rc |= thread_stop(thread); + } + + return rc; +} + +int thread_sreset_all(void) +{ + struct pdbg_target *target, *thread; + int rc = 0, count = 0; + + pdbg_for_each_class_target("pib", target) { + struct pib *pib = target_to_pib(target); + + if (!pib->thread_sreset_all) + break; + + rc |= pib->thread_sreset_all(pib); + count++; + } + + if (count > 0) + return rc; + + pdbg_for_each_class_target("thread", thread) { + if (pdbg_target_status(thread) != PDBG_TARGET_ENABLED) + continue; + + rc |= thread_sreset(thread); + } + + return rc; +} + +int thread_getmem(struct pdbg_target *target, uint64_t addr, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + if (thread->getmem) + return thread->getmem(thread, addr, value); + + PR_ERROR("Not implemented on the backend\n"); + return -1; +} + +int thread_getregs(struct pdbg_target *target, struct thread_regs *regs) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + if (thread->getregs) + return thread->getregs(thread, regs); + + PR_ERROR("Not implemented on the backend\n"); + return -1; +} + +int thread_getgpr(struct pdbg_target *target, int gpr, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getgpr(thread, gpr, value); +} + +int thread_putgpr(struct pdbg_target *target, int gpr, uint64_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putgpr(thread, gpr, value); +} + +int thread_getspr(struct pdbg_target *target, int spr, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getspr(thread, spr, value); +} + +int thread_putspr(struct pdbg_target *target, int spr, uint64_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putspr(thread, spr, value); +} + +int thread_getmsr(struct pdbg_target *target, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getmsr(thread, value); +} + +int thread_putmsr(struct pdbg_target *target, uint64_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putmsr(thread, value); +} + +int thread_getnia(struct pdbg_target *target, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getnia(thread, value); +} + +int thread_putnia(struct pdbg_target *target, uint64_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putnia(thread, value); +} + +int thread_getxer(struct pdbg_target *target, uint64_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getxer(thread, value); +} + +int thread_putxer(struct pdbg_target *target, uint64_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putxer(thread, value); +} + +int thread_getcr(struct pdbg_target *target, uint32_t *value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->getcr(thread, value); +} + +int thread_putcr(struct pdbg_target *target, uint32_t value) +{ + struct thread *thread; + + assert(pdbg_target_is_class(target, "thread")); + thread = target_to_thread(target); + + return thread->putcr(thread, value); +}