1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/arch/powerpc/include/uapi/asm/papr_pdsm.h
Vaibhav Jain bbbca72352 powerpc/papr_scm: Implement initial support for injecting smart errors
Presently PAPR doesn't support injecting smart errors on an
NVDIMM. This makes testing the NVDIMM health reporting functionality
difficult as simulating NVDIMM health related events need a hacked up
qemu version.

To solve this problem this patch proposes simulating certain set of
NVDIMM health related events in papr_scm. Specifically 'fatal' health
state and 'dirty' shutdown state. These error can be injected via the
user-space 'ndctl-inject-smart(1)' command. With the proposed patch and
corresponding ndctl patches following command flow is expected:

$ sudo ndctl list -DH -d nmem0
...
      "health_state":"ok",
      "shutdown_state":"clean",
...
 # inject unsafe shutdown and fatal health error
$ sudo ndctl inject-smart nmem0 -Uf
...
      "health_state":"fatal",
      "shutdown_state":"dirty",
...
 # uninject all errors
$ sudo ndctl inject-smart nmem0 -N
...
      "health_state":"ok",
      "shutdown_state":"clean",
...

The patch adds a new member 'health_bitmap_inject_mask' inside struct
papr_scm_priv which is then bitwise ANDed to the health bitmap fetched from the
hypervisor. The value for 'health_bitmap_inject_mask' is accessible from sysfs
at nmemX/papr/health_bitmap_inject.

A new PDSM named 'SMART_INJECT' is proposed that accepts newly
introduced 'struct nd_papr_pdsm_smart_inject' as payload thats
exchanged between libndctl and papr_scm to indicate the requested
smart-error states.

When the processing the PDSM 'SMART_INJECT', papr_pdsm_smart_inject()
constructs a pair or 'inject_mask' and 'clear_mask' bitmaps from the payload
and bit-blt it to the 'health_bitmap_inject_mask'. This ensures the after being
fetched from the hypervisor, the health_bitmap reflects requested smart-error
states.

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220124202204.1488346-1-vaibhav@linux.ibm.com
2022-02-16 23:10:47 +11:00

