[Pdbg] [PATCH v2 3/3] Add fircheck support

Balbir Singh bsingharora at gmail.com
Mon May 21 16:24:42 AEST 2018


The device tree supports basic understanding of chiplets.
On fircheck we iterate through all ibm,power9-chiplet nodes
and compare their masks from what with a value obtained
via multicast scom to get all top level FIRs

There's a bit of refactoring of code, so that code outside
of main.c can use processorsel to filter targets.

TODOs:

1. Differentiate between recoverable scoms and checkstops
2. Do deeper analysis of the root cause of the checkstop
   (longer term)

Sample output:

p1: FIR bit set for chiplet n3
p0: FIR bit set for chiplet chiplet at 25000000

I don't like chiplet at 25000000 as the name, but that's an
independent fix to follow

Signed-off-by: Balbir Singh <bsingharora at gmail.com>
---
 Makefile.am      |   2 +-
 libpdbg/device.h |   8 ++++
 src/main.c       |  28 ++++++++------
 src/main.h       |  11 ++++++
 src/p9fir.c      | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 145 insertions(+), 13 deletions(-)
 create mode 100644 src/p9fir.c

diff --git a/Makefile.am b/Makefile.am
index 6253b03..af5c5d2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,7 +28,7 @@ BUILT_SOURCES = $(DT) $(DT_headers)
 
 pdbg_SOURCES = \
 	src/main.c src/cfam.c src/scom.c src/reg.c src/mem.c src/thread.c \
-	src/ring.c src/htm.c src/progress.c src/options_ at ARCH@.c
+	src/ring.c src/htm.c src/progress.c src/options_ at ARCH@.c src/p9fir.c
 
 pdbg_LDADD = $(DT_objects) libpdbg.la libfdt.la \
 	-L.libs
diff --git a/libpdbg/device.h b/libpdbg/device.h
index 05d6c12..2e94c9e 100644
--- a/libpdbg/device.h
+++ b/libpdbg/device.h
@@ -144,6 +144,14 @@ struct pdbg_target *dt_find_compatible_node_on_chip(struct pdbg_target *root,
 	for (node = NULL; 			        \
 	     (node = dt_find_compatible_node_on_chip(root, node,\
 						     compat, chip_id)) != NULL;)
+
+/*
+ * We can auto-generate more of these, if we end up needing
+ * many of these later
+ */
+#define dt_for_each_power9_chiplet(root, node) \
+	dt_for_each_compatible(root, node, "ibm,power9-chiplet")
+
 /* Check status property */
 bool dt_node_is_enabled(struct pdbg_target *node);
 
diff --git a/src/main.c b/src/main.c
index 20f5319..12421b6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -64,20 +64,14 @@
 #include "p9-host.dt.h"
 #endif
 
-#define THREADS_PER_CORE	8
-
 static enum backend backend = KERNEL;
 
 static char const *device_node;
 static int i2c_addr = 0x50;
 
-#define MAX_PROCESSORS 16
-#define MAX_CHIPS 24
-#define MAX_THREADS THREADS_PER_CORE
-
-static int **processorsel[MAX_PROCESSORS];
-static int *chipsel[MAX_PROCESSORS][MAX_CHIPS];
-static int threadsel[MAX_PROCESSORS][MAX_CHIPS][MAX_THREADS];
+int **processorsel[MAX_PROCESSORS];
+int *chipsel[MAX_PROCESSORS][MAX_CHIPS];
+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[]);
@@ -124,6 +118,7 @@ static struct action actions[] = {
 	{ "threadstatus", "", "Print the status of a thread", &thread_status_print },
 	{ "sreset",  "", "Reset", &thread_sreset },
 	{ "regs",  "", "State", &thread_state },
+	{ "fircheck", "", "Get information about triggered FIR bits", &handle_fircheck },
 };
 
 
@@ -550,10 +545,19 @@ void print_target(struct pdbg_target *target, int level)
 		else if (!strcmp(pdbg_target_class_name(target), "thread"))
 			c = 't';
 
