From patchwork Wed Jun 20 05:34:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Popple X-Patchwork-Id: 931962 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.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 419YSJ2JMjz9s4n for ; Wed, 20 Jun 2018 15:34:56 +1000 (AEST) 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 419YSJ0VzYzF10W for ; Wed, 20 Jun 2018 15:34:56 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=popple.id.au 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.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 419YRc3wP4zF0x7 for ; Wed, 20 Jun 2018 15:34:20 +1000 (AEST) 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 ozlabs.org (Postfix) with ESMTPSA id 419YRc1qrSz9s4n; Wed, 20 Jun 2018 15:34:20 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=popple.id.au From: Alistair Popple To: pdbg@lists.ozlabs.org Date: Wed, 20 Jun 2018 15:34:09 +1000 Message-Id: <20180620053409.14538-9-alistair@popple.id.au> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180620053409.14538-1-alistair@popple.id.au> References: <20180620053409.14538-1-alistair@popple.id.au> Subject: [Pdbg] [PATCH 8/8] pdbg: Use new command parsing X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "mailing list for https://github.com/open-power/pdbg development" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" This switches all commands except the htm command to use the new command/option parsing code. For the moment we leave the usage help and generic targeting flag processing alone, but future changes should allow this to also use the common parsing code. Signed-off-by: Alistair Popple Signed-off-by: Alistair Popple <alistair@popple.id.au>
--- Makefile.am | 1 + src/cfam.c | 55 ++++++-------------- src/cfam.h | 18 ------- src/main.c | 125 ++++++++++++++++++++++++++++----------------- src/mem.c | 124 ++++++++------------------------------------ src/mem.h | 20 -------- src/reg.c | 164 +++++++++++++++-------------------------------------------- src/reg.h | 20 -------- src/ring.c | 32 ++---------- src/ring.h | 17 ------- src/scom.c | 54 +++++--------------- src/scom.h | 18 ------- src/thread.c | 87 ++++++++++++++++++++++--------- src/thread.h | 23 --------- 14 files changed, 237 insertions(+), 521 deletions(-) delete mode 100644 src/cfam.h delete mode 100644 src/mem.h delete mode 100644 src/reg.h delete mode 100644 src/ring.h delete mode 100644 src/scom.h delete mode 100644 src/thread.h diff --git a/Makefile.am b/Makefile.am index 23f2080..4e0dce2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ pdbg_SOURCES = \ src/ring.c \ src/htm.c \ src/progress.c \ + src/parsers.c \ src/optcmd.c \ src/options_@ARCH@.c diff --git a/src/cfam.c b/src/cfam.c index 269123e..6dab388 100644 --- a/src/cfam.c +++ b/src/cfam.c @@ -20,8 +20,9 @@ #include #include "main.h" +#include "optcmd.h" -static int getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused) +static int _getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused) { uint32_t value; @@ -33,7 +34,15 @@ static int getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, u return 1; } -static int putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data) +static int getcfam(uint32_t addr) +{ + uint64_t addr64 = addr; + + return for_each_target("fsi", _getcfam, &addr64, NULL); +} +OPTCMD_DEFINE_CMD_WITH_ARGS(getcfam, getcfam, (ADDRESS32)); + +static int _putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data) { if (fsi_write(target, *addr, *data)) return 0; @@ -41,44 +50,10 @@ static int putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, u return 1; } -int handle_cfams(int optind, int argc, char *argv[]) +static int putcfam(uint32_t addr, uint32_t data) { - uint64_t addr; - char *endptr; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires an address\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - addr = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse address '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } + uint64_t addr64 = addr, data64 = data; - if (strcmp(argv[optind], "putcfam") == 0) { - uint64_t data; - - if (optind + 2 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - data = strtoull(argv[optind + 2], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - return for_each_target("fsi", putcfam, &addr, &data); - } - - return for_each_target("fsi", getcfam, &addr, NULL); + return for_each_target("fsi", _putcfam, &addr64, &data64); } - - +OPTCMD_DEFINE_CMD_WITH_ARGS(putcfam, putcfam, (ADDRESS32, DATA32)); diff --git a/src/cfam.h b/src/cfam.h deleted file mode 100644 index 997ed3d..0000000 --- a/src/cfam.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2017 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 - -int handle_cfams(int optind, int argc, char *argv[]); diff --git a/src/main.c b/src/main.c index cf9a3b2..1cfaca7 100644 --- a/src/main.c +++ b/src/main.c @@ -34,14 +34,9 @@ #include #include "main.h" -#include "cfam.h" -#include "scom.h" -#include "reg.h" -#include "ring.h" -#include "mem.h" -#include "thread.h" #include "htm.h" #include "options.h" +#include "optcmd.h" #define PR_ERROR(x, args...) \ pdbg_log(PDBG_ERROR, x, ##args) @@ -77,44 +72,64 @@ static int **processorsel[MAX_PROCESSORS]; static int *chipsel[MAX_PROCESSORS][MAX_CHIPS]; static int threadsel[MAX_PROCESSORS][MAX_CHIPS][MAX_THREADS]; -static int handle_probe(int optind, int argc, char *argv[]); -static int handle_release(int optind, int argc, char *argv[]); +static int probe(void); +static int release(void); + +/* TODO: We are repeating ourselves here. A little bit more macro magic could + * easily fix this but I was hesitant to introduce too much magic all at + * once. */ +extern struct optcmd_cmd + optcmd_getscom, optcmd_putscom, optcmd_getcfam, optcmd_putcfam, + optcmd_getgpr, optcmd_putgpr, optcmd_getspr, optcmd_putspr, + optcmd_getnia, optcmd_putnia, optcmd_getmsr, optcmd_putmsr, + optcmd_getring, optcmd_start, optcmd_stop, optcmd_step, + optcmd_threadstatus, optcmd_sreset, optcmd_regs, optcmd_probe, + optcmd_getmem, optcmd_putmem; + +static struct optcmd_cmd *cmds[] = { + &optcmd_getscom, &optcmd_putscom, &optcmd_getcfam, &optcmd_putcfam, + &optcmd_getgpr, &optcmd_putgpr, &optcmd_getspr, &optcmd_putspr, + &optcmd_getnia, &optcmd_putnia, &optcmd_getmsr, &optcmd_putmsr, + &optcmd_getring, &optcmd_start, &optcmd_stop, &optcmd_step, + &optcmd_threadstatus, &optcmd_sreset, &optcmd_regs, &optcmd_probe, + &optcmd_getmem, &optcmd_putmem, +}; +/* Purely for printing usage text. We could integrate printing argument and flag + * help into optcmd if desired. */ struct action { const char *name; const char *args; const char *desc; - int (*fn)(int, int, char **); }; static struct action actions[] = { - { "getgpr", "", "Read General Purpose Register (GPR)", &handle_gpr }, - { "putgpr", " ", "Write General Purpose Register (GPR)", &handle_gpr }, - { "getnia", "", "Get Next Instruction Address (NIA)", &handle_nia }, - { "putnia", "", "Write Next Instrution Address (NIA)", &handle_nia }, - { "getspr", "", "Get Special Purpose Register (SPR)", &handle_spr }, - { "putspr", " ", "Write Special Purpose Register (SPR)", &handle_spr }, - { "getmsr", "", "Get Machine State Register (MSR)", &handle_msr }, - { "putmsr", "", "Write Machine State Register (MSR)", &handle_msr }, - { "getring", " ", "Read a ring. Length must be correct", &handle_getring }, - { "start", "", "Start thread", &thread_start }, - { "step", "", "Set a thread instructions", &thread_step }, - { "stop", "", "Stop thread", &thread_stop }, - { "htm", "core|nest start|stop|status|reset|dump|trace|analyse", "Hardware Trace Macro", &run_htm }, - { "release", "", "Should be called after pdbg work is finished, to release special wakeups and other resources.", &handle_release}, - { "probe", "", "", &handle_probe }, - { "getcfam", "
", "Read system cfam", &handle_cfams }, - { "putcfam", "
[]", "Write system cfam", &handle_cfams }, - { "getscom", "
", "Read system scom", &handle_scoms }, - { "putscom", "
[]", "Write system scom", &handle_scoms }, - { "getmem", "
", "Read system memory", &handle_mem }, - { "putmem", "
", "Write to system memory", &handle_mem }, - { "threadstatus", "", "Print the status of a thread", &thread_status_print }, - { "sreset", "", "Reset", &thread_sreset }, - { "regs", "", "State", &thread_state }, + { "getgpr", "", "Read General Purpose Register (GPR)" }, + { "putgpr", " ", "Write General Purpose Register (GPR)" }, + { "getnia", "", "Get Next Instruction Address (NIA)" }, + { "putnia", "", "Write Next Instrution Address (NIA)" }, + { "getspr", "", "Get Special Purpose Register (SPR)" }, + { "putspr", " ", "Write Special Purpose Register (SPR)" }, + { "getmsr", "", "Get Machine State Register (MSR)" }, + { "putmsr", "", "Write Machine State Register (MSR)" }, + { "getring", " ", "Read a ring. Length must be correct" }, + { "start", "", "Start thread" }, + { "step", "", "Set a thread instructions" }, + { "stop", "", "Stop thread" }, + { "htm", "core|nest start|stop|status|reset|dump|trace|analyse", "Hardware Trace Macro" }, + { "release", "", "Should be called after pdbg work is finished" }, + { "probe", "", "" }, + { "getcfam", "
", "Read system cfam" }, + { "putcfam", "
[]", "Write system cfam" }, + { "getscom", "
", "Read system scom" }, + { "putscom", "
[]", "Write system scom" }, + { "getmem", "
", "Read system memory" }, + { "putmem", "
", "Write to system memory" }, + { "threadstatus", "", "Print the status of a thread" }, + { "sreset", "", "Reset" }, + { "regs", "", "State" }, }; - static void print_usage(char *pname) { int i; @@ -600,7 +615,7 @@ static void release_target(struct pdbg_target *target) pdbg_target_release(target); } -static void do_release(void) +static int release(void) { struct pdbg_target_class *target_class; @@ -610,7 +625,10 @@ static void do_release(void) pdbg_for_each_class_target(target_class->name, target) release_target(target); } + + return 0; } +OPTCMD_DEFINE_CMD(release, release); void print_target(struct pdbg_target *target, int level) { @@ -652,7 +670,7 @@ void print_target(struct pdbg_target *target, int level) } } -static int handle_probe(int optind, int argc, char *argv[]) +static int probe(void) { struct pdbg_target *target; @@ -664,25 +682,21 @@ static int handle_probe(int optind, int argc, char *argv[]) return 1; } +OPTCMD_DEFINE_CMD(probe, probe); /* * Release handler. */ static void atexit_release(void) { - do_release(); -} - -static int handle_release(int optind, int argc, char *argv[]) -{ - do_release(); - - return 1; + release(); } int main(int argc, char *argv[]) { int i, rc = 0; + void **args, **flags; + optcmd_cmd_t *cmd; backend = default_backend(); device_node = default_target(backend); @@ -714,13 +728,28 @@ int main(int argc, char *argv[]) atexit(atexit_release); - for (i = 0; i < ARRAY_SIZE(actions); i++) { - if (strcmp(argv[optind], actions[i].name) == 0) { - rc = actions[i].fn(optind, argc, argv); - goto found_action; + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + if (!strcmp(argv[optind], cmds[i]->cmd)) { + /* Found our command */ + cmd = optcmd_parse(cmds[i], (const char **) &argv[optind + 1], + argc - (optind + 1), &args, &flags); + if (cmd) { + rc = cmd(args, flags); + goto found_action; + } else { + /* Error parsing arguments so exit return directly */ + return 1; + } } } + /* Process subcommands. Currently only 'htm'. + * TODO: Move htm command parsing to optcmd once htm clean-up is complete */ + if (!strcmp(argv[optind], "htm")) { + run_htm(optind, argc, argv); + goto found_action; + } + PR_ERROR("Unsupported command: %s\n", argv[optind]); return 1; diff --git a/src/mem.c b/src/mem.c index e0327d1..29fd21e 100644 --- a/src/mem.c +++ b/src/mem.c @@ -20,21 +20,34 @@ #include #include #include +#include #include #include "main.h" #include "progress.h" +#include "optcmd.h" +#include "parsers.h" #define PR_ERROR(x, args...) \ pdbg_log(PDBG_ERROR, x, ##args) #define PUTMEM_BUF_SIZE 1024 -static int getmem(uint64_t addr, uint64_t size, bool ci) + +struct mem_flags { + bool ci; +}; + +#define MEM_CI_FLAG ("--ci", ci, parse_flag_noarg, false) + +static int getmem(uint64_t addr, uint64_t size, struct mem_flags flags) { struct pdbg_target *target; uint8_t *buf; int rc = 0; + + printf("getmem ci %d\n", flags.ci); + buf = malloc(size); assert(buf); pdbg_for_each_class_target("adu", target) { @@ -43,7 +56,7 @@ static int getmem(uint64_t addr, uint64_t size, bool ci) pdbg_set_progress_tick(progress_tick); progress_init(); - if (!__adu_getmem(target, addr, buf, size, ci)) { + if (!__adu_getmem(target, addr, buf, size, flags.ci)) { if (write(STDOUT_FILENO, buf, size) < 0) PR_ERROR("Unable to write stdout.\n"); else @@ -58,7 +71,10 @@ static int getmem(uint64_t addr, uint64_t size, bool ci) return rc; } -static int putmem(uint64_t addr, bool ci) +OPTCMD_DEFINE_CMD_WITH_FLAGS(getmem, getmem, (ADDRESS, DATA), + mem_flags, (MEM_CI_FLAG)); + +static int putmem(uint64_t addr, struct mem_flags flags) { uint8_t *buf; int read_size, rc = 0; @@ -76,7 +92,7 @@ static int putmem(uint64_t addr, bool ci) progress_init(); do { read_size = read(STDIN_FILENO, buf, PUTMEM_BUF_SIZE); - if (__adu_putmem(adu_target, addr, buf, read_size, ci)) { + if (__adu_putmem(adu_target, addr, buf, read_size, flags.ci)) { rc = 0; printf("Unable to write memory.\n"); break; @@ -89,101 +105,5 @@ static int putmem(uint64_t addr, bool ci) free(buf); return rc; } - -static bool is_real_address(struct thread_regs *regs, uint64_t addr) -{ - return true; - if ((addr & 0xf000000000000000ULL) == 0xc000000000000000ULL) - return true; - return false; -} - -static int load8(struct pdbg_target *target, uint64_t addr, uint64_t *value) -{ - if (adu_getmem(target, addr, (uint8_t *)value, 8)) { - PR_ERROR("Unable to read memory address=%016" PRIx64 ".\n", addr); - return 0; - } - - return 1; -} - -int dump_stack(struct thread_regs *regs) -{ - struct pdbg_target *target; - uint64_t sp = regs->gprs[1]; - uint64_t pc; - - pdbg_for_each_class_target("adu", target) { - if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED) - continue; - break; - } - - printf("STACK:\n"); - if (!target) - PR_ERROR("Unable to read memory (no ADU found)\n"); - - if (sp && is_real_address(regs, sp)) { - if (!load8(target, sp, &sp)) - return 1; - while (sp && is_real_address(regs, sp)) { - if (!load8(target, sp + 16, &pc)) - return 1; - - printf(" 0x%016" PRIx64 " 0x%16" PRIx64 "\n", sp, pc); - - if (!load8(target, sp, &sp)) - return 1; - } - } - - return 0; -} - -int handle_mem(int optind, int argc, char *argv[]) -{ - uint64_t addr; - char *endptr; - bool ci = false; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires an address\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - - if (strcmp(argv[optind +1], "-ci") == 0) { - /* Set cache-inhibited flag */ - ci = true; - } - - addr = strtoull(argv[optind + 1 + ci], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse address '%s'\n", - argv[0], argv[optind], argv[optind + 1 + ci]); - return -1; - } - - if (strcmp(argv[optind], "getmem") == 0) { - uint64_t size; - - if (optind + 2 + ci >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - size = strtoull(argv[optind + 2 + ci], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1 + ci]); - return -1; - } - - return getmem(addr, size, ci); - } - - return putmem(addr, ci); -} +OPTCMD_DEFINE_CMD_WITH_FLAGS(putmem, putmem, (ADDRESS), + mem_flags, (MEM_CI_FLAG)); diff --git a/src/mem.h b/src/mem.h deleted file mode 100644 index 42bdc04..0000000 --- a/src/mem.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2017 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 - -int dump_stack(struct thread_regs *regs); -int handle_mem(int optind, int argc, char *argv[]); diff --git a/src/reg.c b/src/reg.c index 21bec13..aa77a8a 100644 --- a/src/reg.c +++ b/src/reg.c @@ -22,6 +22,7 @@ #include #include "main.h" +#include "optcmd.h" #define REG_MEM -3 #define REG_MSR -2 @@ -91,143 +92,58 @@ static int getprocreg(struct pdbg_target *target, uint32_t index, uint64_t *reg, return !rc; } -int handle_gpr(int optind, int argc, char *argv[]) +static int getgpr(int gpr) { - char *endptr; - uint64_t gpr; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires a GPR\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - gpr = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse GPR '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - if (gpr > 31) { - printf("A GPR must be between zero and 31 inclusive\n"); - return -1; - } - - if (strcmp(argv[optind], "putgpr") == 0) { - uint64_t data; - - if (optind + 2 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - data = strtoull(argv[optind + 2], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - return for_each_target("thread", putprocreg, &gpr, &data); - } - - return for_each_target("thread", getprocreg, &gpr, NULL); + uint64_t reg = gpr; + return for_each_target("thread", getprocreg, ®, NULL); } +OPTCMD_DEFINE_CMD_WITH_ARGS(getgpr, getgpr, (GPR)); -int handle_nia(int optind, int argc, char *argv[]) +static int putgpr(int gpr, uint64_t data) { - uint64_t reg = REG_NIA; - char *endptr; - - if (strcmp(argv[optind], "putnia") == 0) { - uint64_t data; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - data = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - return for_each_target("thread", putprocreg, ®, &data); - } + uint64_t reg = gpr; + return for_each_target("thread", putprocreg, ®, &data); +} +OPTCMD_DEFINE_CMD_WITH_ARGS(putgpr, putgpr, (GPR, DATA)); +static int getnia(void) +{ + uint64_t reg = REG_NIA; return for_each_target("thread", getprocreg, ®, NULL); } +OPTCMD_DEFINE_CMD(getnia, getnia); -int handle_spr(int optind, int argc, char *argv[]) +static int putnia(uint64_t nia) { - char *endptr; - uint64_t spr; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires a GPR\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - spr = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse GPR '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - spr += REG_R31; - - if (strcmp(argv[optind], "putspr") == 0) { - uint64_t data; - - if (optind + 2 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - data = strtoull(argv[optind + 2], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - return for_each_target("thread", putprocreg, &spr, &data); - } - - return for_each_target("thread", getprocreg, &spr, NULL); + uint64_t reg = REG_NIA; + return for_each_target("thread", getprocreg, ®, &nia); } +OPTCMD_DEFINE_CMD_WITH_ARGS(putnia, putnia, (DATA)); -int handle_msr(int optind, int argc, char *argv[]) +static int getspr(int spr) { - uint64_t msr = REG_MSR; - char *endptr; - - if (strcmp(argv[optind], "putmsr") == 0) { - uint64_t data; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } + uint64_t reg = spr + REG_R31; + return for_each_target("thread", getprocreg, ®, NULL); +} +OPTCMD_DEFINE_CMD_WITH_ARGS(getspr, getspr, (SPR)); - errno = 0; - data = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } +static int putspr(int spr, uint64_t data) +{ + uint64_t reg = spr + REG_R31; + return for_each_target("thread", putprocreg, ®, &data); +} +OPTCMD_DEFINE_CMD_WITH_ARGS(putspr, putspr, (SPR, DATA)); - return for_each_target("thread", putprocreg, &msr, &data); - } +static int getmsr(void) +{ + uint64_t reg = REG_MSR; + return for_each_target("thread", getprocreg, ®, NULL); +} +OPTCMD_DEFINE_CMD(getmsr, getmsr); - return for_each_target("thread", getprocreg, &msr, NULL); +static int putmsr(uint64_t data) +{ + uint64_t reg = REG_MSR; + return for_each_target("thread", putprocreg, ®, &data); } +OPTCMD_DEFINE_CMD_WITH_ARGS(putmsr, putmsr, (DATA)); diff --git a/src/reg.h b/src/reg.h deleted file mode 100644 index ad41d9d..0000000 --- a/src/reg.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2017 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. - */ - -int handle_gpr(int optind, int argc, char *argv[]); -int handle_nia(int optind, int argc, char *argv[]); -int handle_spr(int optind, int argc, char *argv[]); -int handle_msr(int optind, int argc, char *argv[]); diff --git a/src/ring.c b/src/ring.c index b0c9376..58df4d1 100644 --- a/src/ring.c +++ b/src/ring.c @@ -18,11 +18,12 @@ #include #include #include +#include -#include -#include +#include #include "main.h" +#include "optcmd.h" static int pdbg_getring(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *len) { @@ -51,31 +52,8 @@ static int pdbg_getring(struct pdbg_target *target, uint32_t index, uint64_t *ad return 1; } -int handle_getring(int optind, int argc, char *argv[]) +static int _getring(uint64_t ring_addr, uint64_t ring_len) { - uint64_t ring_addr, ring_len; - char *endptr; - - if (optind + 2 >= argc) { - printf("%s: command '%s' requires two arguments (address and length)\n", - argv[0], argv[optind]); - return -1; - } - - errno = 0; - ring_addr = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse ring address '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - ring_len = strtoull(argv[optind + 2], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse ring length '%s'\n", - argv[0], argv[optind], argv[optind + 2]); - return -1; - } - return for_each_target("chiplet", pdbg_getring, &ring_addr, &ring_len); } +OPTCMD_DEFINE_CMD_WITH_ARGS(getring, _getring, (ADDRESS, DATA)); diff --git a/src/ring.h b/src/ring.h deleted file mode 100644 index a72c875..0000000 --- a/src/ring.h +++ /dev/null @@ -1,17 +0,0 @@ -/* 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. - */ - -int handle_getring(int optind, int argc, char *argv[]); diff --git a/src/scom.c b/src/scom.c index 4c59e2a..2372e91 100644 --- a/src/scom.c +++ b/src/scom.c @@ -22,8 +22,9 @@ #include #include "main.h" +#include "optcmd.h" -static int getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused) +static int _getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused) { uint64_t value; @@ -35,7 +36,13 @@ static int getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, u return 1; } -static int putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data) + int getscom(uint64_t addr) +{ + return for_each_target("pib", _getscom, &addr, NULL); +} +OPTCMD_DEFINE_CMD_WITH_ARGS(getscom, getscom, (ADDRESS)); + +static int _putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data) { if (pib_write(target, *addr, *data)) return 0; @@ -43,44 +50,9 @@ static int putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, u return 1; } - -int handle_scoms(int optind, int argc, char *argv[]) + int putscom(uint64_t addr, uint64_t data, uint64_t mask) { - uint64_t addr; - char *endptr; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires an address\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - addr = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse address '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - if (strcmp(argv[optind], "putscom") == 0) { - uint64_t data; - - if (optind + 2 >= argc) { - printf("%s: command '%s' requires data\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - data = strtoull(argv[optind + 2], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse data '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - - return for_each_target("pib", putscom, &addr, &data); - } - - return for_each_target("pib", getscom, &addr, NULL); + /* TODO: Restore the functionality */ + return for_each_target("pib", _putscom, &addr, &data); } - +OPTCMD_DEFINE_CMD_WITH_ARGS(putscom, putscom, (ADDRESS, DATA, DEFAULT_DATA("0xffffffffffffffff"))); diff --git a/src/scom.h b/src/scom.h deleted file mode 100644 index d4325b5..0000000 --- a/src/scom.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2017 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 - -int handle_scoms(int optind, int argc, char *argv[]); diff --git a/src/thread.c b/src/thread.c index e8b54cb..4b95636 100644 --- a/src/thread.c +++ b/src/thread.c @@ -21,7 +21,7 @@ #include #include "main.h" -#include "mem.h" +#include "optcmd.h" static int print_thread_status(struct pdbg_target *target, uint32_t index, uint64_t *arg, uint64_t *unused1) { @@ -81,6 +81,57 @@ static int print_core_thread_status(struct pdbg_target *core_target, uint32_t in return rc; } +static bool is_real_address(struct thread_regs *regs, uint64_t addr) +{ + return true; + if ((addr & 0xf000000000000000ULL) == 0xc000000000000000ULL) + return true; + return false; +} + +static int load8(struct pdbg_target *target, uint64_t addr, uint64_t *value) +{ + if (adu_getmem(target, addr, (uint8_t *)value, 8)) { + pdbg_log(PDBG_ERROR, "Unable to read memory address=%016" PRIx64 ".\n", addr); + return 0; + } + + return 1; +} + +static int dump_stack(struct thread_regs *regs) +{ + struct pdbg_target *target; + uint64_t sp = regs->gprs[1]; + uint64_t pc; + + pdbg_for_each_class_target("adu", target) { + if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED) + continue; + break; + } + + printf("STACK:\n"); + if (!target) + pdbg_log(PDBG_ERROR, "Unable to read memory (no ADU found)\n"); + + if (sp && is_real_address(regs, sp)) { + if (!load8(target, sp, &sp)) + return 1; + while (sp && is_real_address(regs, sp)) { + if (!load8(target, sp + 16, &pc)) + return 1; + + printf(" 0x%016" PRIx64 " 0x%16" PRIx64 "\n", sp, pc); + + if (!load8(target, sp, &sp)) + return 1; + } + } + + return 0; +} + static int get_thread_max_index(struct pdbg_target *target, uint32_t index, uint64_t *maxindex, uint64_t *unused) { if (index > *maxindex) @@ -140,48 +191,37 @@ static int state_thread(struct pdbg_target *thread_target, uint32_t index, uint6 return 1; } -int thread_start(int optind, int argc, char *argv[]) +static int thread_start(void) { return for_each_target("thread", start_thread, NULL, NULL); } +OPTCMD_DEFINE_CMD(start, thread_start); -int thread_step(int optind, int argc, char *argv[]) +static int thread_step(uint64_t count) { - uint64_t count; - char *endptr; - - if (optind + 1 >= argc) { - printf("%s: command '%s' requires a count\n", argv[0], argv[optind]); - return -1; - } - - errno = 0; - count = strtoull(argv[optind + 1], &endptr, 0); - if (errno || *endptr != '\0') { - printf("%s: command '%s' couldn't parse count '%s'\n", - argv[0], argv[optind], argv[optind + 1]); - return -1; - } - return for_each_target("thread", step_thread, &count, NULL); } +OPTCMD_DEFINE_CMD_WITH_ARGS(step, thread_step, (DATA)); -int thread_stop(int optind, int argc, char *argv[]) +static int thread_stop(void) { return for_each_target("thread", stop_thread, NULL, NULL); } +OPTCMD_DEFINE_CMD(stop, thread_stop); -int thread_status_print(int optind, int argc, char *argv[]) +static int thread_status_print(void) { return for_each_target("pib", print_proc_thread_status, NULL, NULL); } +OPTCMD_DEFINE_CMD(threadstatus, thread_status_print); -int thread_sreset(int optind, int argc, char *argv[]) +static int thread_sreset(void) { return for_each_target("thread", sreset_thread, NULL, NULL); } +OPTCMD_DEFINE_CMD(sreset, thread_sreset); -int thread_state(int optind, int argc, char *argv[]) +static int thread_state(void) { int err; @@ -191,3 +231,4 @@ int thread_state(int optind, int argc, char *argv[]) return err; } +OPTCMD_DEFINE_CMD(regs, thread_state); diff --git a/src/thread.h b/src/thread.h deleted file mode 100644 index 0c1caa2..0000000 --- a/src/thread.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2017 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 - -int thread_start(int optind, int argc, char *argv[]); -int thread_step(int optind, int argc, char *argv[]); -int thread_stop(int optind, int argc, char *argv[]); -int thread_status_print(int optind, int argc, char *argv[]); -int thread_sreset(int optind, int argc, char *argv[]); -int thread_state(int optind, int argc, char *argv[]);