From patchwork Thu Mar 7 05:43:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Popple X-Patchwork-Id: 1052649 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (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 44FKLl1FkCz9sBF for ; Thu, 7 Mar 2019 16:43:59 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=popple.id.au Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 44FKLl01f8zDqCq for ; Thu, 7 Mar 2019 16:43:59 +1100 (AEDT) X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [203.11.71.1]) (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 44FKLc19NDzDqCC for ; Thu, 7 Mar 2019 16:43:52 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=popple.id.au Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 44FKLb5Dnbz9s9T; Thu, 7 Mar 2019 16:43:51 +1100 (AEDT) From: Alistair Popple To: stewart@linux.vnet.ibm.com, npiggin@gmail.com Date: Thu, 7 Mar 2019 16:43:34 +1100 Message-Id: <20190307054334.3088-1-alistair@popple.id.au> X-Mailer: git-send-email 2.11.0 Subject: [Pdbg] [PATCH v2] WIP: POWER8 SRESET 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: pdbg@lists.ozlabs.org MIME-Version: 1.0 Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" SRESET on POWER8 is made more complex because it can only be run if a thread is in a powersave state. This makes getting an active thread into SRESET hard because we need to emulate what the processor does using instruction ramming. This patch aims to implement this sequence. If a thread is in a nap state it will just use the direct controls, however if it is in an active state it will quiesce the thread and use instruction ramming to put the thread at the 0x100 sreset exception vector. Signed-off-by: Alistair Popple --- libpdbg/chip.c | 42 ++++++++++++++++++++++++++++++++++++++++++ libpdbg/p8chip.c | 24 ++++++++++++++++++------ src/thread.c | 14 ++++++++++++++ 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/libpdbg/chip.c b/libpdbg/chip.c index 5b67c7b..da412d5 100644 --- a/libpdbg/chip.c +++ b/libpdbg/chip.c @@ -534,3 +534,45 @@ int ram_state_thread(struct pdbg_target *thread, struct thread_regs *regs) return 0; } + +#define SPR_SRR0 0x01a +#define SPR_SRR1 0x01b + +#define MSR_HV PPC_BIT(3) /* Hypervisor mode */ +#define MSR_EE PPC_BIT(48) /* External Int. Enable */ +#define MSR_FE0 PPC_BIT(52) /* FP Exception 0 */ +#define MSR_FE1 PPC_BIT(55) /* FP Exception 1 */ +#define MSR_IR PPC_BIT(58) /* Instructions reloc */ +#define MSR_DR PPC_BIT(59) /* Data reloc */ +#define MSR_RI PPC_BIT(62) /* Recoverable Interrupt */ + +int emulate_sreset(struct thread *thread) +{ + uint64_t opcodes[] = { + mfmsr(0), mtspr(277, 0), /* Get MSR */ + mfnia(0), mtspr(277, 0), /* Get NIA */ + mfspr(0, 277), mtmsr(0), /* Put modified MSR back */ + mfspr(0, 277), mtspr(SPR_SRR0, 0), /* Set SRR0 to NIA */ + mfspr(0, 277), mtspr(SPR_SRR1, 0), /* Set SRR1 to SRESET value */ + mfspr(0, 277), mtnia(0), /* Set NIA */ + }; + uint64_t results[] = { + 0, 0, + 0, 0, + 0, 0, + 0, 0, /* SRR0 */ + 0, 0, /* SRR1 SRESET value */ + 0x100, 0, /* Set NIA = 0x100 */ + }; + + /* RAM first 4 opcodes */ + CHECK_ERR(ram_instructions(&thread->target, opcodes, results, 4, 0)); + + /* Set MSR, SRR0 = NIA and ram remaining instructions*/ + results[4] = (results[1] & ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE | MSR_RI)) | MSR_HV; + results[6] = results[3]; + results[8] = results[1]; + CHECK_ERR(ram_instructions(&thread->target, &opcodes[4], &results[4], ARRAY_SIZE(opcodes) - 4, 0)); + + return 0; +} diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c index 914c335..50fef5f 100644 --- a/libpdbg/p8chip.c +++ b/libpdbg/p8chip.c @@ -29,6 +29,8 @@ #define RAS_STATUS_TIMEOUT 100 #define DIRECT_CONTROLS_REG 0x0 +#define DIRECT_CONTROL_PRENAP PPC_BIT(47) +#define DIRECT_CONTROL_SRESET PPC_BIT(60) #define DIRECT_CONTROL_SP_STEP PPC_BIT(61) #define DIRECT_CONTROL_SP_START PPC_BIT(62) #define DIRECT_CONTROL_SP_STOP PPC_BIT(63) @@ -337,12 +339,6 @@ static int p8_thread_start(struct thread *thread) return 0; } -static int p8_thread_sreset(struct thread *thread) -{ - /* Broken on p8 */ - return 1; -} - static int p8_ram_setup(struct thread *thread) { struct pdbg_target *target; @@ -440,6 +436,22 @@ static int p8_ram_destroy(struct thread *thread) return 0; } +int emulate_sreset(struct thread *thread); +static int p8_thread_sreset(struct thread *thread) +{ + if (!p8_ram_setup(thread)) { + /* Thread was active, emulate the sreset */ + emulate_sreset(thread); + p8_ram_destroy(thread); + } else { + /* Use direct controls */ + CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_PRENAP)); + CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SRESET)); + } + + return 0; +} + static int p8_ram_getxer(struct pdbg_target *thread, uint64_t *value) { uint64_t opcodes[] = {mfxerf(0, 0), mtspr(277, 0), mfxerf(0, 1), diff --git a/src/thread.c b/src/thread.c index 1fd448d..f6a19b9 100644 --- a/src/thread.c +++ b/src/thread.c @@ -296,10 +296,24 @@ static int thread_sreset(void) if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) continue; + ram_stop_thread(target); + } + + for_each_path_target_class("thread", target) { + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) + continue; + ram_sreset_thread(target); count++; } + for_each_path_target_class("thread", target) { + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) + continue; + + ram_start_thread(target); + } + return count; } OPTCMD_DEFINE_CMD(sreset, thread_sreset);