Pull the kernel definition of PAPR_SCM DSM command which is located in the proposed kernel tree patches at Ref[1] & [2].
References: [1] "ndctl/papr_scm,uapi: Add support for PAPR nvdimm specific methods" https://lore.kernel.org/linux-nvdimm/[email protected]/ [2] "powerpc/papr_scm: Implement support for PAPR_SCM_PDSM_HEALTH" https://lore.kernel.org/linux-nvdimm/[email protected]/ Signed-off-by: Vaibhav Jain <[email protected]> --- Changelog: v1..v2: * Switched from obsolete papr_scm_dsm.h to recent papr_scm_pdsm.h that describes the ND_CMD_CALL interface between libndctl and papr_scm module. --- ndctl/lib/papr_scm.c | 1 + ndctl/lib/papr_scm_pdsm.h | 192 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 ndctl/lib/papr_scm_pdsm.h diff --git a/ndctl/lib/papr_scm.c b/ndctl/lib/papr_scm.c index 14ff8879f627..57ae943c0260 100644 --- a/ndctl/lib/papr_scm.c +++ b/ndctl/lib/papr_scm.c @@ -17,6 +17,7 @@ #include <ndctl.h> #include <ndctl/libndctl.h> #include <lib/private.h> +#include <papr_scm_pdsm.h> static bool papr_cmd_is_supported(struct ndctl_dimm *dimm, int cmd) { diff --git a/ndctl/lib/papr_scm_pdsm.h b/ndctl/lib/papr_scm_pdsm.h new file mode 100644 index 000000000000..f387ed3958bb --- /dev/null +++ b/ndctl/lib/papr_scm_pdsm.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * PAPR-SCM Dimm specific methods (PDSM) and structs for libndctl + * + * (C) Copyright IBM 2020 + * + * Author: Vaibhav Jain <vaibhav at linux.ibm.com> + */ + +#ifndef _UAPI_ASM_POWERPC_PAPR_SCM_PDSM_H_ +#define _UAPI_ASM_POWERPC_PAPR_SCM_PDSM_H_ + +#include <linux/types.h> + +#ifdef __KERNEL__ +#include <linux/ndctl.h> +#else +#include <ndctl.h> +#endif + +/* + * PDSM Envelope: + * + * The ioctl ND_CMD_CALL transfers data between user-space and kernel via + * 'envelopes' which consists of a header and user-defined payload sections. + * The header is described by 'struct nd_pdsm_cmd_pkg' which expects a + * payload following it and offset of which relative to the struct is provided + * by 'nd_pdsm_cmd_pkg.payload_offset'. * + * + * +-------------+---------------------+---------------------------+ + * | 64-Bytes | 8-Bytes | Max 184-Bytes | + * +-------------+---------------------+---------------------------+ + * | nd_pdsm_cmd_pkg | | + * |-------------+ | | + * | nd_cmd_pkg | | | + * +-------------+---------------------+---------------------------+ + * | nd_family | | | + * | nd_size_out | cmd_status | | + * | nd_size_in | payload_version | PAYLOAD | + * | nd_command | payload_offset -----> | + * | nd_fw_size | | | + * +-------------+---------------------+---------------------------+ + * + * PDSM Header: + * + * The header is defined as 'struct nd_pdsm_cmd_pkg' which embeds a + * 'struct nd_cmd_pkg' instance. The PDSM command is assigned to member + * 'nd_cmd_pkg.nd_command'. Apart from size information of the envelope which is + * contained in 'struct nd_cmd_pkg', the header also has members following + * members: + * + * 'cmd_status' : (Out) Errors if any encountered while servicing PDSM. + * 'payload_version' : (In/Out) Version number associated with the payload. + * 'payload_offset' : (In)Relative offset of payload from start of envelope. + * + * 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. During + * servicing of a PDSM the papr_scm module will read input args from the payload + * field by casting its contents to an appropriate struct pointer based on the + * PDSM command. Similarly the output of servicing the PDSM command will be + * copied to the payload field using the same struct. + * + * 'libnvdimm' enforces a hard limit of 256 bytes on the envelope size, which + * leaves around 184 bytes for the envelope payload (ignoring any padding that + * the compiler may silently introduce). + * + * Payload Version: + * + * A 'payload_version' field is present in PDSM header that indicates a specific + * version of the structure present in PDSM Payload for a given PDSM command. + * This provides backward compatibility in case the PDSM Payload structure + * evolves and different structures are supported by 'papr_scm' and 'libndctl'. + * + * When sending a PDSM Payload to 'papr_scm', 'libndctl' should send the version + * of the payload struct it supports via 'payload_version' field. The 'papr_scm' + * module when servicing the PDSM envelope checks the 'payload_version' and then + * uses 'payload struct version' == MIN('payload_version field', + * 'max payload-struct-version supported by papr_scm') to service the PDSM. + * After servicing the PDSM, 'papr_scm' put the negotiated version of payload + * struct in returned 'payload_version' field. + * + * Libndctl on receiving the envelope back from papr_scm again checks the + * 'payload_version' field and based on it use the appropriate version dsm + * struct to parse the results. + * + * Backward Compatibility: + * + * Above scheme of exchanging different versioned PDSM struct between libndctl + * and papr_scm should provide backward compatibility until following two + * assumptions/conditions when defining new PDSM structs hold: + * + * Let T(X) = { set of attributes in PDSM struct 'T' versioned X } + * + * 1. T(X) is a proper subset of T(Y) if X > Y. + * i.e Each new version of PDSM struct should retain existing struct + * attributes from previous version + * + * 2. If an entity (libndctl or papr_scm) supports a PDSM struct T(X) then + * it should also support T(1), T(2)...T(X - 1). + * i.e When adding support for new version of a PDSM struct, libndctl + * and papr_scm should retain support of the existing PDSM struct + * version they support. + */ + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +/* Papr-scm-header + payload expected with ND_CMD_CALL ioctl from libnvdimm */ +struct nd_pdsm_cmd_pkg { + struct nd_cmd_pkg hdr; /* Package header containing sub-cmd */ + __s32 cmd_status; /* Out: Sub-cmd status returned back */ + __u16 payload_offset; /* In: offset from start of struct */ + __u16 payload_version; /* In/Out: version of the payload */ + __u8 payload[]; /* In/Out: Sub-cmd data buffer */ +} __packed; + +/* + * Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel + * via 'nd_pdsm_cmd_pkg.hdr.nd_command' member of the ioctl struct + */ +enum papr_scm_pdsm { + PAPR_SCM_PDSM_MIN = 0x0, + PAPR_SCM_PDSM_HEALTH, + PAPR_SCM_PDSM_MAX, +}; + +/* Helpers to evaluate the size of PDSM envelope */ +/* Calculate the papr_scm-header size */ +#define ND_PDSM_ENVELOPE_CONTENT_HDR_SIZE \ + (sizeof(struct nd_pdsm_cmd_pkg) - sizeof(struct nd_cmd_pkg)) + +/* Given a type calculate envelope-content size (papr_scm-header + payload) */ +#define ND_PDSM_ENVELOPE_CONTENT_SIZE(_type_) \ + (sizeof(_type_) + ND_PDSM_ENVELOPE_CONTENT_HDR_SIZE) + +/* Convert a libnvdimm nd_cmd_pkg to pdsm specific pkg */ +static struct nd_pdsm_cmd_pkg *nd_to_pdsm_cmd_pkg(struct nd_cmd_pkg *cmd) +{ + return (struct nd_pdsm_cmd_pkg *) cmd; +} + +/* Return the payload pointer for a given pcmd */ +static void *pdsm_cmd_to_payload(struct nd_pdsm_cmd_pkg *pcmd) +{ + if (pcmd->hdr.nd_size_in == 0 && pcmd->hdr.nd_size_out == 0) + return NULL; + else + return (void *)((__u8 *) pcmd + pcmd->payload_offset); +} + +/* Various scm-dimm 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 exchanged between kernel & ndctl in for PAPR_SCM_PDSM_HEALTH + * Various flags indicate the health status of the dimm. + * + * 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 + */ +struct nd_papr_pdsm_health_v1 { + __u8 dimm_unarmed; + __u8 dimm_bad_shutdown; + __u8 dimm_bad_restore; + __u8 dimm_scrubbed; + __u8 dimm_locked; + __u8 dimm_encrypted; + __u16 dimm_health; +} __packed; + +/* + * Typedef the current struct for dimm_health so that any application + * or kernel recompiled after introducing a new version automatically + * supports the new version. + */ +#define nd_papr_pdsm_health nd_papr_pdsm_health_v1 + +/* Current version number for the dimm health struct */ +#define ND_PAPR_PDSM_HEALTH_VERSION 1 + +#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_PDSM_H_ */ -- 2.25.3 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