-		if (c)
-			printf("%c%d: %s\n", c, pdbg_target_index(target), pdbg_target_name(target));
-		else
+		if (c) {
+			/*
+			 * For power9 the core chiplets are indexed from 32. Find a better way
+			 * to do this
+			 */
+			if (!strncmp(target->compatible, "ibm,power9-core", strlen(target->compatible))) {
+				printf("%c%d: %s\n", c, pdbg_target_index(target)-32, pdbg_target_name(target));
+			} else {
+				printf("%c%d: %s\n", c, pdbg_target_index(target), pdbg_target_name(target));
+			}
+		} else {
 			printf("%s\n", pdbg_target_name(target));
+		}
 	}
 
 	pdbg_for_each_child_target(target, next) {
diff --git a/src/main.h b/src/main.h
index e060553..3a5b79b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -17,6 +17,16 @@
 
 #include <target.h>
 
+#define THREADS_PER_CORE	8
+
+#define MAX_PROCESSORS 16
+#define MAX_CHIPS 24
+#define MAX_THREADS THREADS_PER_CORE
+
+extern int **processorsel[MAX_PROCESSORS];
+extern int *chipsel[MAX_PROCESSORS][MAX_CHIPS];
+extern int threadsel[MAX_PROCESSORS][MAX_CHIPS][MAX_THREADS];
+
 enum backend { FSI, I2C, KERNEL, FAKE, HOST };
 
 static inline bool target_is_disabled(struct pdbg_target *target)
@@ -36,3 +46,4 @@ int for_each_child_target(char *class, struct pdbg_target *parent,
 
 int for_each_target(char *class, int (*cb)(struct pdbg_target *, uint32_t, uint64_t *, uint64_t *), uint64_t *arg1, uint64_t *arg2);
 void for_each_target_release(char *class);
+int handle_fircheck(int optind, int argc, char *argv[]);
diff --git a/src/p9fir.c b/src/p9fir.c
new file mode 100644
index 0000000..7cddbdd
--- /dev/null
+++ b/src/p9fir.c
@@ -0,0 +1,109 @@
+
+/* 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.
+ */
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "operations.h"
+#include "bitutils.h"
+#include "target.h"
+#include "device.h"
+#include "main.h"
+
+static uint64_t global_mc_fir_addr;
+
+/*
+ * Print a summary of the FIR check errors.
+ *
+ * NOTE: The current implementation looks at the top most bits
+ * there is much more to do. We need to dig deeper and look at
+ * recoverable and xstop bits and in the future FFDC bits as
+ * well
+ */
+int handle_fircheck(int optind, int argc, char *argv[])
+{
+	struct pdbg_target *pib, *global_fir_dn;
+	int rc = 0;
+
+	global_fir_dn = dt_find_by_name(dt_root, "global_fir");
+	if (!global_fir_dn) {
+		rc = -1;
+		PR_ERROR("Failed to find global multicast scom fir address"
+			 "Please check the device tree bindings\n");
+		goto out;
+	}
+
+	if (!global_mc_fir_addr)
+		global_mc_fir_addr = dt_get_address(global_fir_dn, 0, NULL);
+
+	if (!global_mc_fir_addr) {
+		rc = -1;
+		PR_ERROR("Failed to find global multicast scom fir address"
+			 "Please check the device tree bindings\n");
+		goto out;
+	}
+
+	PR_DEBUG("Chiplet multicast addr for checkstop is 0x%016" PRIx64 "\n",
+			global_mc_fir_addr);
+
+	pdbg_for_each_class_target("pib", pib) {
+		uint64_t value;
+		struct pdbg_target *dn;
+		uint32_t i, status;
+
+		if (!processorsel[pib->index])
+			continue;
+
+		PR_DEBUG("pib is %s:%d\n", pib->name, pib->index);
+		pdbg_target_probe(pib);
+		status = pdbg_target_status(pib);
+		if (status != PDBG_TARGET_ENABLED)
+			continue;
+
+		rc = pib_read(pib, global_mc_fir_addr, &value);
+		if (rc) {
+			PR_ERROR("p%d: Failed to read global machine "
+				"check fir value", pib->index);
+			goto out;
+		}
+
+		if (value == 0)
+			printf("p%d: No checkstop detected\n", pib->index);
+
+		dt_for_each_power9_chiplet(dt_root, dn) {
+			i = dt_prop_get_u32(dn, "index");
+			if (!i)
+				continue; /* we should abort really */
+
+			if (value & PPC_BIT(i)) {
+				printf("p%d: FIR bit set for chiplet %s\n", pib->index, dn->dn_name);
+				value &= ~PPC_BIT(i);
+			}
+		}
+	}
+
+out:
+	return !rc;
+}
-- 
2.13.6



More information about the Pdbg mailing list