[Pdbg] [PATCH RFC 3/4] pdbg: add timeer facility TB error injections.
Alistair Popple
alistair at popple.id.au
Tue May 26 16:21:44 AEST 2020
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 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