diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cfam.c | 55 | ||||
-rw-r--r-- | src/cfam.h | 18 | ||||
-rw-r--r-- | src/main.c | 125 | ||||
-rw-r--r-- | src/mem.c | 122 | ||||
-rw-r--r-- | src/mem.h | 20 | ||||
-rw-r--r-- | src/reg.c | 164 | ||||
-rw-r--r-- | src/reg.h | 20 | ||||
-rw-r--r-- | src/ring.c | 32 | ||||
-rw-r--r-- | src/ring.h | 17 | ||||
-rw-r--r-- | src/scom.c | 54 | ||||
-rw-r--r-- | src/scom.h | 18 | ||||
-rw-r--r-- | src/thread.c | 87 | ||||
-rw-r--r-- | src/thread.h | 23 |
13 files changed, 234 insertions, 521 deletions
@@ -20,8 +20,9 @@ #include <inttypes.h> #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 <inttypes.h> - -int handle_cfams(int optind, int argc, char *argv[]); @@ -34,14 +34,9 @@ #include <target.h> #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", "<gpr>", "Read General Purpose Register (GPR)", &handle_gpr }, - { "putgpr", "<gpr> <value>", "Write General Purpose Register (GPR)", &handle_gpr }, - { "getnia", "", "Get Next Instruction Address (NIA)", &handle_nia }, - { "putnia", "<value>", "Write Next Instrution Address (NIA)", &handle_nia }, - { "getspr", "<spr>", "Get Special Purpose Register (SPR)", &handle_spr }, - { "putspr", "<spr> <value>", "Write Special Purpose Register (SPR)", &handle_spr }, - { "getmsr", "", "Get Machine State Register (MSR)", &handle_msr }, - { "putmsr", "<value>", "Write Machine State Register (MSR)", &handle_msr }, - { "getring", "<addr> <len>", "Read a ring. Length must be correct", &handle_getring }, - { "start", "", "Start thread", &thread_start }, - { "step", "<count>", "Set a thread <count> 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", "<address>", "Read system cfam", &handle_cfams }, - { "putcfam", "<address> <value> [<mask>]", "Write system cfam", &handle_cfams }, - { "getscom", "<address>", "Read system scom", &handle_scoms }, - { "putscom", "<address> <value> [<mask>]", "Write system scom", &handle_scoms }, - { "getmem", "<address> <count>", "Read system memory", &handle_mem }, - { "putmem", "<address>", "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", "<gpr>", "Read General Purpose Register (GPR)" }, + { "putgpr", "<gpr> <value>", "Write General Purpose Register (GPR)" }, + { "getnia", "", "Get Next Instruction Address (NIA)" }, + { "putnia", "<value>", "Write Next Instrution Address (NIA)" }, + { "getspr", "<spr>", "Get Special Purpose Register (SPR)" }, + { "putspr", "<spr> <value>", "Write Special Purpose Register (SPR)" }, + { "getmsr", "", "Get Machine State Register (MSR)" }, + { "putmsr", "<value>", "Write Machine State Register (MSR)" }, + { "getring", "<addr> <len>", "Read a ring. Length must be correct" }, + { "start", "", "Start thread" }, + { "step", "<count>", "Set a thread <count> 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", "<address>", "Read system cfam" }, + { "putcfam", "<address> <value> [<mask>]", "Write system cfam" }, + { "getscom", "<address>", "Read system scom" }, + { "putscom", "<address> <value> [<mask>]", "Write system scom" }, + { "getmem", "<address> <count>", "Read system memory" }, + { "putmem", "<address>", "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) { @@ -648,7 +666,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; @@ -660,25 +678,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); @@ -710,13 +724,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; @@ -20,21 +20,32 @@ #include <string.h> #include <unistd.h> #include <assert.h> +#include <stdbool.h> #include <libpdbg.h> #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; + buf = malloc(size); assert(buf); pdbg_for_each_class_target("adu", target) { @@ -43,7 +54,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 +69,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 +90,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 +103,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 <inttypes.h> -#include <libpdbg.h> - -int dump_stack(struct thread_regs *regs); -int handle_mem(int optind, int argc, char *argv[]); @@ -22,6 +22,7 @@ #include <libpdbg.h> #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[]); @@ -18,11 +18,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <assert.h> -#include <target.h> -#include <operations.h> +#include <libpdbg.h> #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[]); @@ -22,8 +22,9 @@ #include <libpdbg.h> #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 <mask> 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 <inttypes.h> - -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 <libpdbg.h> #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 <inttypes.h> - -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[]); |