165 lines
5.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* PAPR nvDimm Specific Methods (PDSM) and structs for libndctl
*
* (C) Copyright IBM 2020
*
* Author: Vaibhav Jain <vaibhav at linux.ibm.com>
*/
#ifndef _UAPI_ASM_POWERPC_PAPR_PDSM_H_
#define _UAPI_ASM_POWERPC_PAPR_PDSM_H_
#include <linux/types.h>
#include <linux/ndctl.h>
/*
* PDSM Envelope:
*
* The ioctl ND_CMD_CALL exchange data between user-space and kernel via
* envelope which consists of 2 headers sections and payload sections as
* illustrated below:
* +-----------------+---------------+---------------------------+
* | 64-Bytes | 8-Bytes | Max 184-Bytes |
* +-----------------+---------------+---------------------------+
* | ND-HEADER | PDSM-HEADER | PDSM-PAYLOAD |
* +-----------------+---------------+---------------------------+
* | nd_family | | |
* | nd_size_out | cmd_status | |
* | nd_size_in | reserved | nd_pdsm_payload |
* | nd_command | payload --> | |
* | nd_fw_size | | |
* | nd_payload ---> | | |
* +---------------+-----------------+---------------------------+
*
* ND Header:
* This is the generic libnvdimm header described as 'struct nd_cmd_pkg'
* which is interpreted by libnvdimm before passed on to papr_scm. Important
* member fields used are:
* 'nd_family' : (In) NVDIMM_FAMILY_PAPR_SCM
* 'nd_size_in' : (In) PDSM-HEADER + PDSM-IN-PAYLOAD (usually 0)
* 'nd_size_out' : (In) PDSM-HEADER + PDSM-RETURN-PAYLOAD
* 'nd_command' : (In) One of PAPR_PDSM_XXX
* 'nd_fw_size' : (Out) PDSM-HEADER + size of actual payload returned
*
* PDSM Header:
* This is papr-scm specific header that precedes the payload. This is defined
* as nd_cmd_pdsm_pkg. Following fields aare available in this header:
*
* 'cmd_status' : (Out) Errors if any encountered while servicing PDSM.
* 'reserved' : Not used, reserved for future and should be set to 0.
* 'payload' : A union of all the possible payload structs
*
* PDSM Payload:
*
* The layout of the PDSM Payload is defined by various structs shared between
* papr_scm and libndctl so that contents of payload can be interpreted. As such
* its defined as a union of all possible payload structs as
* 'union nd_pdsm_payload'. Based on the value of 'nd_cmd_pkg.nd_command'
* appropriate member of the union is accessed.
*/
/* Max payload size that we can handle */
#define ND_PDSM_PAYLOAD_MAX_SIZE 184
/* Max payload size that we can handle */
#define ND_PDSM_HDR_SIZE \
(sizeof(struct nd_pkg_pdsm) - ND_PDSM_PAYLOAD_MAX_SIZE)
/* Various nvdimm health indicators */
#define PAPR_PDSM_DIMM_HEALTHY 0
#define PAPR_PDSM_DIMM_UNHEALTHY 1
#define PAPR_PDSM_DIMM_CRITICAL 2
#define PAPR_PDSM_DIMM_FATAL 3
/* struct nd_papr_pdsm_health.extension_flags field flags */
/* Indicate that the 'dimm_fuel_gauge' field is valid */
#define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID 1
/* Indicate that the 'dimm_dsc' field is valid */
#define PDSM_DIMM_DSC_VALID 2
/*
* Struct exchanged between kernel & ndctl in for PAPR_PDSM_HEALTH
* Various flags indicate the health status of the dimm.
*
* extension_flags : Any extension fields present in the struct.
* dimm_unarmed : Dimm not armed. So contents wont persist.
* dimm_bad_shutdown : Previous shutdown did not persist contents.
* dimm_bad_restore : Contents from previous shutdown werent restored.
* dimm_scrubbed : Contents of the dimm have been scrubbed.
* dimm_locked : Contents of the dimm cant be modified until CEC reboot
* dimm_encrypted : Contents of dimm are encrypted.
* dimm_health : Dimm health indicator. One of PAPR_PDSM_DIMM_XXXX
* dimm_fuel_gauge : Life remaining of DIMM as a percentage from 0-100
*/
struct nd_papr_pdsm_health {
union {
struct {
__u32 extension_flags;
__u8 dimm_unarmed;
__u8 dimm_bad_shutdown;
__u8 dimm_bad_restore;
__u8 dimm_scrubbed;
__u8 dimm_locked;
__u8 dimm_encrypted;
__u16 dimm_health;
/* Extension flag PDSM_DIMM_HEALTH_RUN_GAUGE_VALID */
__u16 dimm_fuel_gauge;
/* Extension flag PDSM_DIMM_DSC_VALID */
__u64 dimm_dsc;
};
__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
};
};
/* Flags for injecting specific smart errors */
#define PDSM_SMART_INJECT_HEALTH_FATAL (1 << 0)
#define PDSM_SMART_INJECT_BAD_SHUTDOWN (1 << 1)
struct nd_papr_pdsm_smart_inject {
union {
struct {
/* One or more of PDSM_SMART_INJECT_ */
__u32 flags;
__u8 fatal_enable;
__u8 unsafe_shutdown_enable;
};
__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
};
};
/*
* Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel
* via 'nd_cmd_pkg.nd_command' member of the ioctl struct
*/
enum papr_pdsm {
PAPR_PDSM_MIN = 0x0,
PAPR_PDSM_HEALTH,
PAPR_PDSM_SMART_INJECT,
PAPR_PDSM_MAX,
};
/* Maximal union that can hold all possible payload types */
union nd_pdsm_payload {
struct nd_papr_pdsm_health health;
struct nd_papr_pdsm_smart_inject smart_inject;
__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
} __packed;
/*
* PDSM-header + payload expected with ND_CMD_CALL ioctl from libnvdimm
* Valid member of union 'payload' is identified via 'nd_cmd_pkg.nd_command'
* that should always precede this struct when sent to papr_scm via CMD_CALL
* interface.
*/
struct nd_pkg_pdsm {
__s32 cmd_status; /* Out: Sub-cmd status returned back */
__u16 reserved[2]; /* Ignored and to be set as '0' */
union nd_pdsm_payload payload;
} __packed;
#endif /* _UAPI_ASM_POWERPC_PAPR_PDSM_H_ */