diff options
author | Cyril Bur <cyrilbur@gmail.com> | 2018-02-14 15:27:42 +1100 |
---|---|---|
committer | Alistair Popple <alistair@popple.id.au> | 2018-02-16 16:22:23 +1100 |
commit | 2f0db42bf79bb0e91cc424dcb71ba78ff4766526 (patch) | |
tree | 880fb714f171083f6e1da4a66b7fcdc3af73bc6b /src/htm.c | |
parent | 01b39f4737a7e3a5bb9d1e01d6e1f18d20a5b739 (diff) | |
download | pdbg-2f0db42bf79bb0e91cc424dcb71ba78ff4766526.tar.gz pdbg-2f0db42bf79bb0e91cc424dcb71ba78ff4766526.zip |
main: Add HTM functions to deal with Core HTM
This commit also updates the README to only reference the new commands
Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
Diffstat (limited to 'src/htm.c')
-rw-r--r-- | src/htm.c | 222 |
1 files changed, 148 insertions, 74 deletions
@@ -13,6 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + + + + /* + * This file does the Hardware Trace Macro command parsing for pdbg + * the program. + * It will call into libpdbg backend with a target to either a 'nhtm' + * or a 'chtm' which will ultimately do the work. + * + */ #define _GNU_SOURCE #include <inttypes.h> #include <stdio.h> @@ -20,6 +30,8 @@ #include <string.h> #include <unistd.h> +#include <ccan/array_size/array_size.h> + #include <target.h> #include <operations.h> @@ -27,6 +39,13 @@ #define HTM_DUMP_BASENAME "htm.dump" +#define HTM_ENUM_TO_STRING(e) ((e == HTM_NEST) ? "nhtm" : "chtm") + +enum htm_type { + HTM_CORE, + HTM_NEST, +}; + static char *get_htm_dump_filename(void) { char *filename; @@ -47,12 +66,12 @@ static char *get_htm_dump_filename(void) return filename; } -int run_htm_start(int optind, int argc, char *argv[]) +static int run_start(enum htm_type type, int optind, int argc, char *argv[]) { struct pdbg_target *target; int rc = 0; - pdbg_for_each_class_target("nhtm", target) { + pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) { uint64_t chip_id; uint32_t index; @@ -70,12 +89,12 @@ int run_htm_start(int optind, int argc, char *argv[]) return rc; } -int run_htm_stop(int optind, int argc, char *argv[]) +static int run_stop(enum htm_type type, int optind, int argc, char *argv[]) { struct pdbg_target *target; int rc = 0; - pdbg_for_each_class_target("nhtm", target) { + pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) { uint64_t chip_id; uint32_t index; @@ -93,12 +112,12 @@ int run_htm_stop(int optind, int argc, char *argv[]) return rc; } -int run_htm_status(int optind, int argc, char *argv[]) +static int run_status(enum htm_type type, int optind, int argc, char *argv[]) { struct pdbg_target *target; int rc = 0; - pdbg_for_each_class_target("nhtm", target) { + pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) { uint64_t chip_id; uint32_t index; @@ -117,13 +136,13 @@ int run_htm_status(int optind, int argc, char *argv[]) return rc; } -int run_htm_reset(int optind, int argc, char *argv[]) +static int run_reset(enum htm_type type, int optind, int argc, char *argv[]) { uint64_t old_base = 0, base, size; struct pdbg_target *target; int rc = 0; - pdbg_for_each_class_target("nhtm", target) { + pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) { uint64_t chip_id; uint32_t index; @@ -149,7 +168,7 @@ int run_htm_reset(int optind, int argc, char *argv[]) return rc; } -int run_htm_dump(int optind, int argc, char *argv[]) +static int run_dump(enum htm_type type, int optind, int argc, char *argv[]) { struct pdbg_target *target; char *filename; @@ -161,7 +180,7 @@ int run_htm_dump(int optind, int argc, char *argv[]) /* size = 0 will dump everything */ printf("Dumping HTM trace to file [chip].[#]%s\n", filename); - pdbg_for_each_class_target("nhtm", target) { + pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) { uint64_t chip_id; uint32_t index; @@ -180,91 +199,146 @@ int run_htm_dump(int optind, int argc, char *argv[]) return rc; } -int run_htm_trace(int optind, int argc, char *argv[]) +static int run_trace(enum htm_type type, int optind, int argc, char *argv[]) { - uint64_t old_base = 0, base, size; - struct pdbg_target *target; - int rc = 0; + int rc; - pdbg_for_each_class_target("nhtm", target) { - uint64_t chip_id; - uint32_t index; - - if (target_is_disabled(target)) - continue; - - index = pdbg_target_index(target); - assert(!pdbg_get_u64_property(target, "chip-id", &chip_id)); - - /* - * Don't mind if stop fails, it will fail if it wasn't - * running, if anything bad is happening reset will fail - */ - htm_stop(target); - printf("Resetting HTM@%" PRIu64 "#%d\n", chip_id, index); - if (htm_reset(target, &base, &size) != 1) - printf("Couldn't reset HTM@%" PRIu64 "#%d\n", chip_id, index); - if (old_base != base) { - printf("The kernel has initialised HTM memory at:\n"); - printf("base: 0x%016" PRIx64 " for 0x%016" PRIx64 " size\n", - base, size); - printf("./pdbg getmem 0x%016" PRIx64 " 0x%016" PRIx64 " > htm.dump\n\n", - base, size); - } - old_base = base; + rc = run_reset(type, optind, argc, argv); + if (rc == 0) { + printf("No HTM units were reset.\n"); + printf("It is unlikely anything will start... trying anyway\n"); } - pdbg_for_each_class_target("nhtm", target) { - uint64_t chip_id; - uint32_t index; + rc = run_start(type, optind, argc, argv); + if (rc == 0) + printf("No HTM units were started\n"); - if (target_is_disabled(target)) - continue; + return rc; +} - index = pdbg_target_index(target); - assert(!pdbg_get_u64_property(target, "chip-id", &chip_id)); - printf("Starting HTM@%" PRIu64 "#%d\n", chip_id, index); - if (htm_start(target) != 1) - printf("Couldn't start HTM@%" PRIu64 "#%d\n", chip_id, index); - rc++; +static int run_analyse(enum htm_type type, int optind, int argc, char *argv[]) +{ + int rc; + + rc = run_stop(type, optind, argc, argv); + if (rc == 0) { + printf("No HTM units were stopped.\n"); + printf("It is unlikely anything will dump... trying anyway\n"); } + rc = run_dump(type, optind, argc, argv); + if (rc == 0) + printf("No HTM buffers were dumped to file\n"); + return rc; } -int run_htm_analyse(int optind, int argc, char *argv[]) +static struct { + const char *name; + const char *args; + const char *desc; + int (*fn)(enum htm_type, int, int, char **); +} actions[] = { + { "start", "", "Start %s HTM", &run_start }, + { "stop", "", "Stop %s HTM", &run_stop }, + { "status", "", "Get %s HTM status", &run_status }, + { "reset", "", "Reset %s HTM", &run_reset }, + { "dump", "", "Dump %s HTM buffer to file", &run_dump }, + { "trace", "", "Configure and start %s HTM", &run_trace }, + { "analyse","", "Stop and dump %s HTM", &run_analyse}, +}; + +static void print_usage(enum htm_type type) { - struct pdbg_target *target; - char *filename; - int rc = 0; + int i; - pdbg_for_each_class_target("nhtm", target) { - if (target_is_disabled(target)) - continue; + for (i = 0; i < ARRAY_SIZE(actions); i++) { + printf("%s %s", actions[i].name, actions[i].args); + printf(actions[i].desc, HTM_ENUM_TO_STRING(type)); + printf("\n"); + } +} + +int run_htm(int optind, int argc, char *argv[]) +{ + enum htm_type type; + int i, rc = 0; - htm_stop(target); + if (argc - optind < 2) { + fprintf(stderr, "Expecting one of 'core' or 'nest' with a command\n"); + return 0; } - filename = get_htm_dump_filename(); - if (!filename) + optind++; + if (strcmp(argv[optind], "core") == 0) { + type = HTM_CORE; + } else if (strcmp(argv[optind], "nest") == 0) { + type = HTM_NEST; + } else { + fprintf(stderr, "Expecting one of 'core' or 'nest' not %s\n", + argv[optind]); return 0; + } - printf("Dumping HTM trace to file [chip].[#]%s\n", filename); - pdbg_for_each_class_target("nhtm", target) { - uint64_t chip_id; - uint32_t index; + if (type == HTM_CORE) + fprintf(stderr, "Warning: Core HTM is currently experimental\n"); - if (target_is_disabled(target)) - continue; + optind++; + for (i = 0; i < ARRAY_SIZE(actions); i++) { + if (strcmp(argv[optind], actions[i].name) == 0) { + rc = actions[i].fn(type, optind, argc, argv); + break; + } + } - index = pdbg_target_index(target); - assert(!pdbg_get_u64_property(target, "chip-id", &chip_id)); - printf("Dumping HTM@%" PRIu64 "#%d\n", chip_id, index); - if (htm_dump(target, 0, filename) != 1) - printf("Couldn't dump HTM@%" PRIu64 "#%d\n", chip_id, index); - rc++; + if (i == ARRAY_SIZE(actions)) { + PR_ERROR("Unsupported command: %s\n", argv[optind]); + print_usage(type); + return 0; + } else if (rc == 0) { + fprintf(stderr, "Couldn't run the HTM command.\n"); + fprintf(stderr, "Double check that your kernel has debugfs mounted and the memtrace patches\n"); } - free(filename); return rc; } + +/* + * These are all the old handlers that only worked with nest HTM. + * I don't want to break the commands but we've gone with a more + * flexible HTM command structure to better incorporate core HTM. + */ +int run_htm_start(int optind, int argc, char *argv[]) +{ + return run_start(HTM_NEST, optind, argc, argv); +} + +int run_htm_stop(int optind, int argc, char *argv[]) +{ + return run_stop(HTM_NEST, optind, argc, argv); +} + +int run_htm_status(int optind, int argc, char *argv[]) +{ + return run_status(HTM_NEST, optind, argc, argv); +} + +int run_htm_reset(int optind, int argc, char *argv[]) +{ + return run_reset(HTM_NEST, optind, argc, argv); +} + +int run_htm_dump(int optind, int argc, char *argv[]) +{ + return run_dump(HTM_NEST, optind, argc, argv);; +} + +int run_htm_trace(int optind, int argc, char *argv[]) +{ + return run_trace(HTM_NEST, optind, argc, argv); +} + +int run_htm_analyse(int optind, int argc, char *argv[]) +{ + return run_analyse(HTM_NEST, optind, argc, argv); +} |