[Pdbg] [PATCH RFC 3/4] pdbg: add timeer facility TB error injections.
Mahesh J Salgaonkar
mahesh at linux.ibm.com
Tue May 26 16:18:21 AEST 2020
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 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);
> > +
> > +}
> >
> >
--
Mahesh J Salgaonkar
More information about the Pdbg
mailing list