summaryrefslogtreecommitdiffstats
path: root/src/htm.c
diff options
context:
space:
mode:
authorCyril Bur <cyrilbur@gmail.com>2018-02-14 15:27:42 +1100
committerAlistair Popple <alistair@popple.id.au>2018-02-16 16:22:23 +1100
commit2f0db42bf79bb0e91cc424dcb71ba78ff4766526 (patch)
tree880fb714f171083f6e1da4a66b7fcdc3af73bc6b /src/htm.c
parent01b39f4737a7e3a5bb9d1e01d6e1f18d20a5b739 (diff)
downloadpdbg-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.c222
1 files changed, 148 insertions, 74 deletions
diff --git a/src/htm.c b/src/htm.c
index d6638ea..56fcf26 100644
--- a/src/htm.c
+++ b/src/htm.c
@@ -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);
+}
OpenPOWER on IntegriCloud