[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