[Pdbg] [PATCH RFC 3/4] pdbg: add timeer facility TB error injections.

Nicholas Piggin npiggin at gmail.com
Wed May 13 15:04:31 AEST 2020


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 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