From patchwork Wed Aug 29 01:50:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rashmica Gupta X-Patchwork-Id: 963195 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.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 420TB40z6fz9s4Z for ; Wed, 29 Aug 2018 11:51:24 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IB0V0CuE"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 420TB36WfLzF1Zs for ; Wed, 29 Aug 2018 11:51:23 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IB0V0CuE"; dkim-atps=neutral X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::442; helo=mail-pf1-x442.google.com; envelope-from=rashmica.g@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IB0V0CuE"; dkim-atps=neutral Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 420T9m6bDqzDrRN for ; Wed, 29 Aug 2018 11:51:08 +1000 (AEST) Received: by mail-pf1-x442.google.com with SMTP id i26-v6so1488671pfo.12 for ; Tue, 28 Aug 2018 18:51:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZbaZUxibd4ei78ROk7le7m7suS7V8iYW9FpRWU9bqYU=; b=IB0V0CuExsDWpdyBh5/+suDXSuto033mH8BWCGJvbhtjgkmOSwWEE+QxoXFdYExTgU VWeHr97rEqXGZwhnwt6HCs9sJiSFz5PqyXrq4PWo89qXCnnVmEJ9BHCT3tKaES8FVOAZ F0iudEGXoa8U3AjvtX+10ccndkFMYnfzk39MBl0asPPJIZp8rTh0/XOVVUkxXXDRPm4B DaVOa/ufv+0V4yJPSx31s6YNRw5ocWfnXCPz+Y0Z8F1BbNmRibk+ELLDfXOnMTtbwTF1 OZUttzWJAm5OjALyURR+sK3lDeaclnzDSbuqzMdPUCgXohBxr4pCkAqSfsTJtqHDsZLw RoOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZbaZUxibd4ei78ROk7le7m7suS7V8iYW9FpRWU9bqYU=; b=bnkmu5KDw4nfG9qiRDSPi75/U6pSN1USTauY0L2MaRVxJsZaPNA/elVJNvM4VlyIUM TKU0iDt0ErBRH9Uof2Xh7q9vKQDFIfpBIQtZzmfW5KthxfKpAa4FswlMypHJqFZkPwrd J3PrgZa+NBSHdI38YLV9nhvRFH4oJh/ff+h+GIBP7YO1v1XP6cLsk+7p9Teduqu2xWo5 apwcG0BgQj0TOunNTA9jSFM8cIW89bLl3HhhYFrnsd0wQmFLYCgpQ/JJQdaaxr4G7YAG 4JhcOJAkJFiTSWB+1P0oE6t5zNIJW5q4o0vIwvbqcJI9qW+D2vRuTxOa6Rd2JGQROnfm dGFQ== X-Gm-Message-State: APzg51D9KHYEEKHZLsgKVp0W9ZiZ/6uLMNiiB4+x8mMg19kaLxxhAoe5 2gvCGpgWnLDsDUBLeIlfS6TN8HXu X-Google-Smtp-Source: ANB0VdZ4hqY6ZplDMRqvm+Lwu8sYPaCQKgE/xI6xO5Pq0VuWM7Te+xCfhTrnZWAmVdbORc9aVmq1Aw== X-Received: by 2002:a63:990a:: with SMTP id d10-v6mr3823554pge.80.1535507466553; Tue, 28 Aug 2018 18:51:06 -0700 (PDT) Received: from rashmica.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id t14-v6sm3082571pgu.0.2018.08.28.18.51.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 28 Aug 2018 18:51:06 -0700 (PDT) From: Rashmica Gupta To: pdbg@lists.ozlabs.org Date: Wed, 29 Aug 2018 11:50:31 +1000 Message-Id: <20180829015047.7355-4-rashmica.g@gmail.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180829015047.7355-1-rashmica.g@gmail.com> References: <20180829015047.7355-1-rashmica.g@gmail.com> Subject: [Pdbg] [PATCH 03/19] libpdbg: Add in getxer and putxer functions X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.27 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: npiggin@gmail.com MIME-Version: 1.0 Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" Signed-off-by: Rashmica Gupta --- libpdbg/chip.c | 40 ++++++++++++++++++------ libpdbg/chip.h | 24 +++++++++++++++ libpdbg/libpdbg.h | 4 ++- libpdbg/operations.h | 3 +- libpdbg/p8chip.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libpdbg/p9chip.c | 31 +++++++++++++++++-- libpdbg/target.h | 2 ++ 7 files changed, 177 insertions(+), 13 deletions(-) create mode 100644 libpdbg/chip.h diff --git a/libpdbg/chip.c b/libpdbg/chip.c index 1c5080e..01c9b58 100644 --- a/libpdbg/chip.c +++ b/libpdbg/chip.c @@ -26,7 +26,7 @@ #include "bitutils.h" #include "debug.h" -static uint64_t mfspr(uint64_t reg, uint64_t spr) +uint64_t mfspr(uint64_t reg, uint64_t spr) { if (reg > 31) PR_ERROR("Invalid register specified for mfspr\n"); @@ -34,7 +34,7 @@ static uint64_t mfspr(uint64_t reg, uint64_t spr) return MFSPR_OPCODE | (reg << 21) | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6); } -static uint64_t mtspr(uint64_t spr, uint64_t reg) +uint64_t mtspr(uint64_t spr, uint64_t reg) { if (reg > 31) PR_ERROR("Invalid register specified for mtspr\n"); @@ -148,7 +148,7 @@ int ram_sreset_thread(struct pdbg_target *thread_target) * data. Note that only register r0 is saved and restored so opcodes * must not touch other registers. */ -static int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes, +int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes, uint64_t *results, int len, unsigned int lpar) { uint64_t opcode = 0, r0 = 0, r1 = 0, scratch = 0; @@ -168,6 +168,7 @@ static int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes /* RAM instructions */ for (i = -2; i < len + 2; i++) { if (i == -2) + /* Save r1 (assumes opcodes don't touch other registers) */ opcode = mtspr(277, 1); else if (i == -1) /* Save r0 (assumes opcodes don't touch other registers) */ @@ -309,6 +310,31 @@ int ram_getmem(struct pdbg_target *thread, uint64_t addr, uint64_t *value) return 0; } +int ram_getxer(struct pdbg_target *thread_target, uint64_t *value) +{ + + struct thread *thread; + + assert(!strcmp(thread_target->class, "thread")); + thread = target_to_thread(thread_target); + + CHECK_ERR(thread->ram_getxer(thread_target, value)); + + return 0; +} + +int ram_putxer(struct pdbg_target *thread_target, uint64_t value) +{ + struct thread *thread; + + assert(!strcmp(thread_target->class, "thread")); + thread = target_to_thread(thread_target); + + CHECK_ERR(thread->ram_putxer(thread_target, value)); + + return 0; +} + /* * Read the given ring from the given chiplet. Result must be large enough to hold ring_len bits. */ @@ -368,12 +394,8 @@ int ram_state_thread(struct pdbg_target *thread, struct thread_regs *regs) } printf("CR : 0x%08" PRIx32 "\n", regs->cr); -#if 0 - /* TODO: Disabling because reading SPR 0x1 reliably checkstops a P8 */ - ram_getspr(thread, 0x1, &value); - regs->xer = value; - printf("XER : 0x%08" PRIx32 "\n", regs->xer); -#endif + ram_getxer(thread, ®s->xer); + printf("XER : 0x%08" PRIx64 "\n", regs->xer); printf("GPRS :\n"); for (i = 0; i < 32; i++) { diff --git a/libpdbg/chip.h b/libpdbg/chip.h new file mode 100644 index 0000000..52f3486 --- /dev/null +++ b/libpdbg/chip.h @@ -0,0 +1,24 @@ +/* Copyright 2018 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. + */ +#ifndef __LIBPDBG_CHIP_H +#define __LIBPDBG_CHIP_H + +uint64_t mfspr(uint64_t reg, uint64_t spr) __attribute__ ((visibility("hidden"))); +uint64_t mtspr(uint64_t spr, uint64_t reg) __attribute__ ((visibility("hidden"))); +int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes, + uint64_t *results, int len, unsigned int lpar) __attribute__ + ((visibility("hidden"))); +#endif diff --git a/libpdbg/libpdbg.h b/libpdbg/libpdbg.h index e626786..2e55060 100644 --- a/libpdbg/libpdbg.h +++ b/libpdbg/libpdbg.h @@ -108,7 +108,7 @@ struct thread_regs { uint64_t ctr; uint64_t tar; uint32_t cr; - uint32_t xer; + uint64_t xer; uint64_t gprs[32]; uint64_t lpcr; @@ -151,6 +151,8 @@ int ram_stop_thread(struct pdbg_target *target); int ram_sreset_thread(struct pdbg_target *target); int ram_state_thread(struct pdbg_target *target, struct thread_regs *regs); struct thread_state thread_status(struct pdbg_target *target); +int ram_getxer(struct pdbg_target *thread, uint64_t *value); +int ram_putxer(struct pdbg_target *thread, uint64_t value); int getring(struct pdbg_target *chiplet_target, uint64_t ring_addr, uint64_t ring_len, uint32_t result[]); enum pdbg_sleep_state {PDBG_THREAD_STATE_RUN, PDBG_THREAD_STATE_DOZE, diff --git a/libpdbg/operations.h b/libpdbg/operations.h index 52bfe7e..4735c55 100644 --- a/libpdbg/operations.h +++ b/libpdbg/operations.h @@ -67,9 +67,10 @@ #define MFOCRF_OPCODE 0x7c100026UL #define MFSPR_MASK (MFSPR_OPCODE | ((0x1f) << 16) | ((0x3e0) << 6)) #define MFXER_OPCODE (MFSPR_OPCODE | ((1 & 0x1f) << 16) | ((1 & 0x3e0) << 6)) +#define MTXER_OPCODE (MTSPR_OPCODE | ((1 & 0x1f) << 16) | ((1 & 0x3e0) << 6)) #define LD_OPCODE 0xe8000000UL -#define MFSPR_SPR(opcode) (((opcode >> 16) & 0x1f) | ((opcode >> 6) & 0x3e0)) +#define MXSPR_SPR(opcode) (((opcode >> 16) & 0x1f) | ((opcode >> 6) & 0x3e0)) /* GDB server functionality */ int gdbserver_start(uint16_t port); diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c index cb5a46b..89ecfd6 100644 --- a/libpdbg/p8chip.c +++ b/libpdbg/p8chip.c @@ -83,9 +83,61 @@ #define EX_PM_GP0_REG 0xf0100 #define SPECIAL_WKUP_DONE PPC_BIT(31) +/* p8 specific opcodes for instruction ramming*/ +#define MTXERF0_OPCODE 0x00000008UL +#define MTXERF1_OPCODE 0x00000108UL +#define MTXERF2_OPCODE 0x00000208UL +#define MTXERF3_OPCODE 0x00000308UL +#define MFXERF0_OPCODE 0x00000010UL +#define MFXERF1_OPCODE 0x00000110UL +#define MFXERF2_OPCODE 0x00000210UL +#define MFXERF3_OPCODE 0x00000310UL + /* How long (in us) to wait for a special wakeup to complete */ #define SPECIAL_WKUP_TIMEOUT 10 +#include "chip.h" + +static uint64_t mfxerf(uint64_t reg, uint64_t field) +{ + if (reg > 31) + PR_ERROR("Invalid register specified for mfxerf\n"); + + switch (field) { + case 0: + return MFXERF0_OPCODE | (reg << 21); + case 1: + return MFXERF1_OPCODE | (reg << 21); + case 2: + return MFXERF2_OPCODE | (reg << 21); + case 3: + return MFXERF3_OPCODE | (reg << 21); + default: + PR_ERROR("Invalid XER field specified\n"); + } + return 0; +} + +static uint64_t mtxerf(uint64_t reg, uint64_t field) +{ + if (reg > 31) + PR_ERROR("Invalid register specified for mtxerf\n"); + + switch (field) { + case 0: + return MTXERF0_OPCODE | (reg << 21); + case 1: + return MTXERF1_OPCODE | (reg << 21); + case 2: + return MTXERF2_OPCODE | (reg << 21); + case 3: + return MTXERF3_OPCODE | (reg << 21); + default: + PR_ERROR("Invalid XER field specified\n"); + } + return 0; +} + static int assert_special_wakeup(struct core *chip) { int i = 0; @@ -386,6 +438,38 @@ static int p8_ram_destroy(struct thread *thread) 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), + mtspr(277, 0), mfxerf(0, 2), mtspr(277, 0), + mfxerf(0, 3), mtspr(277, 0)}; + uint64_t results[] = {0, 0, 0, 0, 0, 0, 0, 0}; + + /* On POWER8 we can't get xer with getspr. We seem to only be able to + * get and set IBM bits 32-34 and 44-56. + */ + PR_WARNING("Can only get/set IBM bits 32-34 and 44-56 of the XER register\n"); + + + CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0)); + + *value = results[1] | results[3] | results[5] | results[7]; + return 0; +} + +static int p8_ram_putxer(struct pdbg_target *thread, uint64_t value) +{ + uint64_t fields[] = {value, value, value, value, 0}; + uint64_t opcodes[] = {mfspr(0, 277), mtxerf(0, 0), mtxerf(0, 1), mtxerf(0, 2), mtxerf(0, 3)}; + + /* We seem to only be able to get and set IBM bits 32-34 and 44-56.*/ + PR_WARNING("Can only set IBM bits 32-34 and 44-56 of the XER register\n"); + + CHECK_ERR(ram_instructions(thread, opcodes, fields, ARRAY_SIZE(opcodes), 0)); + + return 0; +} + /* * Initialise all viable threads for ramming on the given core. */ @@ -413,6 +497,8 @@ 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, }; DECLARE_HW_UNIT(p8_thread); diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c index 189d80a..f126968 100644 --- a/libpdbg/p9chip.c +++ b/libpdbg/p9chip.c @@ -292,7 +292,6 @@ static int __p9_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t switch(opcode & OPCODE_MASK) { case MTNIA_OPCODE: predecode = 8; - /* Not currently supported as we can only MTNIA from LR */ PR_ERROR("MTNIA is not currently supported\n"); break; @@ -307,7 +306,18 @@ static int __p9_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t break; case MFSPR_OPCODE: - switch(MFSPR_SPR(opcode)) { + switch(MXSPR_SPR(opcode)) { + case 1: /* XER */ + predecode = 4; + break; + default: + predecode = 0; + break; + } + break; + + case MTSPR_OPCODE: + switch(MXSPR_SPR(opcode)) { case 1: /* XER */ predecode = 4; break; @@ -395,6 +405,21 @@ static int p9_ram_destroy(struct thread *thread) return 0; } +static int p9_ram_getxer(struct pdbg_target *thread, uint64_t *value) +{ + CHECK_ERR(ram_getspr(thread, 1, value)); + + return 0; +} + +static int p9_ram_putxer(struct pdbg_target *thread, uint64_t value) +{ + CHECK_ERR(ram_putspr(thread, 1, value)); + + return 0; + +} + static struct thread p9_thread = { .target = { .name = "POWER9 Thread", @@ -410,6 +435,8 @@ 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, }; DECLARE_HW_UNIT(p9_thread); diff --git a/libpdbg/target.h b/libpdbg/target.h index 9f055ac..8bad405 100644 --- a/libpdbg/target.h +++ b/libpdbg/target.h @@ -153,6 +153,8 @@ 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 pdbg_target *, uint64_t *value); + int (*ram_putxer)(struct pdbg_target *, uint64_t value); }; #define target_to_thread(x) container_of(x, struct thread, target)