Message ID | 158918649880.16822.9214964387579789187.stgit@jupiter |
---|---|
State | New |
Headers | show |
Series | [RFC,1/4] pdbg: Add support for error injection framework. | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch master (6c10b68bf774a9fe21affd5ef0b40084cd49800d) |
snowpatch_ozlabs/build-multiarch | fail | Test build-multiarch on branch master |
Hey Mahesh, Very nice, I'm assuming adding various MCE injection should be quite easy when the framework is in place. I'm handwaving a bit here because I haven't looked at pdbg's targeting for so long maybe it doesn't quite work so well, but what I had hoped is that targets would implement an ->inject_error and ->inject_error_list that core code knows nothing about but calls directly. Then the targets would be able to advertise exactly what they implement and common code doesn't have these target specifics. Thanks, Nick Excerpts from Mahesh Salgaonkar's message of May 11, 2020 6:41 pm: > # ./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@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); > + > +} > >
On 2020-05-13 15:04:31 Wed, Nicholas Piggin wrote: > Hey Mahesh, > > Very nice, I'm assuming adding various MCE injection should be quite > easy when the framework is in place. > > I'm handwaving a bit here because I haven't looked at pdbg's targeting > for so long maybe it doesn't quite work so well, but what I had hoped is > that targets would implement an ->inject_error and ->inject_error_list > that core code knows nothing about but calls directly. I followed the getscom/putscom way.. Let me see if I can hook this up into target itself. Thanks, -Mahesh. > > Then the targets would be able to advertise exactly what they implement > and common code doesn't have these target specifics. > > Thanks, > Nick > > Excerpts from Mahesh Salgaonkar's message of May 11, 2020 6:41 pm: > > # ./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@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); > > + > > +} > > > >
Sorry, I meant to get to this earlier but Nick's idea seems worth investigating. We could add ->inject_error and ->inject_error_list to the struct pdbg_target which would allow us to add recipes for injecting errors on any target that supports them which would be nice. - Alistair On Tuesday, 26 May 2020 4:18:21 PM AEST Mahesh J Salgaonkar wrote: > On 2020-05-13 15:04:31 Wed, Nicholas Piggin wrote: > > Hey Mahesh, > > > > Very nice, I'm assuming adding various MCE injection should be quite > > easy when the framework is in place. > > > > I'm handwaving a bit here because I haven't looked at pdbg's targeting > > for so long maybe it doesn't quite work so well, but what I had hoped is > > that targets would implement an ->inject_error and ->inject_error_list > > that core code knows nothing about but calls directly. > > I followed the getscom/putscom way.. Let me see if I can hook this up > into target itself. > > Thanks, > -Mahesh. > > > Then the targets would be able to advertise exactly what they implement > > and common code doesn't have these target specifics. > > > > Thanks, > > Nick > > > > Excerpts from Mahesh Salgaonkar's message of May 11, 2020 6:41 pm: > > > # ./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@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); > > > + > > > +}
On 2020-05-26 16:21:44 Tue, Alistair Popple wrote: > Sorry, I meant to get to this earlier but Nick's idea seems worth > investigating. We could add ->inject_error and ->inject_error_list to the > struct pdbg_target which would allow us to add recipes for injecting errors on > any target that supports them which would be nice. Yup I agree. I was on leave last week. I will take look and try to hook this into target (struct pdbg_target ) itself. Thanks, -Mahesh. > > - Alistair > > On Tuesday, 26 May 2020 4:18:21 PM AEST Mahesh J Salgaonkar wrote: > > On 2020-05-13 15:04:31 Wed, Nicholas Piggin wrote: > > > Hey Mahesh, > > > > > > Very nice, I'm assuming adding various MCE injection should be quite > > > easy when the framework is in place. > > > > > > I'm handwaving a bit here because I haven't looked at pdbg's targeting > > > for so long maybe it doesn't quite work so well, but what I had hoped is > > > that targets would implement an ->inject_error and ->inject_error_list > > > that core code knows nothing about but calls directly. > > > > I followed the getscom/putscom way.. Let me see if I can hook this up > > into target itself. > > > > Thanks, > > -Mahesh. > > > > > Then the targets would be able to advertise exactly what they implement > > > and common code doesn't have these target specifics. > > > > > > Thanks, > > > Nick > > > > > > Excerpts from Mahesh Salgaonkar's message of May 11, 2020 6:41 pm: > > > > # ./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@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); > > > > + > > > > +} > > > >
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); + +}
# ./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@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