[Pdbg] [PATCH RFC 3/4] pdbg: add timeer facility TB error injections.
Mahesh Salgaonkar
mahesh at linux.ibm.com
Mon May 11 18:41:38 AEST 2020
# ./pdbg -p0 -c3 -t3 inject
Usage: pdbg inject <component> <error>
<component>:
? Show component list
tb
# ./pdbg -p0 -c3 -t3 inject tb ?
Usage: pdbg inject tb <error>:
<error>:
? Show error list
tfmr_parity TFMR parity error
hdec_parity HDEC parity error
tb_residue TB parity/residue error
purr_parity PURR parity error
spurr_parity SPURR parity error
dec_parity DEC parity error
# ./pdbg -p0 -c1 -t3 inject tb dec_parity
p0:c1:t3: 0x20010a84 = 0x001e000000000000
#
# ./pdbg -p0 -c1,2 inject tb hdec_parity
p0:c1: 0x20010a84 = 0x0002000000000000
p0:c2: 0x20010a84 = 0x0002000000000000
#
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.ibm.com>
---
Makefile.am | 3 +
src/err_inject.c | 46 +++++++++++++++++++++
src/err_inject.h | 43 +++++++++++++++++++
src/timefac_error.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 205 insertions(+), 1 deletion(-)
create mode 100644 src/timefac_error.c
diff --git a/Makefile.am b/Makefile.am
index 05522cf..ed97505 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -122,7 +122,8 @@ pdbg_SOURCES = \
src/util.c \
src/util.h \
src/err_inject.c \
- src/err_inject.h
+ src/err_inject.h \
+ src/timefac_error.c
pdbg_CFLAGS = -I$(top_srcdir)/libpdbg -Wall -Werror -DGIT_SHA1=\"${GIT_SHA1}\" \
$(ARCH_FLAGS)
diff --git a/src/err_inject.c b/src/err_inject.c
index ef6bc97..c059ef8 100644
--- a/src/err_inject.c
+++ b/src/err_inject.c
@@ -22,6 +22,7 @@
#include <libpdbg.h>
#include <ccan/list/list.h>
+#include <bitutils.h>
#include "main.h"
#include "optcmd.h"
@@ -162,9 +163,54 @@ static void inject_errors(char *component, char *error)
}
}
+static char *target_short_path(struct pdbg_target *target)
+{
+ char result[255];
+ char *bufp = result;
+ int proc_index = -1, chip_index = -1, thread_index = -1;
+ int n = 0;
+
+ if (get_target_type(target) == TARGET_TYPE_THREAD) {
+ thread_index = pdbg_target_index(target);
+ target = pdbg_target_parent("core", target);
+ }
+ if (get_target_type(target) == TARGET_TYPE_CORE) {
+ chip_index = pdbg_target_index(target);
+ target = pdbg_target_parent("pib", target);
+ }
+ if (get_target_type(target) == TARGET_TYPE_PROC)
+ proc_index = pdbg_target_index(target);
+
+ if (proc_index >= 0)
+ n += sprintf(bufp + n, "p%d:", proc_index);
+ if (chip_index >= 0)
+ n += sprintf(bufp + n, "c%d:", chip_index);
+ if (thread_index >= 0)
+ n += sprintf(bufp + n, "t%d:", thread_index);
+
+ return strdup(result);
+}
+
+int target_inject_error(struct pdbg_target *target, uint32_t scom_addr,
+ uint64_t val)
+{
+ char *short_path;
+ int rc;
+
+ rc = pib_write(target, scom_addr, val);
+ if (rc)
+ return rc;
+
+ short_path = target_short_path(target);
+ printf("%s 0x%x = 0x%016llx\n", short_path, scom_addr, val);
+ free(short_path);
+ return 0;
+}
+
static void error_inject_init(void)
{
/* Call error inject init routines. */
+ timefac_err_init();
}
static int inject(char *component, char *error)
diff --git a/src/err_inject.h b/src/err_inject.h
index 76acee7..d295470 100644
--- a/src/err_inject.h
+++ b/src/err_inject.h
@@ -3,6 +3,12 @@
#include <stdint.h>
#include <stdbool.h>
+#include <libpdbg.h>
+
+/* Target types */
+#define TARGET_TYPE_PROC 1
+#define TARGET_TYPE_CORE 2
+#define TARGET_TYPE_THREAD 3
typedef int (*inject_error_t)(struct pdbg_target *target, void *data);
@@ -17,4 +23,41 @@ typedef int (*inject_error_t)(struct pdbg_target *target, void *data);
*/
extern int register_error_inject(char *component, char *error,
char *error_desc, inject_error_t func, void *data);
+
+/* Get target type */
+static inline int get_target_type(struct pdbg_target *target)
+{
+ const char *classname;
+
+ classname = pdbg_target_class_name(target);
+ if (!strcmp(classname, "pib"))
+ return TARGET_TYPE_PROC;
+
+ if (!strcmp(classname, "core"))
+ return TARGET_TYPE_CORE;
+
+ if (!strcmp(classname, "thread"))
+ return TARGET_TYPE_THREAD;
+
+ return 0;
+}
+
+/**
+ * @brief Inject an error on specified target using scom addr/value.
+ * @param[in] target pdbg target where error to be injected.
+ * @param[in] scom_adddr SCOM address to use.
+ * @param[in] val Value to set for a given scom address.
+ *
+ * This function uses pib_write() to write to scom address and on
+ * successfull injection it prints out target short path along with
+ * scom address and data written.
+ * e.g.
+ * p0:c1:t3: 0x20010a84 = 0x001e000000000000
+ */
+int target_inject_error(struct pdbg_target *target, uint32_t scom_addr,
+ uint64_t val);
+
+/* Error inject init functions */
+extern void timefac_err_init(void);
+
#endif
diff --git a/src/timefac_error.c b/src/timefac_error.c
new file mode 100644
index 0000000..cb6c9ac
--- /dev/null
+++ b/src/timefac_error.c
@@ -0,0 +1,114 @@
+/* Copyright 2020 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.
+ */
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libpdbg.h>
+#include <ccan/list/list.h>
+#include <ccan/array_size/array_size.h>
+#include <bitutils.h>
+
+#include "main.h"
+#include "optcmd.h"
+#include "path.h"
+#include "err_inject.h"
+
+/* SPR_MODE scom address */
+#define P9_SCOM_SPR_MODE 0x20010A84
+
+/* TB Errors */
+#define TB_ERROR_MASK PPC_BITMASK(10, 15)
+/* Core level TB errors */
+#define TB_ERROR_TFMR_PARITY 0x1
+#define TB_ERROR_HDEC_PARITY 0x2
+#define TB_ERROR_TB_PARITY 0x3
+/* Thread level TB errors */
+#define TB_ERROR_PURR_PARITY 0x4
+#define TB_ERROR_SPURR_PARITY 0x5
+#define TB_ERROR_DEC_PARITY 0x6
+
+typedef struct error_type {
+ char *name;
+ char *desc;
+ uint64_t error;
+} error_type_t;
+
+static error_type_t tb_error_type[] = {
+ { "tfmr_parity", "TFMR parity error", TB_ERROR_TFMR_PARITY },
+ { "hdec_parity", "HDEC parity error", TB_ERROR_HDEC_PARITY },
+ { "tb_residue", "TB parity/residue error", TB_ERROR_TB_PARITY },
+ { "purr_parity", "PURR parity error", TB_ERROR_PURR_PARITY },
+ { "spurr_parity", "SPURR parity error", TB_ERROR_SPURR_PARITY },
+ { "dec_parity", "DEC parity error", TB_ERROR_DEC_PARITY },
+};
+
+static int timefac_inject_tb_error(struct pdbg_target *target, void *data)
+{
+ int target_type = 0;
+ uint64_t err_type;
+ uint64_t val;
+ uint64_t tindex;
+ int rc;
+
+ err_type = *((uint64_t *)data);
+ if (err_type < TB_ERROR_PURR_PARITY)
+ target_type = TARGET_TYPE_CORE;
+ else
+ target_type = TARGET_TYPE_THREAD;
+
+ if (target_type != get_target_type(target))
+ return -EINVAL;
+
+ /*
+ * TODO: Add a check for proc type p8/p9/p10 and then use scom
+ * address appropriately.
+ */
+ rc = pib_read(target, P9_SCOM_SPR_MODE, &val);
+ if (rc) {
+ /* just print the error message and continue. */
+ printf("Failed to read scom addr: %x\n", P9_SCOM_SPR_MODE);
+ val = 0;
+ }
+
+ /* set the error type and thread index where error to be injected */
+ if (target_type == TARGET_TYPE_THREAD) {
+ tindex = pdbg_target_index(target);
+ err_type |= (tindex << 3);
+ }
+ val = SETFIELD(TB_ERROR_MASK, val, err_type);
+
+ rc = target_inject_error(target, P9_SCOM_SPR_MODE, val);
+ if (rc) {
+ printf("Failed to inject\n");
+ }
+ return rc;
+}
+
+void timefac_err_init(void)
+{
+ int i;
+
+ /* Register Tb error injects. */
+ for (i = 0; i < ARRAY_SIZE(tb_error_type); i++)
+ register_error_inject("tb", tb_error_type[i].name,
+ tb_error_type[i].desc, timefac_inject_tb_error,
+ &tb_error_type[i].error);
+
+}
More information about the Pdbg
mailing list