[Pdbg] [PATCH 2/2] Add fircheck support

Balbir Singh bsingharora at gmail.com
Tue Feb 13 15:58:29 AEDT 2018


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

TODOs:

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

This patch also converts for_each_target to an exported
routine, we can avoid this by moving all the code from
libpdbg/fir.c to src/main.c, but the separation might
be a good thing in the long term

Signed-off-by: Balbir Singh <bsingharora at gmail.com>
---
 Makefile.am   |   3 +-
 libpdbg/fir.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.c    |  13 +++++--
 3 files changed, 120 insertions(+), 3 deletions(-)
 create mode 100644 libpdbg/fir.c

diff --git a/Makefile.am b/Makefile.am
index 3c266d2..be459d2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -50,7 +50,8 @@ libpdbg_la_SOURCES = \
 	libpdbg/adu.c \
 	libpdbg/device.c \
 	libpdbg/target.c \
-	libpdbg/htm.c
+	libpdbg/htm.c	\
+	libpdbg/fir.c
 
 M4_V = $(M4_V_$(V))
 M4_V_ = $(M4_V_$(AM_DEFAULT_VERBOSITY))
diff --git a/libpdbg/fir.c b/libpdbg/fir.c
new file mode 100644
index 0000000..12a81ee
--- /dev/null
+++ b/libpdbg/fir.c
@@ -0,0 +1,107 @@
+/* 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"
+
+static uint64_t global_mc_fir_addr;
+static uint64_t global_mc_fir_value;
+
+extern int for_each_target(char *class, int (*cb)(struct pdbg_target *, uint32_t, uint64_t *, uint64_t *),
+				uint64_t *arg1, uint64_t *arg2);
+
+/*
+ * The design of for_each_target() makes the code non-reenterant
+ * TODO: Fix it
+ */
+static int getfir(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *value)
+{
+	int rc;
+	rc = pib_read(target, *addr, value);
+	return rc;
+}
+
+/*
+ * 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 fircheck(void)
+{
+	struct dt_node *global_fir_dn, *dn;
+	int rc;
+	uint64_t first_bit, mask, set_bit;
+
+	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;
+	}
+
+	rc = for_each_target("pib", getfir, &global_mc_fir_addr, &global_mc_fir_value);
+	if (rc) {
+		PR_ERROR("Failed to read value from multicast scom"
+			 "address %llx\n", global_mc_fir_addr);
+		goto out;
+	}
+
+	if (global_mc_fir_value == 0)
+		printf("No checkstop detected\n");
+
+	dt_for_each_compatible(dt_root, dn, "ibm,chiplet-fir") {
+		mask = dt_prop_get_u64(dn, "fir_mask");
+		if (!mask)
+			continue; /* we should abort really */
+		if (global_mc_fir_value & mask) {
+			first_bit = __builtin_clzll((unsigned long)mask);
+			set_bit = __builtin_clzll((unsigned long)global_mc_fir_value);
+			printf("FIR bit set for chiplet %s, instance %llx\n",
+				dn->name, set_bit - first_bit);
+			global_mc_fir_value &= (global_mc_fir_value - 1);
+		}
+	}
+
+out:
+	return !rc;
+}
+
diff --git a/src/main.c b/src/main.c
index 9eab915..3c3f1c2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,7 +47,7 @@ enum command { GETCFAM = 1, PUTCFAM, GETSCOM, PUTSCOM,	\
 	       STOP, START, THREADSTATUS, STEP, PROBE,	\
 	       GETVMEM, SRESET, HTM_STOP, HTM_ANALYSE,  \
 	       HTM_START, HTM_DUMP, HTM_RESET, HTM_GO,  \
-	       HTM_TRACE, HTM_STATUS };
+	       HTM_TRACE, HTM_STATUS, FIRCHECK };
 
 #define MAX_CMD_ARGS 3
 enum command cmd = 0;
@@ -72,6 +72,8 @@ static int **processorsel[MAX_PROCESSORS];
 static int *chipsel[MAX_PROCESSORS][MAX_CHIPS];
 static int threadsel[MAX_PROCESSORS][MAX_CHIPS][MAX_THREADS];
 
+extern int fircheck(void);
+
 static void print_usage(char *pname)
 {
 	printf("Usage: %s [options] command ...\n\n", pname);
@@ -124,6 +126,7 @@ static void print_usage(char *pname)
 	printf("\thtm_dump\n");
 	printf("\thtm_trace\n");
 	printf("\thtm_analyse\n");
+	printf("\tfircheck\n");
 }
 
 enum command parse_cmd(char *optarg)
@@ -225,6 +228,9 @@ enum command parse_cmd(char *optarg)
 	} else if (strcmp(optarg, "htm_analyse") == 0) {
 		cmd = HTM_ANALYSE;
 		cmd_min_arg_count = 0;
+	} else if (strcmp(optarg, "fircheck") == 0) {
+		cmd = FIRCHECK;
+		cmd_min_arg_count = 0;
 	}
 
 	if (cmd_min_arg_count && !cmd_max_arg_count)
@@ -384,7 +390,7 @@ static int for_each_child_target(char *class, struct pdbg_target *parent,
 }
 
 /* Call the given call back on each enabled target in the given class */
-static int for_each_target(char *class, int (*cb)(struct pdbg_target *, uint32_t, uint64_t *, uint64_t *), uint64_t *arg1, uint64_t *arg2)
+int for_each_target(char *class, int (*cb)(struct pdbg_target *, uint32_t, uint64_t *, uint64_t *), uint64_t *arg1, uint64_t *arg2)
 {
 	struct pdbg_target *target;
 	uint32_t index;
@@ -1094,6 +1100,9 @@ int main(int argc, char *argv[])
 	case HTM_ANALYSE:
 		rc = run_htm_analyse();
 		break;
+	case FIRCHECK:
+		rc = fircheck();
+		break;
 	default:
 		PR_ERROR("Unsupported command\n");
 		break;
-- 
2.13.6



More information about the Pdbg mailing list