* [PATCH v5 4/4] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
From: Vaibhav Jain @ 2020-03-31 14:32 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com>
This patch implements support for papr_scm command
'DSM_PAPR_SCM_HEALTH' that returns a newly introduced 'struct
nd_papr_scm_dimm_health_stat' instance containing dimm health
information back to user space in response to ND_CMD_CALL. This
functionality is implemented in newly introduced papr_scm_get_health()
that queries the scm-dimm health information and then copies these bitmaps
to the package payload whose layout is defined by 'struct
papr_scm_ndctl_health'.
The patch also introduces a new member a new member 'struct
papr_scm_priv.health' thats an instance of 'struct
nd_papr_scm_dimm_health_stat' to cache the health information of a
scm-dimm. As a result functions drc_pmem_query_health() and
papr_flags_show() are updated to populate and use this new struct
instead of two be64 integers that we earlier used.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v4..v5: None
v3..v4: Call the DSM_PAPR_SCM_HEALTH service function from
papr_scm_service_dsm() instead of papr_scm_ndctl(). [Aneesh]
v2..v3: Updated struct nd_papr_scm_dimm_health_stat_v1 to use '__xx'
types as its exported to the userspace [Aneesh]
Changed the constants DSM_PAPR_SCM_DIMM_XX indicating dimm
health from enum to #defines [Aneesh]
v1..v2: New patch in the series
---
arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 40 +++++++
arch/powerpc/platforms/pseries/papr_scm.c | 109 ++++++++++++++++---
2 files changed, 132 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
index c039a49b41b4..8265125304ca 100644
--- a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
+++ b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
@@ -132,6 +132,7 @@ struct nd_papr_scm_cmd_pkg {
*/
enum dsm_papr_scm {
DSM_PAPR_SCM_MIN = 0x10000,
+ DSM_PAPR_SCM_HEALTH,
DSM_PAPR_SCM_MAX,
};
@@ -158,4 +159,43 @@ static void *papr_scm_pcmd_to_payload(struct nd_papr_scm_cmd_pkg *pcmd)
else
return (void *)((__u8 *) pcmd + pcmd->payload_offset);
}
+
+/* Various scm-dimm health indicators */
+#define DSM_PAPR_SCM_DIMM_HEALTHY 0
+#define DSM_PAPR_SCM_DIMM_UNHEALTHY 1
+#define DSM_PAPR_SCM_DIMM_CRITICAL 2
+#define DSM_PAPR_SCM_DIMM_FATAL 3
+
+/*
+ * Struct exchanged between kernel & ndctl in for PAPR_DSM_PAPR_SMART_HEALTH
+ * Various bitflags 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.
+ */
+struct nd_papr_scm_dimm_health_stat_v1 {
+ __u8 dimm_unarmed;
+ __u8 dimm_bad_shutdown;
+ __u8 dimm_bad_restore;
+ __u8 dimm_scrubbed;
+ __u8 dimm_locked;
+ __u8 dimm_encrypted;
+ __u16 dimm_health;
+};
+
+/*
+ * 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_scm_dimm_health_stat nd_papr_scm_dimm_health_stat_v1
+
+/* Current version number for the dimm health struct */
+#define ND_PAPR_SCM_DIMM_HEALTH_VERSION 1
+
#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ */
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index e8ce96d2249e..ce94762954e0 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -47,8 +47,7 @@ struct papr_scm_priv {
struct mutex dimm_mutex;
/* Health information for the dimm */
- __be64 health_bitmap;
- __be64 health_bitmap_valid;
+ struct nd_papr_scm_dimm_health_stat health;
};
static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -158,6 +157,7 @@ static int drc_pmem_query_health(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
int64_t rc;
+ __be64 health;
rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
if (rc != H_SUCCESS) {
@@ -172,13 +172,41 @@ static int drc_pmem_query_health(struct papr_scm_priv *p)
return rc;
/* Store the retrieved health information in dimm platform data */
- p->health_bitmap = ret[0];
- p->health_bitmap_valid = ret[1];
+ health = ret[0] & ret[1];
dev_dbg(&p->pdev->dev,
"Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n",
- be64_to_cpu(p->health_bitmap),
- be64_to_cpu(p->health_bitmap_valid));
+ be64_to_cpu(ret[0]),
+ be64_to_cpu(ret[1]));
+
+ memset(&p->health, 0, sizeof(p->health));
+
+ /* Check for various masks in bitmap and set the buffer */
+ if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ p->health.dimm_unarmed = true;
+
+ if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ p->health.dimm_bad_shutdown = true;
+
+ if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ p->health.dimm_bad_restore = true;
+
+ if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ p->health.dimm_encrypted = true;
+
+ if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED) {
+ p->health.dimm_locked = true;
+ p->health.dimm_scrubbed = true;
+ }
+
+ if (health & PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_UNHEALTHY;
+
+ if (health & PAPR_SCM_DIMM_HEALTH_CRITICAL)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_CRITICAL;
+
+ if (health & PAPR_SCM_DIMM_HEALTH_FATAL)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_FATAL;
mutex_unlock(&p->dimm_mutex);
return 0;
@@ -331,6 +359,51 @@ static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
return 0;
}
+/* Fetch the DIMM health info and populate it in provided package. */
+static int papr_scm_get_health(struct papr_scm_priv *p,
+ struct nd_papr_scm_cmd_pkg *pkg)
+{
+ int rc;
+ size_t copysize = sizeof(p->health);
+
+ rc = drc_pmem_query_health(p);
+ if (rc)
+ goto out;
+ /*
+ * If the requested payload version is greater than one we know
+ * about, return the payload version we know about and let
+ * caller/userspace handle.
+ */
+ if (pkg->payload_version > ND_PAPR_SCM_DIMM_HEALTH_VERSION)
+ pkg->payload_version = ND_PAPR_SCM_DIMM_HEALTH_VERSION;
+
+ if (pkg->hdr.nd_size_out < copysize) {
+ dev_dbg(&p->pdev->dev, "%s Payload not large enough\n",
+ __func__);
+ dev_dbg(&p->pdev->dev, "%s Expected %lu, available %u\n",
+ __func__, copysize, pkg->hdr.nd_size_out);
+ rc = -ENOSPC;
+ goto out;
+ }
+
+ dev_dbg(&p->pdev->dev, "%s Copying payload size=%lu version=0x%x\n",
+ __func__, copysize, pkg->payload_version);
+
+ /* Copy a subset of health struct based on copysize */
+ memcpy(papr_scm_pcmd_to_payload(pkg), &p->health, copysize);
+ pkg->hdr.nd_fw_size = copysize;
+
+out:
+ /*
+ * Put the error in out package and return success from function
+ * so that errors if any are propogated back to userspace.
+ */
+ pkg->cmd_status = rc;
+ dev_dbg(&p->pdev->dev, "%s completion code = %d\n", __func__, rc);
+
+ return 0;
+}
+
static int papr_scm_service_dsm(struct papr_scm_priv *p,
struct nd_papr_scm_cmd_pkg *call_pkg)
{
@@ -345,6 +418,9 @@ static int papr_scm_service_dsm(struct papr_scm_priv *p,
/* Depending on the DSM command call appropriate service routine */
switch (call_pkg->hdr.nd_command) {
+ case DSM_PAPR_SCM_HEALTH:
+ return papr_scm_get_health(p, call_pkg);
+
default:
pr_debug("Unsupported DSM command 0x%llx\n",
call_pkg->hdr.nd_command);
@@ -431,7 +507,6 @@ static ssize_t papr_flags_show(struct device *dev,
{
struct nvdimm *dimm = to_nvdimm(dev);
struct papr_scm_priv *p = nvdimm_provider_data(dimm);
- __be64 health;
int rc;
rc = drc_pmem_query_health(p);
@@ -443,26 +518,26 @@ static ssize_t papr_flags_show(struct device *dev,
if (rc)
return rc;
- health = p->health_bitmap & p->health_bitmap_valid;
-
- /* Check for various masks in bitmap and set the buffer */
- if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ if (p->health.dimm_unarmed)
rc += sprintf(buf, "not_armed ");
- if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ if (p->health.dimm_bad_shutdown)
rc += sprintf(buf + rc, "save_fail ");
- if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ if (p->health.dimm_bad_restore)
rc += sprintf(buf + rc, "restore_fail ");
- if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ if (p->health.dimm_encrypted)
rc += sprintf(buf + rc, "encrypted ");
- if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK)
+ if (p->health.dimm_health)
rc += sprintf(buf + rc, "smart_notify ");
- if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED)
- rc += sprintf(buf + rc, "scrubbed locked ");
+ if (p->health.dimm_scrubbed)
+ rc += sprintf(buf + rc, "scrubbed ");
+
+ if (p->health.dimm_locked)
+ rc += sprintf(buf + rc, "locked ");
if (rc > 0)
rc += sprintf(buf + rc, "\n");
--
2.25.1
^ permalink raw reply related
* [PATCH v5 2/4] ndctl/uapi: Introduce NVDIMM_FAMILY_PAPR_SCM as a new NVDIMM DSM family
From: Vaibhav Jain @ 2020-03-31 14:32 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com>
Add PAPR-scm family of DSM command-set to the white list of NVDIMM
command sets.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v4..v5 : None
v3..v4 : None
v2..v3 : Updated the patch prefix to 'ndctl/uapi' [Aneesh]
v1..v2 : None
---
include/uapi/linux/ndctl.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index de5d90212409..99fb60600ef8 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -244,6 +244,7 @@ struct nd_cmd_pkg {
#define NVDIMM_FAMILY_HPE2 2
#define NVDIMM_FAMILY_MSFT 3
#define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR_SCM 5
#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
struct nd_cmd_pkg)
--
2.25.1
^ permalink raw reply related
* [PATCH v5 0/4] powerpc/papr_scm: Add support for reporting nvdimm health
From: Vaibhav Jain @ 2020-03-31 14:32 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
The PAPR standard[1][3] provides mechanisms to query the health and
performance stats of an NVDIMM via various hcalls as described in Ref[2].
Until now these stats were never available nor exposed to the user-space
tools like 'ndctl'. This is partly due to PAPR platform not having support
for ACPI and NFIT. Hence 'ndctl' is unable to query and report the dimm
health status and a user had no way to determine the current health status
of a NDVIMM.
To overcome this limitation, this patch-set updates papr_scm kernel module
to query and fetch nvdimm health stats using hcalls described in Ref[2].
This health and performance stats are then exposed to userspace via syfs
and Dimm-Specific-Methods(DSM) issued by libndctl.
These changes coupled with proposed ndtcl changes located at Ref[4] should
provide a way for the user to retrieve NVDIMM health status using ndtcl.
Below is a sample output using proposed kernel + ndctl for PAPR NVDIMM in
a emulation environment:
# ndctl list -DH
[
{
"dev":"nmem0",
"health":{
"health_state":"fatal",
"shutdown_state":"dirty"
}
}
]
Dimm health report output on a pseries guest lpar with vPMEM or HMS
based nvdimms that are in perfectly healthy conditions:
# ndctl list -d nmem0 -H
[
{
"dev":"nmem0",
"health":{
"health_state":"ok",
"shutdown_state":"clean"
}
}
]
PAPR Dimm-Specific-Methods(DSM)
================================
As the name suggests DSMs are used by vendor specific code in libndctl to
execute certain operations or fetch certain information for NVDIMMS. DSMs
can be sent to papr_scm module via libndctl (userspace) and libnvdimm
(kernel) using the ND_CMD_CALL ioctl which can be handled in the dimm
control function papr_scm_ndctl(). For PAPR this patchset proposes a single
DSM to retrieve DIMM health, defined in the newly introduced uapi header
named 'papr_scm_dsm.h'. Support for more DSMs will be added in future.
Structure of the patch-set
==========================
The patchset starts with implementing support for fetching nvdimm health
information from PHYP and partially exposing it to user-space via nvdimm
flags.
Second & Third patches deal with implementing support for servicing DSM
commands papr_scm.
Finally the Fourth patch implements support for servicing DSM
'DSM_PAPR_SCM_HEALTH' that returns the nvdimm health information to
libndctl.
Changelog:
==========
v4..v5:
* Fixed a bug in new implementation of papr_scm_ndctl() that was triggering
a false error condition.
v3..v4:
* Restructured papr_scm_ndctl() to dispatch ND_CMD_CALL commands to a new
function named papr_scm_service_dsm() to serivice DSM requests. [Aneesh]
v2..v3:
* Updated the papr_scm_dsm.h header to be more confimant general kernel
guidelines for UAPI headers. [Aneesh]
* Changed the definition of macro PAPR_SCM_DIMM_UNARMED_MASK to not
include case when the nvdimm is unarmed because its a vPMEM
nvdimm. [Aneesh]
v1..v2:
* Restructured the patch-set based on review comments on V1 patch-set to
simplify the patch review. Multiple small patches have been combined into
single patches to reduce cross referencing that was needed in earlier
patch-set. Hence most of the patches in this patch-set as now new. [Aneesh]
* Removed the initial work done for fetch nvdimm performance statistics.
These changes will be re-proposed in a separate patch-set. [Aneesh]
* Simplified handling of versioning of 'struct
nd_papr_scm_dimm_health_stat_v1' as only one version of the structure is
currently in existence.
References:
[1]: "Power Architecture Platform Reference"
https://en.wikipedia.org/wiki/Power_Architecture_Platform_Reference
[2]: commit 58b278f568f0
("powerpc: Provide initial documentation for PAPR hcalls")
[3]: "Linux on Power Architecture Platform Reference"
https://members.openpowerfoundation.org/document/dl/469
[4]: https://patchwork.kernel.org/project/linux-nvdimm/list/?series=244625
Vaibhav Jain (4):
powerpc/papr_scm: Fetch nvdimm health information from PHYP
ndctl/uapi: Introduce NVDIMM_FAMILY_PAPR_SCM as a new NVDIMM DSM
family
powerpc/papr_scm,uapi: Add support for handling PAPR DSM commands
powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
arch/powerpc/include/asm/papr_scm.h | 48 ++++
arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 201 ++++++++++++++
arch/powerpc/platforms/pseries/papr_scm.c | 277 ++++++++++++++++++-
include/uapi/linux/ndctl.h | 1 +
4 files changed, 519 insertions(+), 8 deletions(-)
create mode 100644 arch/powerpc/include/asm/papr_scm.h
create mode 100644 arch/powerpc/include/uapi/asm/papr_scm_dsm.h
--
2.25.1
^ permalink raw reply
* [PATCH v5 1/4] powerpc/papr_scm: Fetch nvdimm health information from PHYP
From: Vaibhav Jain @ 2020-03-31 14:32 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331143229.306718-1-vaibhav@linux.ibm.com>
Implement support for fetching nvdimm health information via
H_SCM_HEALTH hcall as documented in Ref[1]. The hcall returns a pair
of 64-bit big-endian integers which are then stored in 'struct
papr_scm_priv' and subsequently partially exposed to user-space via
newly introduced dimm specific attribute 'papr_flags'. Also a new asm
header named 'papr-scm.h' is added that describes the interface
between PHYP and guest kernel.
Following flags are reported via 'papr_flags' sysfs attribute contents
of which are space separated string flags indicating various nvdimm
states:
* "not_armed" : Indicating that nvdimm contents wont survive a power
cycle.
* "save_fail" : Indicating that nvdimm contents couldn't be flushed
during last shutdown event.
* "restore_fail": Indicating that nvdimm contents couldn't be restored
during dimm initialization.
* "encrypted" : Dimm contents are encrypted.
* "smart_notify": There is health event for the nvdimm.
* "scrubbed" : Indicating that contents of the nvdimm have been
scrubbed.
* "locked" : Indicating that nvdimm contents cant be modified
until next power cycle.
[1]: commit 58b278f568f0 ("powerpc: Provide initial documentation for
PAPR hcalls")
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v4..v5 : None
v3..v4 : None
v2..v3 : Removed PAPR_SCM_DIMM_HEALTH_NON_CRITICAL as a condition for
NVDIMM unarmed [Aneesh]
v1..v2 : New patch in the series.
---
arch/powerpc/include/asm/papr_scm.h | 48 ++++++++++
arch/powerpc/platforms/pseries/papr_scm.c | 105 +++++++++++++++++++++-
2 files changed, 151 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/include/asm/papr_scm.h
diff --git a/arch/powerpc/include/asm/papr_scm.h b/arch/powerpc/include/asm/papr_scm.h
new file mode 100644
index 000000000000..868d3360f56a
--- /dev/null
+++ b/arch/powerpc/include/asm/papr_scm.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Structures and defines needed to manage nvdimms for spapr guests.
+ */
+#ifndef _ASM_POWERPC_PAPR_SCM_H_
+#define _ASM_POWERPC_PAPR_SCM_H_
+
+#include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+/* DIMM health bitmap bitmap indicators */
+/* SCM device is unable to persist memory contents */
+#define PAPR_SCM_DIMM_UNARMED PPC_BIT(0)
+/* SCM device failed to persist memory contents */
+#define PAPR_SCM_DIMM_SHUTDOWN_DIRTY PPC_BIT(1)
+/* SCM device contents are persisted from previous IPL */
+#define PAPR_SCM_DIMM_SHUTDOWN_CLEAN PPC_BIT(2)
+/* SCM device contents are not persisted from previous IPL */
+#define PAPR_SCM_DIMM_EMPTY PPC_BIT(3)
+/* SCM device memory life remaining is critically low */
+#define PAPR_SCM_DIMM_HEALTH_CRITICAL PPC_BIT(4)
+/* SCM device will be garded off next IPL due to failure */
+#define PAPR_SCM_DIMM_HEALTH_FATAL PPC_BIT(5)
+/* SCM contents cannot persist due to current platform health status */
+#define PAPR_SCM_DIMM_HEALTH_UNHEALTHY PPC_BIT(6)
+/* SCM device is unable to persist memory contents in certain conditions */
+#define PAPR_SCM_DIMM_HEALTH_NON_CRITICAL PPC_BIT(7)
+/* SCM device is encrypted */
+#define PAPR_SCM_DIMM_ENCRYPTED PPC_BIT(8)
+/* SCM device has been scrubbed and locked */
+#define PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED PPC_BIT(9)
+
+/* Bits status indicators for health bitmap indicating unarmed dimm */
+#define PAPR_SCM_DIMM_UNARMED_MASK (PAPR_SCM_DIMM_UNARMED | \
+ PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+
+/* Bits status indicators for health bitmap indicating unflushed dimm */
+#define PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK (PAPR_SCM_DIMM_SHUTDOWN_DIRTY)
+
+/* Bits status indicators for health bitmap indicating unrestored dimm */
+#define PAPR_SCM_DIMM_BAD_RESTORE_MASK (PAPR_SCM_DIMM_EMPTY)
+
+/* Bit status indicators for smart event notification */
+#define PAPR_SCM_DIMM_SMART_EVENT_MASK (PAPR_SCM_DIMM_HEALTH_CRITICAL | \
+ PAPR_SCM_DIMM_HEALTH_FATAL | \
+ PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 0b4467e378e5..aaf2e4ab1f75 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <asm/plpar_wrappers.h>
+#include <asm/papr_scm.h>
#define BIND_ANY_ADDR (~0ul)
@@ -39,6 +40,13 @@ struct papr_scm_priv {
struct resource res;
struct nd_region *region;
struct nd_interleave_set nd_set;
+
+ /* Protect dimm data from concurrent access */
+ struct mutex dimm_mutex;
+
+ /* Health information for the dimm */
+ __be64 health_bitmap;
+ __be64 health_bitmap_valid;
};
static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -144,6 +152,35 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
return drc_pmem_bind(p);
}
+static int drc_pmem_query_health(struct papr_scm_priv *p)
+{
+ unsigned long ret[PLPAR_HCALL_BUFSIZE];
+ int64_t rc;
+
+ rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
+ if (rc != H_SUCCESS) {
+ dev_err(&p->pdev->dev,
+ "Failed to query health information, Err:%lld\n", rc);
+ return -ENXIO;
+ }
+
+ /* Protect modifications to papr_scm_priv with the mutex */
+ rc = mutex_lock_interruptible(&p->dimm_mutex);
+ if (rc)
+ return rc;
+
+ /* Store the retrieved health information in dimm platform data */
+ p->health_bitmap = ret[0];
+ p->health_bitmap_valid = ret[1];
+
+ dev_dbg(&p->pdev->dev,
+ "Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n",
+ be64_to_cpu(p->health_bitmap),
+ be64_to_cpu(p->health_bitmap_valid));
+
+ mutex_unlock(&p->dimm_mutex);
+ return 0;
+}
static int papr_scm_meta_get(struct papr_scm_priv *p,
struct nd_cmd_get_config_data_hdr *hdr)
@@ -304,6 +341,67 @@ static inline int papr_scm_node(int node)
return min_node;
}
+static ssize_t papr_flags_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvdimm *dimm = to_nvdimm(dev);
+ struct papr_scm_priv *p = nvdimm_provider_data(dimm);
+ __be64 health;
+ int rc;
+
+ rc = drc_pmem_query_health(p);
+ if (rc)
+ return rc;
+
+ /* Protect against modifications to papr_scm_priv with the mutex */
+ rc = mutex_lock_interruptible(&p->dimm_mutex);
+ if (rc)
+ return rc;
+
+ health = p->health_bitmap & p->health_bitmap_valid;
+
+ /* Check for various masks in bitmap and set the buffer */
+ if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ rc += sprintf(buf, "not_armed ");
+
+ if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ rc += sprintf(buf + rc, "save_fail ");
+
+ if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ rc += sprintf(buf + rc, "restore_fail ");
+
+ if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ rc += sprintf(buf + rc, "encrypted ");
+
+ if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK)
+ rc += sprintf(buf + rc, "smart_notify ");
+
+ if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED)
+ rc += sprintf(buf + rc, "scrubbed locked ");
+
+ if (rc > 0)
+ rc += sprintf(buf + rc, "\n");
+
+ mutex_unlock(&p->dimm_mutex);
+ return rc;
+}
+DEVICE_ATTR_RO(papr_flags);
+
+/* papr_scm specific dimm attributes */
+static struct attribute *papr_scm_nd_attributes[] = {
+ &dev_attr_papr_flags.attr,
+ NULL,
+};
+
+static struct attribute_group papr_scm_nd_attribute_group = {
+ .attrs = papr_scm_nd_attributes,
+};
+
+static const struct attribute_group *papr_scm_dimm_attr_groups[] = {
+ &papr_scm_nd_attribute_group,
+ NULL,
+};
+
static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
{
struct device *dev = &p->pdev->dev;
@@ -330,8 +428,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
dimm_flags = 0;
set_bit(NDD_ALIASING, &dimm_flags);
- p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
- PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
+ p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_attr_groups,
+ dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
if (!p->nvdimm) {
dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
goto err;
@@ -415,6 +513,9 @@ static int papr_scm_probe(struct platform_device *pdev)
if (!p)
return -ENOMEM;
+ /* Initialize the dimm mutex */
+ mutex_init(&p->dimm_mutex);
+
/* optional DT properties */
of_property_read_u32(dn, "ibm,metadata-size", &metadata_size);
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v3 0/5] mm: Enable CONFIG_NODES_SPAN_OTHER_NODES by default for NUMA
From: Baoquan He @ 2020-03-31 14:31 UTC (permalink / raw)
To: Michal Hocko
Cc: mmorana, Catalin Marinas, Heiko Carstens,
open list:MEMORY MANAGEMENT, Paul Mackerras, H. Peter Anvin,
sparclinux, Alexander Duyck, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, Hoan Tran, Pavel Tatashin,
lho, Vasily Gorbik, Vlastimil Babka, Will Deacon, Borislav Petkov,
Thomas Gleixner, linux-arm-kernel, Oscar Salvador, linux-kernel,
Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200331142138.GL30449@dhcp22.suse.cz>
On 03/31/20 at 04:21pm, Michal Hocko wrote:
> On Tue 31-03-20 22:03:32, Baoquan He wrote:
> > Hi Michal,
> >
> > On 03/31/20 at 10:55am, Michal Hocko wrote:
> > > On Tue 31-03-20 11:14:23, Mike Rapoport wrote:
> > > > Maybe I mis-read the code, but I don't see how this could happen. In the
> > > > HAVE_MEMBLOCK_NODE_MAP=y case, free_area_init_node() calls
> > > > calculate_node_totalpages() that ensures that node->node_zones are entirely
> > > > within the node because this is checked in zone_spanned_pages_in_node().
> > >
> > > zone_spanned_pages_in_node does chech the zone boundaries are within the
> > > node boundaries. But that doesn't really tell anything about other
> > > potential zones interleaving with the physical memory range.
> > > zone->spanned_pages simply gives the physical range for the zone
> > > including holes. Interleaving nodes are essentially a hole
> > > (__absent_pages_in_range is going to skip those).
> > >
> > > That means that when free_area_init_core simply goes over the whole
> > > physical zone range including holes and that is why we need to check
> > > both for physical and logical holes (aka other nodes).
> > >
> > > The life would be so much easier if the whole thing would simply iterate
> > > over memblocks...
> >
> > The memblock iterating sounds a great idea. I tried with putting the
> > memblock iterating in the upper layer, memmap_init(), which is used for
> > boot mem only anyway. Do you think it's doable and OK? It yes, I can
> > work out a formal patch to make this simpler as you said. The draft code
> > is as below. Like this it uses the existing code and involves little change.
>
> Doing this would be a step in the right direction! I haven't checked the
> code very closely though. The below sounds way too simple to be truth I
> am afraid. First for_each_mem_pfn_range is available only for
> CONFIG_HAVE_MEMBLOCK_NODE_MAP (which is one of the reasons why I keep
> saying that I really hate that being conditional). Also I haven't really
> checked the deferred initialization path - I have a very vague
> recollection that it has been converted to the memblock api but I have
> happilly dropped all that memory.
Thanks for your quick response and pointing out the rest suspect aspects,
I will investigate what you mentioned, see if they impact.
>
> > diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> > index 138a56c0f48f..558d421f294b 100644
> > --- a/mm/page_alloc.c
> > +++ b/mm/page_alloc.c
> > @@ -6007,14 +6007,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
> > * function. They do not exist on hotplugged memory.
> > */
> > if (context == MEMMAP_EARLY) {
> > - if (!early_pfn_valid(pfn)) {
> > - pfn = next_pfn(pfn);
> > - continue;
> > - }
> > - if (!early_pfn_in_nid(pfn, nid)) {
> > - pfn++;
> > - continue;
> > - }
> > if (overlap_memmap_init(zone, &pfn))
> > continue;
> > if (defer_init(nid, pfn, end_pfn))
> > @@ -6130,9 +6122,17 @@ static void __meminit zone_init_free_lists(struct zone *zone)
> > }
> >
> > void __meminit __weak memmap_init(unsigned long size, int nid,
> > - unsigned long zone, unsigned long start_pfn)
> > + unsigned long zone, unsigned long range_start_pfn)
> > {
> > - memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
> > + unsigned long start_pfn, end_pfn;
> > + unsigned long range_end_pfn = range_start_pfn + size;
> > + int i;
> > + for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
> > + start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
> > + end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
> > + if (end_pfn > start_pfn)
> > + memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
> > + }
> > }
> >
> > static int zone_batchsize(struct zone *zone)
>
> --
> Michal Hocko
> SUSE Labs
>
^ permalink raw reply
* Re: [PATCH v3 0/5] mm: Enable CONFIG_NODES_SPAN_OTHER_NODES by default for NUMA
From: Michal Hocko @ 2020-03-31 14:21 UTC (permalink / raw)
To: Baoquan He
Cc: mmorana, Catalin Marinas, Heiko Carstens,
open list:MEMORY MANAGEMENT, Paul Mackerras, H. Peter Anvin,
sparclinux, Alexander Duyck, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, Hoan Tran, Pavel Tatashin,
lho, Vasily Gorbik, Vlastimil Babka, Will Deacon, Borislav Petkov,
Thomas Gleixner, linux-arm-kernel, Oscar Salvador, linux-kernel,
Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200331140332.GA2129@MiWiFi-R3L-srv>
On Tue 31-03-20 22:03:32, Baoquan He wrote:
> Hi Michal,
>
> On 03/31/20 at 10:55am, Michal Hocko wrote:
> > On Tue 31-03-20 11:14:23, Mike Rapoport wrote:
> > > Maybe I mis-read the code, but I don't see how this could happen. In the
> > > HAVE_MEMBLOCK_NODE_MAP=y case, free_area_init_node() calls
> > > calculate_node_totalpages() that ensures that node->node_zones are entirely
> > > within the node because this is checked in zone_spanned_pages_in_node().
> >
> > zone_spanned_pages_in_node does chech the zone boundaries are within the
> > node boundaries. But that doesn't really tell anything about other
> > potential zones interleaving with the physical memory range.
> > zone->spanned_pages simply gives the physical range for the zone
> > including holes. Interleaving nodes are essentially a hole
> > (__absent_pages_in_range is going to skip those).
> >
> > That means that when free_area_init_core simply goes over the whole
> > physical zone range including holes and that is why we need to check
> > both for physical and logical holes (aka other nodes).
> >
> > The life would be so much easier if the whole thing would simply iterate
> > over memblocks...
>
> The memblock iterating sounds a great idea. I tried with putting the
> memblock iterating in the upper layer, memmap_init(), which is used for
> boot mem only anyway. Do you think it's doable and OK? It yes, I can
> work out a formal patch to make this simpler as you said. The draft code
> is as below. Like this it uses the existing code and involves little change.
Doing this would be a step in the right direction! I haven't checked the
code very closely though. The below sounds way too simple to be truth I
am afraid. First for_each_mem_pfn_range is available only for
CONFIG_HAVE_MEMBLOCK_NODE_MAP (which is one of the reasons why I keep
saying that I really hate that being conditional). Also I haven't really
checked the deferred initialization path - I have a very vague
recollection that it has been converted to the memblock api but I have
happilly dropped all that memory.
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 138a56c0f48f..558d421f294b 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -6007,14 +6007,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
> * function. They do not exist on hotplugged memory.
> */
> if (context == MEMMAP_EARLY) {
> - if (!early_pfn_valid(pfn)) {
> - pfn = next_pfn(pfn);
> - continue;
> - }
> - if (!early_pfn_in_nid(pfn, nid)) {
> - pfn++;
> - continue;
> - }
> if (overlap_memmap_init(zone, &pfn))
> continue;
> if (defer_init(nid, pfn, end_pfn))
> @@ -6130,9 +6122,17 @@ static void __meminit zone_init_free_lists(struct zone *zone)
> }
>
> void __meminit __weak memmap_init(unsigned long size, int nid,
> - unsigned long zone, unsigned long start_pfn)
> + unsigned long zone, unsigned long range_start_pfn)
> {
> - memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
> + unsigned long start_pfn, end_pfn;
> + unsigned long range_end_pfn = range_start_pfn + size;
> + int i;
> + for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
> + start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
> + end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
> + if (end_pfn > start_pfn)
> + memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
> + }
> }
>
> static int zone_batchsize(struct zone *zone)
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* Re: [PATCH v3 0/5] mm: Enable CONFIG_NODES_SPAN_OTHER_NODES by default for NUMA
From: Baoquan He @ 2020-03-31 14:03 UTC (permalink / raw)
To: Michal Hocko
Cc: mmorana, Catalin Marinas, Heiko Carstens,
open list:MEMORY MANAGEMENT, Paul Mackerras, H. Peter Anvin,
sparclinux, Alexander Duyck, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, Hoan Tran, Pavel Tatashin,
lho, Vasily Gorbik, Vlastimil Babka, Will Deacon, Borislav Petkov,
Thomas Gleixner, linux-arm-kernel, Oscar Salvador, linux-kernel,
Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200331085513.GE30449@dhcp22.suse.cz>
Hi Michal,
On 03/31/20 at 10:55am, Michal Hocko wrote:
> On Tue 31-03-20 11:14:23, Mike Rapoport wrote:
> > Maybe I mis-read the code, but I don't see how this could happen. In the
> > HAVE_MEMBLOCK_NODE_MAP=y case, free_area_init_node() calls
> > calculate_node_totalpages() that ensures that node->node_zones are entirely
> > within the node because this is checked in zone_spanned_pages_in_node().
>
> zone_spanned_pages_in_node does chech the zone boundaries are within the
> node boundaries. But that doesn't really tell anything about other
> potential zones interleaving with the physical memory range.
> zone->spanned_pages simply gives the physical range for the zone
> including holes. Interleaving nodes are essentially a hole
> (__absent_pages_in_range is going to skip those).
>
> That means that when free_area_init_core simply goes over the whole
> physical zone range including holes and that is why we need to check
> both for physical and logical holes (aka other nodes).
>
> The life would be so much easier if the whole thing would simply iterate
> over memblocks...
The memblock iterating sounds a great idea. I tried with putting the
memblock iterating in the upper layer, memmap_init(), which is used for
boot mem only anyway. Do you think it's doable and OK? It yes, I can
work out a formal patch to make this simpler as you said. The draft code
is as below. Like this it uses the existing code and involves little change.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 138a56c0f48f..558d421f294b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6007,14 +6007,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
* function. They do not exist on hotplugged memory.
*/
if (context == MEMMAP_EARLY) {
- if (!early_pfn_valid(pfn)) {
- pfn = next_pfn(pfn);
- continue;
- }
- if (!early_pfn_in_nid(pfn, nid)) {
- pfn++;
- continue;
- }
if (overlap_memmap_init(zone, &pfn))
continue;
if (defer_init(nid, pfn, end_pfn))
@@ -6130,9 +6122,17 @@ static void __meminit zone_init_free_lists(struct zone *zone)
}
void __meminit __weak memmap_init(unsigned long size, int nid,
- unsigned long zone, unsigned long start_pfn)
+ unsigned long zone, unsigned long range_start_pfn)
{
- memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
+ unsigned long start_pfn, end_pfn;
+ unsigned long range_end_pfn = range_start_pfn + size;
+ int i;
+ for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
+ start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
+ end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
+ if (end_pfn > start_pfn)
+ memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL);
+ }
}
static int zone_batchsize(struct zone *zone)
^ permalink raw reply related
* [PATCH v2] powerpc/perf: Add documentation around use of "ppc_set_pmu_inuse" in PMU core-book3s
From: Athira Rajeev @ 2020-03-31 12:43 UTC (permalink / raw)
To: mpe; +Cc: maddy, linuxppc-dev
From: Madhavan Srinivasan <maddy@linux.ibm.com>
"pmcregs_in_use" flag is part of lppaca (Virtual Process Area),
which is used to indicate whether Performance Monitoring Unit (PMU) and
PMU sprs are in-use and whether should it be saved/restored by
hypervisor. ppc_set_pmu_inuse() is used to set/unset the VPA
flag "pmcregs_in_use". "pmcregs_in_use" flag is set in
"power_pmu_enable" via ppc_set_pmu_inuse(1) and it is unset
when there are no active events (n_events == 0 condition).
Patch here adds documentation on the ppc_set_pmu_inuse() usage.
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
---
Changes in v2:
- Corrected the patch author information
arch/powerpc/perf/core-book3s.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 3086055..48bfdc9 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1285,6 +1285,11 @@ static void power_pmu_enable(struct pmu *pmu)
goto out;
if (cpuhw->n_events == 0) {
+ /*
+ * Indicate PMU not in-use to Hypervisor.
+ * We end-up here via "ctx_sched_out()" from common code and
+ * "power_pmu_del()".
+ */
ppc_set_pmu_inuse(0);
goto out;
}
@@ -1341,6 +1346,11 @@ static void power_pmu_enable(struct pmu *pmu)
* Write the new configuration to MMCR* with the freeze
* bit set and set the hardware events to their initial values.
* Then unfreeze the events.
+ * ppc_set_pmu_inuse(1): "power_pmu_enable" will unset the
+ * "pmcregs_in_use" flag when a previous profiling/sampling session
+ * is completed and un-setting of flag will notify the Hypervisor to
+ * drop save/restore of PMU sprs. Now that PMU need to be enabled, first
+ * set the "pmcregs_in_use" flag in VPA.
*/
ppc_set_pmu_inuse(1);
mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] powerpc/perf: Add documentation around use of "ppc_set_pmu_inuse" in PMU core-book3s
From: Athira Rajeev @ 2020-03-31 12:43 UTC (permalink / raw)
To: Michael Ellerman; +Cc: maddy, linuxppc-dev
In-Reply-To: <1585568332-11934-1-git-send-email-atrajeev@linux.vnet.ibm.com>
Hi,
Please ignore this version as I messed up with the author information. I am sending a V2 with the proper author name.
Thanks
Athira
> On 30-Mar-2020, at 5:08 PM, Athira Rajeev <atrajeev@linux.vnet.ibm.com> wrote:
>
> "pmcregs_in_use" flag is part of lppaca (Virtual Process Area),
> which is used to indicate whether Performance Monitoring Unit (PMU) and
> PMU sprs are in-use and whether should it be saved/restored by
> hypervisor. ppc_set_pmu_inuse() is used to set/unset the VPA
> flag "pmcregs_in_use". "pmcregs_in_use" flag is set in
> "power_pmu_enable" via ppc_set_pmu_inuse(1) and it is unset
> when there are no active events (n_events == 0 condition).
>
> Patch here adds documentation on the ppc_set_pmu_inuse() usage.
>
> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
> Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
> ---
> arch/powerpc/perf/core-book3s.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
> index 3086055..48bfdc9 100644
> --- a/arch/powerpc/perf/core-book3s.c
> +++ b/arch/powerpc/perf/core-book3s.c
> @@ -1285,6 +1285,11 @@ static void power_pmu_enable(struct pmu *pmu)
> goto out;
>
> if (cpuhw->n_events == 0) {
> + /*
> + * Indicate PMU not in-use to Hypervisor.
> + * We end-up here via "ctx_sched_out()" from common code and
> + * "power_pmu_del()".
> + */
> ppc_set_pmu_inuse(0);
> goto out;
> }
> @@ -1341,6 +1346,11 @@ static void power_pmu_enable(struct pmu *pmu)
> * Write the new configuration to MMCR* with the freeze
> * bit set and set the hardware events to their initial values.
> * Then unfreeze the events.
> + * ppc_set_pmu_inuse(1): "power_pmu_enable" will unset the
> + * "pmcregs_in_use" flag when a previous profiling/sampling session
> + * is completed and un-setting of flag will notify the Hypervisor to
> + * drop save/restore of PMU sprs. Now that PMU need to be enabled, first
> + * set the "pmcregs_in_use" flag in VPA.
> */
> ppc_set_pmu_inuse(1);
> mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
> --
> 1.8.3.1
>
^ permalink raw reply
* Re: [PATCH V2 0/3] mm/debug: Add more arch page table helper tests
From: Gerald Schaefer @ 2020-03-31 12:30 UTC (permalink / raw)
To: Anshuman Khandual
Cc: linux-doc, Heiko Carstens, linux-mm, Paul Mackerras,
H. Peter Anvin, linux-riscv, Will Deacon, linux-arch, linux-s390,
Jonathan Corbet, x86, Mike Rapoport, Christian Borntraeger,
Ingo Molnar, Catalin Marinas, linux-snps-arc, Vasily Gorbik,
Borislav Petkov, Paul Walmsley, Kirill A . Shutemov,
Thomas Gleixner, linux-arm-kernel, Vineet Gupta, linux-kernel,
Palmer Dabbelt, Andrew Morton, linuxppc-dev
In-Reply-To: <1585027375-9997-1-git-send-email-anshuman.khandual@arm.com>
On Tue, 24 Mar 2020 10:52:52 +0530
Anshuman Khandual <anshuman.khandual@arm.com> wrote:
> This series adds more arch page table helper tests. The new tests here are
> either related to core memory functions and advanced arch pgtable helpers.
> This also creates a documentation file enlisting all expected semantics as
> suggested by Mike Rapoport (https://lkml.org/lkml/2020/1/30/40).
>
> This series has been tested on arm64 and x86 platforms. There is just one
> expected failure on arm64 that will be fixed when we enable THP migration.
>
> [ 21.741634] WARNING: CPU: 0 PID: 1 at mm/debug_vm_pgtable.c:782
>
> which corresponds to
>
> WARN_ON(!pmd_present(pmd_mknotpresent(pmd_mkhuge(pmd))))
>
> There are many TRANSPARENT_HUGEPAGE and ARCH_HAS_TRANSPARENT_HUGEPAGE_PUD
> ifdefs scattered across the test. But consolidating all the fallback stubs
> is not very straight forward because ARCH_HAS_TRANSPARENT_HUGEPAGE_PUD is
> not explicitly dependent on ARCH_HAS_TRANSPARENT_HUGEPAGE.
>
> This series has been build tested on many platforms including the ones that
> subscribe the test through ARCH_HAS_DEBUG_VM_PGTABLE.
>
Hi Anshuman,
thanks for the update. There are a couple of issues on s390, some might
also affect other archs.
1) The pxd_huge_tests are using pxd_set/clear_huge, which defaults to
returning 0 if !CONFIG_HAVE_ARCH_HUGE_VMAP. As result, the checks for
!pxd_test/clear_huge in the pxd_huge_tests will always trigger the
warning. This should affect all archs w/o CONFIG_HAVE_ARCH_HUGE_VMAP.
Could be fixed like this:
@@ -923,8 +923,10 @@ void __init debug_vm_pgtable(void)
pmd_leaf_tests(pmd_aligned, prot);
pud_leaf_tests(pud_aligned, prot);
- pmd_huge_tests(pmdp, pmd_aligned, prot);
- pud_huge_tests(pudp, pud_aligned, prot);
+ if (IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP)) {
+ pmd_huge_tests(pmdp, pmd_aligned, prot);
+ pud_huge_tests(pudp, pud_aligned, prot);
+ }
pte_savedwrite_tests(pte_aligned, prot);
pmd_savedwrite_tests(pmd_aligned, prot);
BTW, please add some comments to the various #ifdef/#else stuff, especially
when the different parts are far away and/or nested.
2) The hugetlb_advanced_test will fail because it directly de-references
huge *ptep pointers instead of using huge_ptep_get() for this. We have
very different pagetable entry layout for pte and (large) pmd on s390,
and unfortunately the whole hugetlbfs code is using pte_t instead of pmd_t
like THP. For this reason, huge_ptep_get() was introduced, which will
return a "converted" pte, because directly reading from a *ptep (pointing
to a large pmd) will not return a proper pte. Only ARM has also an
implementation of huge_ptep_get(), so they could be affected, depending
on what exactly they need it for.
Could be fixed like this (the first de-reference is a bit special,
because at that point *ptep does not really point to a large (pmd) entry
yet, it is initially an invalid pte entry, which breaks our huge_ptep_get()
conversion logic. I also added PMD_MASK alignment for RANDOM_ORVALUE,
because we do have some special bits there in our large pmds. It seems
to also work w/o that alignment, but it feels a bit wrong):
@@ -731,26 +731,26 @@ static void __init hugetlb_advanced_test
unsigned long vaddr, pgprot_t prot)
{
struct page *page = pfn_to_page(pfn);
- pte_t pte = READ_ONCE(*ptep);
+ pte_t pte;
- pte = __pte(pte_val(pte) | RANDOM_ORVALUE);
+ pte = pte_mkhuge(mk_pte_phys(RANDOM_ORVALUE & PMD_MASK, prot));
set_huge_pte_at(mm, vaddr, ptep, pte);
barrier();
WARN_ON(!pte_same(pte, huge_ptep_get(ptep)));
huge_pte_clear(mm, vaddr, ptep, PMD_SIZE);
- pte = READ_ONCE(*ptep);
+ pte = huge_ptep_get(ptep);
WARN_ON(!huge_pte_none(pte));
pte = mk_huge_pte(page, prot);
set_huge_pte_at(mm, vaddr, ptep, pte);
huge_ptep_set_wrprotect(mm, vaddr, ptep);
- pte = READ_ONCE(*ptep);
+ pte = huge_ptep_get(ptep);
WARN_ON(huge_pte_write(pte));
pte = mk_huge_pte(page, prot);
set_huge_pte_at(mm, vaddr, ptep, pte);
huge_ptep_get_and_clear(mm, vaddr, ptep);
- pte = READ_ONCE(*ptep);
+ pte = huge_ptep_get(ptep);
WARN_ON(!huge_pte_none(pte));
pte = mk_huge_pte(page, prot);
@@ -759,7 +759,7 @@ static void __init hugetlb_advanced_test
pte = huge_pte_mkwrite(pte);
pte = huge_pte_mkdirty(pte);
huge_ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
- pte = READ_ONCE(*ptep);
+ pte = huge_ptep_get(ptep);
WARN_ON(!(huge_pte_write(pte) && huge_pte_dirty(pte)));
}
#else
3) The pmd_protnone_tests() has an issue, because it passes a pmd to
pmd_protnone() which has not been marked as large. We check for large
pmd in the s390 implementation of pmd_protnone(), and will fail if a
pmd is not large. We had similar issues before, in other helpers, where
I changed the logic on s390 to not require the pmd large check, but I'm
not so sure in this case. Is there a valid use case for doing
pmd_protnone() on "normal" pmds? Or could this be changed like this:
@@ -537,7 +537,7 @@ static void __init pte_protnone_tests(un
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot)
{
- pmd_t pmd = pfn_pmd(pfn, prot);
+ pmd_t pmd = mk_huge_pmd(pfn_to_page(pfn), prot);
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
return;
Regards,
Gerald
^ permalink raw reply
* Re: [RFC/PATCH 0/3] Add support for stop instruction inside KVM guest
From: Gautham R Shenoy @ 2020-03-31 12:14 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: Michael Neuling, Nicholas Piggin, Bharata B Rao, linuxppc-dev,
kvm-ppc, Vaidyanathan Srinivasan, linuxppc-dev, David Gibson
In-Reply-To: <1585656658-1838-1-git-send-email-ego@linux.vnet.ibm.com>
On Tue, Mar 31, 2020 at 05:40:55PM +0530, Gautham R. Shenoy wrote:
> From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
>
>
> *** RFC Only. Not intended for inclusion ************
>
> Motivation
> ~~~~~~~~~~~~~~~
>
> The POWER ISA v3.0 allows stop instruction to be executed from a Guest
> Kernel (HV=0,PR=0) context. If the hypervisor has cleared
> PSSCR[ESL|EC] bits, then the stop instruction thus executed will cause
> the vCPU thread to "pause", thereby donating its cycles to the other
> threads in the core until the paused thread is woken up by an
> interrupt. If the hypervisor has set the PSSCR[ESL|EC] bits, then
> execution of the "stop" instruction will raise a Hypervisor Facility
> Unavailable exception.
>
> The stop idle state in the guest (henceforth referred to as stop0lite)
> when enabled
>
> * has a very small wakeup latency (1-3us) comparable to that of
> snooze and considerably better compared the Shared CEDE state
> (25-30us). Results are provided below for wakeup latency measured
> by waking up an idle CPU in a given state using a timer as well as
> using an IPI.
>
> ======================================================================
> Wakeup Latency measured using a timer (in ns) [Lower is better]
> ======================================================================
> Idle state | Nr samples | Min | Max | Median | Avg | Stddev|
> ======================================================================
> snooze | 60 | 787 | 1059 | 938 | 937.4 | 42.27 |
> ======================================================================
> stop0lite | 60 | 770 | 1182 | 948 | 946.4 | 67.41 |
> ======================================================================
> Shared CEDE| 60 | 9550 | 36694 | 29219 |28564.1|3545.9 |
> ======================================================================
>
Posted two copies of Wakeup latency measured by timer. Here is the
wakeup latency measured using an IPI.
======================================================================
Wakeup latency measured using an IPI (in ns) [Lower is better]
======================================================================
Idle state | Nr | Min | Max | Median | Avg | Stddev |
|samples | | | | | |
----------------------------------------------------------------------
snooze | 60 | 2089| 4228| 2259| 2342.31| 316.56|
----------------------------------------------------------------------
stop0lite | 60 | 1947| 3674| 2653| 2610.57| 266.73|
----------------------------------------------------------------------
Shared CEDE| 60 | 20147| 36305| 21827| 26762.65| 6875.01|
======================================================================
--
Thanks and Regards
gautham.
^ permalink raw reply
* [RFC/PATCH 3/3] cpuidle/pseries: Add stop0lite state
From: Gautham R. Shenoy @ 2020-03-31 12:10 UTC (permalink / raw)
To: Paul Mackerras, Michael Neuling, Nicholas Piggin,
Michael Ellerman, David Gibson, Vaidyanathan Srinivasan,
Bharata B Rao
Cc: linuxppc-dev, linuxppc-dev, kvm-ppc, Gautham R. Shenoy
In-Reply-To: <1585656658-1838-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
The POWER ISA v3.0 allows stop instruction to be executed from a
HV=0,PR=0 context. If the PSSCR[ESL|EC] bits are cleared, then the
stop instruction thus executed will cause the thread to pause, thereby
donating its cycles to the other threads in the core until the paused
thread is woken up by an interrupt.
In this patch we define a cpuidle state for pseries guests named
stop0lite. This has a latency and residency intermediate to that of
snooze and CEDE. While snooze has non-existent latency, it consumes
the CPU cycles without contributing to anything useful. CEDE on the
other hand requires a full VM exit, which can result in some other
vCPU being scheduled on this physical CPU thereby delaying the
scheduling of the CEDEd vCPU back. In such cases, when the expected
idle duration is small (1-20us), the vCPU can go to this stop0lite
state which provides a nice intermediate state between snooze and
CEDE.
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpuidle/cpuidle-pseries.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index 74c2479..9c8c18d 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -20,6 +20,7 @@
#include <asm/firmware.h>
#include <asm/runlatch.h>
#include <asm/plpar_wrappers.h>
+#include <asm/processor.h>
struct cpuidle_driver pseries_idle_driver = {
.name = "pseries_idle",
@@ -170,6 +171,26 @@ static int shared_cede_loop(struct cpuidle_device *dev,
.enter = &dedicated_cede_loop },
};
+
+
+static int stop_loop(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ unsigned long srr1 = 0;
+
+ if (!prep_irq_for_idle_irqsoff())
+ return index;
+
+ __ppc64_runlatch_off();
+ asm volatile("stop");
+ __ppc64_runlatch_on();
+ fini_irq_for_idle_irqsoff();
+ irq_set_pending_from_srr1(srr1);
+
+ return index;
+}
+
/*
* States for shared partition case.
*/
@@ -180,6 +201,12 @@ static int shared_cede_loop(struct cpuidle_device *dev,
.exit_latency = 0,
.target_residency = 0,
.enter = &snooze_loop },
+ { /* stop0_lite */
+ .name = "stop0lite",
+ .desc = "Pauses the CPU",
+ .exit_latency = 2,
+ .target_residency=20,
+ .enter = &stop_loop },
{ /* Shared Cede */
.name = "Shared Cede",
.desc = "Shared Cede",
--
1.9.4
^ permalink raw reply related
* [RFC/PATCH 0/3] Add support for stop instruction inside KVM guest
From: Gautham R. Shenoy @ 2020-03-31 12:10 UTC (permalink / raw)
To: Paul Mackerras, Michael Neuling, Nicholas Piggin,
Michael Ellerman, David Gibson, Vaidyanathan Srinivasan,
Bharata B Rao
Cc: linuxppc-dev, linuxppc-dev, kvm-ppc, Gautham R. Shenoy
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
*** RFC Only. Not intended for inclusion ************
Motivation
~~~~~~~~~~~~~~~
The POWER ISA v3.0 allows stop instruction to be executed from a Guest
Kernel (HV=0,PR=0) context. If the hypervisor has cleared
PSSCR[ESL|EC] bits, then the stop instruction thus executed will cause
the vCPU thread to "pause", thereby donating its cycles to the other
threads in the core until the paused thread is woken up by an
interrupt. If the hypervisor has set the PSSCR[ESL|EC] bits, then
execution of the "stop" instruction will raise a Hypervisor Facility
Unavailable exception.
The stop idle state in the guest (henceforth referred to as stop0lite)
when enabled
* has a very small wakeup latency (1-3us) comparable to that of
snooze and considerably better compared the Shared CEDE state
(25-30us). Results are provided below for wakeup latency measured
by waking up an idle CPU in a given state using a timer as well as
using an IPI.
======================================================================
Wakeup Latency measured using a timer (in ns) [Lower is better]
======================================================================
Idle state | Nr samples | Min | Max | Median | Avg | Stddev|
======================================================================
snooze | 60 | 787 | 1059 | 938 | 937.4 | 42.27 |
======================================================================
stop0lite | 60 | 770 | 1182 | 948 | 946.4 | 67.41 |
======================================================================
Shared CEDE| 60 | 9550 | 36694 | 29219 |28564.1|3545.9 |
======================================================================
======================================================================
Wakeup Latency measured using a timer (in ns) [Lower is better]
======================================================================
Idle state | Nr samples | Min | Max | Median | Avg | Stddev|
======================================================================
snooze | 60 | 787 | 1059 | 938 | 937.4 | 42.27 |
======================================================================
stop0lite | 60 | 770 | 1182 | 948 | 946.4 | 67.41 |
======================================================================
Shared CEDE| 60 | 9550 | 36694 | 29219 |28564.1|3545.9 |
======================================================================
* provides an improved single threaded performance compared to snooze
since the idle state completely relinquishes the core cycles. The
single threaded performance is observed to be better even when
compared to "Shared CEDE", since in the latter case something else
can scheduled on the ceded CPU, while "stop0lite" doesn't give up
the CPU.
On a KVM guest with smp 8,sockets=1,cores=2,threads=4 with vCPUs of
a vCore bound to a physical core, we run a single-threaded ebizzy
pinned to one of the guest vCPUs while the sibling vCPUs in the core
are idling. We enable only one guest idle state at a time to measure
the single-threaded performance benefit that the idle state provides
by giving up the core resources to the non-idle thread. we obtain
~13% improvement in the throughput compared to that with "snooze"
and ~8% improvement in the throughput compared to "Shared CEDE".
=======================================================================
| ebizzy records/s : [Higher the better] |
=======================================================================
|Idle state | Nr | Min | Max | Median | Avg | Stddev |
| |samples | | | | | |
=======================================================================
|snooze | 10 | 1378988| 1379358| 1379032|1379067.3| 113.47|
=======================================================================
|stop0lite | 10 | 1561836| 1562058| 1561906|1561927.5| 81.87|
=======================================================================
|Shared CEDE| 10 | 1446584| 1447383| 1447037|1447009.0| 244.16|
=======================================================================
Is stop0lite a replacement for snooze ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Not yet. snooze is a polling state, and can respond much faster to a
need_resched() compared to stop0lite which needs an IPI to wakeup from
idle state. This can be seen in the results below:
With the context_switch2 pipe test, we can see that with stop0lite,
the number of context switches are 32.47% lesser than with
snooze. This is due to the fact that snooze is a polling state which
polls for TIF_NEED_RESCHED. Thus it does not require an interrupt to
exit the state and start executing the scheduler code. However,
stop0lite needs an IPI.
Compared to the "Shared CEDE" state, we see that with stop0lite, we
have 82.7% improvement in the number of context switches. This is due
to the low wakeup latency compared to Shared CEDE.
======================================================================
context switch2 : Number of context switches/s [Higher the better]
======================================================================
Idle state | Nr | Min | Max | Median | Avg | Stddev |
|samples | | | | | |
======================================================================
snooze | 100 | 210480| 221578| 219860|219684.88| 1344.97|
======================================================================
stop0lite | 100 | 146730| 150266| 148258|148331.70| 871.50|
======================================================================
Shared CEDE| 100 | 75812| 82792| 81232| 81187.16| 832.99|
======================================================================
Is stop0lite a replacement for Shared CEDE ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
No. For longer idle durations, Shared CEDE is a better option compared
to "stop0lite", both from a performance (CEDEd CPUs can be put into
deeper idle states such as stop2, which can provide SMT folding
benefits) and utilization (Hypervisor can utilize the idle CPUs for
running something useful).
What this patch-set does:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The patchset has 3 patches
Patch 1: Allows the guest to run "stop" instruction without crashing
even if the hypervisor has set the PSSCR[ESL|EC] bits. This
is done by handling the Hypervisor Facility Unavailable
exception and incrementing the program counter by 4 bytes,
thus emulating the wakeup from a PSSCR[ESL = EC = 0] stop.
Patch 2: Clears the PSSCR[ESL|EC] bits unconditionally before
dispatching a vCPU, thereby allowing the vCPU to execute a
"stop" instruction.
Patch 3: Defines a cpuidle state for pseries guest named "stop0lite"
to be invoked by the cpuidle driver.
What this patch-set does not do:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* It does not define an interface by which the guest discovers the
stop-capability. Should this be defined via device-tree?
* It does address the problem of guest migration. i.e, a guest started
on a hypervisor which supports guest stop state, if migrated to a
hypervisor which does not support guest stop state will crash,
unless it has Patch 1 above.
I would like to seek feedback and comments with respect to how to go
about implementing the issues that have not been addressed in this
patchset.
Gautham R. Shenoy (3):
powerpc/kvm: Handle H_FAC_UNAVAIL when guest executes stop.
pseries/kvm: Clear PSSCR[ESL|EC] bits before guest entry
cpuidle/pseries: Add stop0lite state
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/kvm/book3s_hv.c | 8 ++++++--
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 25 +++++++++++++------------
drivers/cpuidle/cpuidle-pseries.c | 27 +++++++++++++++++++++++++++
4 files changed, 47 insertions(+), 14 deletions(-)
--
1.9.4
^ permalink raw reply
* [RFC/PATCH 2/3] pseries/kvm: Clear PSSCR[ESL|EC] bits before guest entry
From: Gautham R. Shenoy @ 2020-03-31 12:10 UTC (permalink / raw)
To: Paul Mackerras, Michael Neuling, Nicholas Piggin,
Michael Ellerman, David Gibson, Vaidyanathan Srinivasan,
Bharata B Rao
Cc: linuxppc-dev, linuxppc-dev, kvm-ppc, Gautham R. Shenoy
In-Reply-To: <1585656658-1838-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
ISA v3.0 allows the guest to execute a stop instruction. For this, the
PSSCR[ESL|EC] bits need to be cleared by the hypervisor before
scheduling in the guest vCPU.
Currently we always schedule in a vCPU with PSSCR[ESL|EC] bits
set. This patch changes the behaviour to enter the guest with
PSSCR[ESL|EC] bits cleared. This is a RFC patch where we
unconditionally clear these bits. Ideally this should be done
conditionally on platforms where the guest stop instruction has no
Bugs (starting POWER9 DD2.3).
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
arch/powerpc/kvm/book3s_hv.c | 2 +-
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 25 +++++++++++++------------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cdb7224..36d059a 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -3424,7 +3424,7 @@ static int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit,
mtspr(SPRN_IC, vcpu->arch.ic);
mtspr(SPRN_PID, vcpu->arch.pid);
- mtspr(SPRN_PSSCR, vcpu->arch.psscr | PSSCR_EC |
+ mtspr(SPRN_PSSCR, (vcpu->arch.psscr & ~(PSSCR_EC | PSSCR_ESL)) |
(local_paca->kvm_hstate.fake_suspend << PSSCR_FAKE_SUSPEND_LG));
mtspr(SPRN_HFSCR, vcpu->arch.hfscr);
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index dbc2fec..c2daec3 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -823,6 +823,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
mtspr SPRN_PID, r7
mtspr SPRN_WORT, r8
BEGIN_FTR_SECTION
+ /* POWER9-only registers */
+ ld r5, VCPU_TID(r4)
+ ld r6, VCPU_PSSCR(r4)
+ lbz r8, HSTATE_FAKE_SUSPEND(r13)
+ lis r7, (PSSCR_EC | PSSCR_ESL)@h /* Allow guest to call stop */
+ andc r6, r6, r7
+ rldimi r6, r8, PSSCR_FAKE_SUSPEND_LG, 63 - PSSCR_FAKE_SUSPEND_LG
+ ld r7, VCPU_HFSCR(r4)
+ mtspr SPRN_TIDR, r5
+ mtspr SPRN_PSSCR, r6
+ mtspr SPRN_HFSCR, r7
+FTR_SECTION_ELSE
/* POWER8-only registers */
ld r5, VCPU_TCSCR(r4)
ld r6, VCPU_ACOP(r4)
@@ -833,18 +845,7 @@ BEGIN_FTR_SECTION
mtspr SPRN_CSIGR, r7
mtspr SPRN_TACR, r8
nop
-FTR_SECTION_ELSE
- /* POWER9-only registers */
- ld r5, VCPU_TID(r4)
- ld r6, VCPU_PSSCR(r4)
- lbz r8, HSTATE_FAKE_SUSPEND(r13)
- oris r6, r6, PSSCR_EC@h /* This makes stop trap to HV */
- rldimi r6, r8, PSSCR_FAKE_SUSPEND_LG, 63 - PSSCR_FAKE_SUSPEND_LG
- ld r7, VCPU_HFSCR(r4)
- mtspr SPRN_TIDR, r5
- mtspr SPRN_PSSCR, r6
- mtspr SPRN_HFSCR, r7
-ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
8:
ld r5, VCPU_SPRG0(r4)
--
1.9.4
^ permalink raw reply related
* [RFC/PATCH 1/3] powerpc/kvm: Handle H_FAC_UNAVAIL when guest executes stop.
From: Gautham R. Shenoy @ 2020-03-31 12:10 UTC (permalink / raw)
To: Paul Mackerras, Michael Neuling, Nicholas Piggin,
Michael Ellerman, David Gibson, Vaidyanathan Srinivasan,
Bharata B Rao
Cc: linuxppc-dev, linuxppc-dev, kvm-ppc, Gautham R. Shenoy
In-Reply-To: <1585656658-1838-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
If a guest executes a stop instruction when the hypervisor has set the
PSSCR[ESL|EC] bits, the processor will throw an Hypervisor Facility
Unavailable exception. Currently when we receive this exception, we
only check if the exeception is generated due to a doorbell
instruction, in which case we emulate it. For all other cases,
including the case when the guest executes a stop-instruction, the
hypervisor sends a PROGILL to the guest program, which results in a
guest crash.
This patch adds code to handle the case when the hypervisor receives a
H_FAC_UNAVAIL exception due to guest executing the stop
instruction. The hypervisor increments the pc to the next instruction
and resumes the guest as expected by the semantics of the
PSSCR[ESL|EC] = 0 stop instruction.
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/kvm/book3s_hv.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index da5cab0..2568c18 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -399,6 +399,7 @@
/* HFSCR and FSCR bit numbers are the same */
#define FSCR_SCV_LG 12 /* Enable System Call Vectored */
#define FSCR_MSGP_LG 10 /* Enable MSGP */
+#define FSCR_STOP_LG 9 /* Enable stop states */
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
#define FSCR_TM_LG 5 /* Enable Transactional Memory */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 33be4d9..cdb7224 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1419,7 +1419,11 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) &&
cpu_has_feature(CPU_FTR_ARCH_300))
r = kvmppc_emulate_doorbell_instr(vcpu);
- if (r == EMULATE_FAIL) {
+ else if (((vcpu->arch.hfscr >> 56) == FSCR_STOP_LG) &&
+ cpu_has_feature(CPU_FTR_ARCH_300)) {
+ kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
+ r = RESUME_GUEST;
+ } else if (r == EMULATE_FAIL) {
kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
r = RESUME_GUEST;
}
--
1.9.4
^ permalink raw reply related
* Re: [PATCH v2 2/2] powerpc: Remove Xilinx PPC405/PPC440 support
From: Bartlomiej Zolnierkiewicz @ 2020-03-31 11:43 UTC (permalink / raw)
To: Michal Simek
Cc: Kate Stewart, Mark Rutland, Desnes A. Nunes do Rosario,
Geert Uytterhoeven, linux-doc, linux-fbdev, dri-devel,
Paul Mackerras, Miquel Raynal, Mauro Carvalho Chehab,
Fabio Estevam, Sasha Levin, sfr, Jonathan Corbet, maz,
Masahiro Yamada, YueHaibing, Krzysztof Kozlowski, Allison Randal,
linux-arm-kernel, devicetree, Andrew Donnellan, Arnd Bergmann,
Alistair Popple, linuxppc-dev, Nicholas Piggin, Alexios Zavras,
Rob Herring, git, Jonathan Cameron, Thomas Gleixner,
Andy Shevchenko, Dmitry Vyukov, monstr, Wei Hu,
Greg Kroah-Hartman, Nick Desaulniers, linux-kernel,
Enrico Weigelt, David S. Miller, Thiago Jung Bauermann
In-Reply-To: <9c3e02ffa9812c6f046708b45932d40f33e8817a.1585575111.git.michal.simek@xilinx.com>
On 3/30/20 3:32 PM, Michal Simek wrote:
> The latest Xilinx design tools called ISE and EDK has been released in
> October 2013. New tool doesn't support any PPC405/PPC440 new designs.
> These platforms are no longer supported and tested.
>
> PowerPC 405/440 port is orphan from 2013 by
> commit cdeb89943bfc ("MAINTAINERS: Fix incorrect status tag") and
> commit 19624236cce1 ("MAINTAINERS: Update Grant's email address and maintainership")
> that's why it is time to remove the support fot these platforms.
>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> # for fbdev
> ---
>
> Changes in v2:
> - Based on my chat with Arnd I removed arch/powerpc/xmon/ changes done in
> v1 to keep them the same as before. (kbuild reported some issues with it
> too)
>
> Documentation/devicetree/bindings/xilinx.txt | 143 ------
> Documentation/powerpc/bootwrapper.rst | 28 +-
> MAINTAINERS | 6 -
> arch/powerpc/Kconfig.debug | 2 +-
> arch/powerpc/boot/Makefile | 7 +-
> arch/powerpc/boot/dts/Makefile | 1 -
> arch/powerpc/boot/dts/virtex440-ml507.dts | 406 ----------------
> arch/powerpc/boot/dts/virtex440-ml510.dts | 466 -------------------
> arch/powerpc/boot/ops.h | 1 -
> arch/powerpc/boot/serial.c | 5 -
> arch/powerpc/boot/uartlite.c | 79 ----
> arch/powerpc/boot/virtex.c | 97 ----
> arch/powerpc/boot/virtex405-head.S | 31 --
> arch/powerpc/boot/wrapper | 8 -
> arch/powerpc/configs/40x/virtex_defconfig | 75 ---
> arch/powerpc/configs/44x/virtex5_defconfig | 74 ---
> arch/powerpc/configs/ppc40x_defconfig | 8 -
> arch/powerpc/configs/ppc44x_defconfig | 8 -
> arch/powerpc/include/asm/xilinx_intc.h | 16 -
> arch/powerpc/include/asm/xilinx_pci.h | 21 -
> arch/powerpc/kernel/cputable.c | 39 --
> arch/powerpc/platforms/40x/Kconfig | 31 --
> arch/powerpc/platforms/40x/Makefile | 1 -
> arch/powerpc/platforms/40x/virtex.c | 54 ---
> arch/powerpc/platforms/44x/Kconfig | 37 --
> arch/powerpc/platforms/44x/Makefile | 2 -
> arch/powerpc/platforms/44x/virtex.c | 60 ---
> arch/powerpc/platforms/44x/virtex_ml510.c | 30 --
> arch/powerpc/platforms/Kconfig | 4 -
> arch/powerpc/sysdev/Makefile | 2 -
> arch/powerpc/sysdev/xilinx_intc.c | 88 ----
> arch/powerpc/sysdev/xilinx_pci.c | 132 ------
> drivers/char/Kconfig | 2 +-
> drivers/video/fbdev/Kconfig | 2 +-
> 34 files changed, 7 insertions(+), 1959 deletions(-)
> delete mode 100644 arch/powerpc/boot/dts/virtex440-ml507.dts
> delete mode 100644 arch/powerpc/boot/dts/virtex440-ml510.dts
> delete mode 100644 arch/powerpc/boot/uartlite.c
> delete mode 100644 arch/powerpc/boot/virtex.c
> delete mode 100644 arch/powerpc/boot/virtex405-head.S
> delete mode 100644 arch/powerpc/configs/40x/virtex_defconfig
> delete mode 100644 arch/powerpc/configs/44x/virtex5_defconfig
> delete mode 100644 arch/powerpc/include/asm/xilinx_intc.h
> delete mode 100644 arch/powerpc/include/asm/xilinx_pci.h
> delete mode 100644 arch/powerpc/platforms/40x/virtex.c
> delete mode 100644 arch/powerpc/platforms/44x/virtex.c
> delete mode 100644 arch/powerpc/platforms/44x/virtex_ml510.c
> delete mode 100644 arch/powerpc/sysdev/xilinx_intc.c
> delete mode 100644 arch/powerpc/sysdev/xilinx_pci.c
Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics
^ permalink raw reply
* [PATCH v4 4/4] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
From: Vaibhav Jain @ 2020-03-31 10:58 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331105829.266591-1-vaibhav@linux.ibm.com>
This patch implements support for papr_scm command
'DSM_PAPR_SCM_HEALTH' that returns a newly introduced 'struct
nd_papr_scm_dimm_health_stat' instance containing dimm health
information back to user space in response to ND_CMD_CALL. This
functionality is implemented in newly introduced papr_scm_get_health()
that queries the scm-dimm health information and then copies these bitmaps
to the package payload whose layout is defined by 'struct
papr_scm_ndctl_health'.
The patch also introduces a new member a new member 'struct
papr_scm_priv.health' thats an instance of 'struct
nd_papr_scm_dimm_health_stat' to cache the health information of a
scm-dimm. As a result functions drc_pmem_query_health() and
papr_flags_show() are updated to populate and use this new struct
instead of two be64 integers that we earlier used.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v3..v4: Call the DSM_PAPR_SCM_HEALTH service function from
papr_scm_service_dsm() instead of papr_scm_ndctl(). [Aneesh]
v2..v3: Updated struct nd_papr_scm_dimm_health_stat_v1 to use '__xx'
types as its exported to the userspace [Aneesh]
Changed the constants DSM_PAPR_SCM_DIMM_XX indicating dimm
health from enum to #defines [Aneesh]
v1..v2: New patch in the series
---
arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 40 +++++++
arch/powerpc/platforms/pseries/papr_scm.c | 109 ++++++++++++++++---
2 files changed, 132 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
index c039a49b41b4..8265125304ca 100644
--- a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
+++ b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
@@ -132,6 +132,7 @@ struct nd_papr_scm_cmd_pkg {
*/
enum dsm_papr_scm {
DSM_PAPR_SCM_MIN = 0x10000,
+ DSM_PAPR_SCM_HEALTH,
DSM_PAPR_SCM_MAX,
};
@@ -158,4 +159,43 @@ static void *papr_scm_pcmd_to_payload(struct nd_papr_scm_cmd_pkg *pcmd)
else
return (void *)((__u8 *) pcmd + pcmd->payload_offset);
}
+
+/* Various scm-dimm health indicators */
+#define DSM_PAPR_SCM_DIMM_HEALTHY 0
+#define DSM_PAPR_SCM_DIMM_UNHEALTHY 1
+#define DSM_PAPR_SCM_DIMM_CRITICAL 2
+#define DSM_PAPR_SCM_DIMM_FATAL 3
+
+/*
+ * Struct exchanged between kernel & ndctl in for PAPR_DSM_PAPR_SMART_HEALTH
+ * Various bitflags 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.
+ */
+struct nd_papr_scm_dimm_health_stat_v1 {
+ __u8 dimm_unarmed;
+ __u8 dimm_bad_shutdown;
+ __u8 dimm_bad_restore;
+ __u8 dimm_scrubbed;
+ __u8 dimm_locked;
+ __u8 dimm_encrypted;
+ __u16 dimm_health;
+};
+
+/*
+ * 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_scm_dimm_health_stat nd_papr_scm_dimm_health_stat_v1
+
+/* Current version number for the dimm health struct */
+#define ND_PAPR_SCM_DIMM_HEALTH_VERSION 1
+
#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ */
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index e415a3c0d89e..62b20ef66b33 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -47,8 +47,7 @@ struct papr_scm_priv {
struct mutex dimm_mutex;
/* Health information for the dimm */
- __be64 health_bitmap;
- __be64 health_bitmap_valid;
+ struct nd_papr_scm_dimm_health_stat health;
};
static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -158,6 +157,7 @@ static int drc_pmem_query_health(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
int64_t rc;
+ __be64 health;
rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
if (rc != H_SUCCESS) {
@@ -172,13 +172,41 @@ static int drc_pmem_query_health(struct papr_scm_priv *p)
return rc;
/* Store the retrieved health information in dimm platform data */
- p->health_bitmap = ret[0];
- p->health_bitmap_valid = ret[1];
+ health = ret[0] & ret[1];
dev_dbg(&p->pdev->dev,
"Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n",
- be64_to_cpu(p->health_bitmap),
- be64_to_cpu(p->health_bitmap_valid));
+ be64_to_cpu(ret[0]),
+ be64_to_cpu(ret[1]));
+
+ memset(&p->health, 0, sizeof(p->health));
+
+ /* Check for various masks in bitmap and set the buffer */
+ if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ p->health.dimm_unarmed = true;
+
+ if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ p->health.dimm_bad_shutdown = true;
+
+ if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ p->health.dimm_bad_restore = true;
+
+ if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ p->health.dimm_encrypted = true;
+
+ if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED) {
+ p->health.dimm_locked = true;
+ p->health.dimm_scrubbed = true;
+ }
+
+ if (health & PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_UNHEALTHY;
+
+ if (health & PAPR_SCM_DIMM_HEALTH_CRITICAL)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_CRITICAL;
+
+ if (health & PAPR_SCM_DIMM_HEALTH_FATAL)
+ p->health.dimm_health = DSM_PAPR_SCM_DIMM_FATAL;
mutex_unlock(&p->dimm_mutex);
return 0;
@@ -331,6 +359,51 @@ static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
return 0;
}
+/* Fetch the DIMM health info and populate it in provided package. */
+static int papr_scm_get_health(struct papr_scm_priv *p,
+ struct nd_papr_scm_cmd_pkg *pkg)
+{
+ int rc;
+ size_t copysize = sizeof(p->health);
+
+ rc = drc_pmem_query_health(p);
+ if (rc)
+ goto out;
+ /*
+ * If the requested payload version is greater than one we know
+ * about, return the payload version we know about and let
+ * caller/userspace handle.
+ */
+ if (pkg->payload_version > ND_PAPR_SCM_DIMM_HEALTH_VERSION)
+ pkg->payload_version = ND_PAPR_SCM_DIMM_HEALTH_VERSION;
+
+ if (pkg->hdr.nd_size_out < copysize) {
+ dev_dbg(&p->pdev->dev, "%s Payload not large enough\n",
+ __func__);
+ dev_dbg(&p->pdev->dev, "%s Expected %lu, available %u\n",
+ __func__, copysize, pkg->hdr.nd_size_out);
+ rc = -ENOSPC;
+ goto out;
+ }
+
+ dev_dbg(&p->pdev->dev, "%s Copying payload size=%lu version=0x%x\n",
+ __func__, copysize, pkg->payload_version);
+
+ /* Copy a subset of health struct based on copysize */
+ memcpy(papr_scm_pcmd_to_payload(pkg), &p->health, copysize);
+ pkg->hdr.nd_fw_size = copysize;
+
+out:
+ /*
+ * Put the error in out package and return success from function
+ * so that errors if any are propogated back to userspace.
+ */
+ pkg->cmd_status = rc;
+ dev_dbg(&p->pdev->dev, "%s completion code = %d\n", __func__, rc);
+
+ return 0;
+}
+
static int papr_scm_service_dsm(struct papr_scm_priv *p,
struct nd_papr_scm_cmd_pkg *call_pkg)
{
@@ -345,6 +418,9 @@ static int papr_scm_service_dsm(struct papr_scm_priv *p,
/* Depending on the DSM command call appropriate service routine */
switch (call_pkg->hdr.nd_command) {
+ case DSM_PAPR_SCM_HEALTH:
+ return papr_scm_get_health(p, call_pkg);
+
default:
pr_debug("Unsupported DSM command 0x%llx\n",
call_pkg->hdr.nd_command);
@@ -431,7 +507,6 @@ static ssize_t papr_flags_show(struct device *dev,
{
struct nvdimm *dimm = to_nvdimm(dev);
struct papr_scm_priv *p = nvdimm_provider_data(dimm);
- __be64 health;
int rc;
rc = drc_pmem_query_health(p);
@@ -443,26 +518,26 @@ static ssize_t papr_flags_show(struct device *dev,
if (rc)
return rc;
- health = p->health_bitmap & p->health_bitmap_valid;
-
- /* Check for various masks in bitmap and set the buffer */
- if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ if (p->health.dimm_unarmed)
rc += sprintf(buf, "not_armed ");
- if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ if (p->health.dimm_bad_shutdown)
rc += sprintf(buf + rc, "save_fail ");
- if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ if (p->health.dimm_bad_restore)
rc += sprintf(buf + rc, "restore_fail ");
- if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ if (p->health.dimm_encrypted)
rc += sprintf(buf + rc, "encrypted ");
- if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK)
+ if (p->health.dimm_health)
rc += sprintf(buf + rc, "smart_notify ");
- if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED)
- rc += sprintf(buf + rc, "scrubbed locked ");
+ if (p->health.dimm_scrubbed)
+ rc += sprintf(buf + rc, "scrubbed ");
+
+ if (p->health.dimm_locked)
+ rc += sprintf(buf + rc, "locked ");
if (rc > 0)
rc += sprintf(buf + rc, "\n");
--
2.24.1
^ permalink raw reply related
* [PATCH v4 3/4] powerpc/papr_scm, uapi: Add support for handling PAPR DSM commands
From: Vaibhav Jain @ 2020-03-31 10:58 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331105829.266591-1-vaibhav@linux.ibm.com>
Implement support for handling PAPR DSM commands in papr_scm
module. We advertise support for ND_CMD_CALL for the dimm command mask
and implement necessary scaffolding in the module to handle ND_CMD_CALL
ioctl and DSM commands that we receive.
The layout of the DSM commands as we expect from libnvdimm/libndctl is
described in newly introduced uapi header 'papr_scm_dsm.h' which
defines a new 'struct nd_papr_scm_cmd_pkg' header. This header is used
to communicate the DSM command via 'nd_pkg_papr_scm->nd_command' and
size of payload that need to be sent/received for servicing the DSM.
The PAPR DSM commands are assigned indexes started from 0x10000 to
prevent them from overlapping ND_CMD_* values and also makes handling
dimm commands in papr_scm_ndctl(). A new function cmd_to_func() is
implemented that reads the args to papr_scm_ndctl() and performs
sanity tests on them. In case of a DSM command being sent via
ND_CMD_CALL a newly introduced function papr_scm_service_dsm() is
called to handle the request.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v3..v4: Updated papr_scm_ndctl() to delegate DSM command handling to a
different function papr_scm_service_dsm(). [Aneesh]
v2..v3: Updated the nd_papr_scm_cmd_pkg to use __xx types as its
exported to the userspace [Aneesh]
v1..v2: New patch in the series.
---
arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 161 +++++++++++++++++++
arch/powerpc/platforms/pseries/papr_scm.c | 97 ++++++++++-
2 files changed, 252 insertions(+), 6 deletions(-)
create mode 100644 arch/powerpc/include/uapi/asm/papr_scm_dsm.h
diff --git a/arch/powerpc/include/uapi/asm/papr_scm_dsm.h b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
new file mode 100644
index 000000000000..c039a49b41b4
--- /dev/null
+++ b/arch/powerpc/include/uapi/asm/papr_scm_dsm.h
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * PAPR SCM Device specific methods and struct for libndctl and ndctl
+ *
+ * (C) Copyright IBM 2020
+ *
+ * Author: Vaibhav Jain <vaibhav at linux.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_
+#define _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+#include <linux/ndctl.h>
+#else
+#include <ndctl.h>
+#endif
+
+/*
+ * DSM 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_papr_scm_cmd_pkg' which expects a
+ * payload following it and offset of which relative to the struct is provided
+ * by 'nd_papr_scm_cmd_pkg.payload_offset'. *
+ *
+ * +-------------+---------------------+---------------------------+
+ * | 64-Bytes | 8-Bytes | Max 184-Bytes |
+ * +-------------+---------------------+---------------------------+
+ * | nd_papr_scm_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 | | |
+ * +-------------+---------------------+---------------------------+
+ *
+ * DSM Header:
+ *
+ * The header is defined as 'struct nd_papr_scm_cmd_pkg' which embeds a
+ * 'struct nd_cmd_pkg' instance. The DSM command is assigned to member
+ * 'nd_cmd_pkg.nd_command'. Apart from size information of the envelop which is
+ * contained in 'struct nd_cmd_pkg', the header also has members following
+ * members:
+ *
+ * 'cmd_status' : (Out) Errors if any encountered while servicing DSM.
+ * 'payload_version' : (In/Out) Version number associated with the payload.
+ * 'payload_offset' : (In)Relative offset of payload from start of envelope.
+ *
+ * DSM Payload:
+ *
+ * The layout of the DSM Payload is defined by various structs shared between
+ * papr_scm and libndctl so that contents of payload can be interpreted. During
+ * servicing of a DSM the papr_scm module will read input args from the payload
+ * field by casting its contents to an appropriate struct pointer based on the
+ * DSM command. Similarly the output of servicing the DSM 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 DSM header that indicates a specific
+ * version of the structure present in DSM Payload for a given DSM command. This
+ * provides backward compatibility in case the DSM Payload structure evolves
+ * and different structures are supported by 'papr_scm' and 'libndctl'.
+ *
+ * When sending a DSM 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 DSM envelop 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 DSM. After
+ * servicing the DSM, 'papr_scm' put the negotiated version of payload struct in
+ * returned 'payload_version' field.
+ *
+ * Libndctl on receiving the envelop 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 DSM struct between libndctl
+ * and papr_scm should provide backward compatibility until following two
+ * assumptions/conditions when defining new DSM structs hold:
+ *
+ * Let T(X) = { set of attributes in DSM struct 'T' versioned X }
+ *
+ * 1. T(X) is a proper subset of T(Y) if X > Y.
+ * i.e Each new version of DSM struct should retain existing struct
+ * attributes from previous version
+ *
+ * 2. If an entity (libndctl or papr_scm) supports a DSM 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 DSM struct, libndctl
+ * and papr_scm should retain support of the existing DSM struct
+ * version they support.
+ */
+
+/* Papr-scm-header + payload expected with ND_CMD_CALL ioctl from libnvdimm */
+struct nd_papr_scm_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 */
+};
+
+/*
+ * Sub commands for ND_CMD_CALL. To prevent overlap from ND_CMD_*, values for
+ * these enums start at 0x10000. These values are then returned from
+ * cmd_to_func() making it easy to implement the switch-case block in
+ * papr_scm_ndctl(). These commands are sent to the kernel via
+ * 'nd_papr_scm_cmd_pkg.hdr.nd_command'
+ */
+enum dsm_papr_scm {
+ DSM_PAPR_SCM_MIN = 0x10000,
+ DSM_PAPR_SCM_MAX,
+};
+
+/* Helpers to evaluate the size of PAPR_SCM envelope */
+/* Calculate the papr_scm-header size */
+#define ND_PAPR_SCM_ENVELOPE_CONTENT_HDR_SIZE \
+ (sizeof(struct nd_papr_scm_cmd_pkg) - sizeof(struct nd_cmd_pkg))
+
+/* Given a type calculate envelope-content size (papr_scm-header + payload) */
+#define ND_PAPR_SCM_ENVELOPE_CONTENT_SIZE(_type_) \
+ (sizeof(_type_) + ND_PAPR_SCM_ENVELOPE_CONTENT_HDR_SIZE)
+
+/* Convert a libnvdimm nd_cmd_pkg to papr_scm specific pkg */
+static struct nd_papr_scm_cmd_pkg *nd_to_papr_cmd_pkg(struct nd_cmd_pkg *cmd)
+{
+ return (struct nd_papr_scm_cmd_pkg *) cmd;
+}
+
+/* Return the payload pointer for a given pcmd */
+static void *papr_scm_pcmd_to_payload(struct nd_papr_scm_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);
+}
+#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_DSM_H_ */
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index aaf2e4ab1f75..e415a3c0d89e 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -15,13 +15,15 @@
#include <asm/plpar_wrappers.h>
#include <asm/papr_scm.h>
+#include <asm/papr_scm_dsm.h>
#define BIND_ANY_ADDR (~0ul)
#define PAPR_SCM_DIMM_CMD_MASK \
((1ul << ND_CMD_GET_CONFIG_SIZE) | \
(1ul << ND_CMD_GET_CONFIG_DATA) | \
- (1ul << ND_CMD_SET_CONFIG_DATA))
+ (1ul << ND_CMD_SET_CONFIG_DATA) | \
+ (1ul << ND_CMD_CALL))
struct papr_scm_priv {
struct platform_device *pdev;
@@ -283,15 +285,92 @@ static int papr_scm_meta_set(struct papr_scm_priv *p,
return 0;
}
+/*
+ * Validate the inputs args to dimm-control function and return '0' if valid.
+ * This also does initial sanity validation to ND_CMD_CALL sub-command packages.
+ */
+static int is_cmd_valid(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+ unsigned int buf_len)
+{
+ unsigned long cmd_mask = PAPR_SCM_DIMM_CMD_MASK;
+ struct nd_papr_scm_cmd_pkg *pkg = nd_to_papr_cmd_pkg(buf);
+
+ /* Only dimm-specific calls are supported atm */
+ if (!nvdimm)
+ return -EINVAL;
+
+ if (!test_bit(cmd, &cmd_mask)) {
+ pr_debug("%s: Unsupported cmd=%u\n", __func__, cmd);
+ return -EINVAL;
+ } else if (cmd == ND_CMD_CALL) {
+
+ /* Verify the envelop package */
+ if (!buf || buf_len < sizeof(struct nd_papr_scm_cmd_pkg)) {
+ pr_debug("%s: Invalid pkg size=%u\n", __func__,
+ buf_len);
+ return -EINVAL;
+ }
+
+ /* Verify that the DSM command family is valid */
+ if (pkg->hdr.nd_family != NVDIMM_FAMILY_PAPR_SCM) {
+ pr_debug("%s: Invalid pkg family=0x%llx\n", __func__,
+ pkg->hdr.nd_family);
+ return -EINVAL;
+
+ }
+
+ /* We except a payload with all DSM commands */
+ if (papr_scm_pcmd_to_payload(pkg) == NULL) {
+ pr_debug("%s: Empty payload for sub-command=0x%llx\n",
+ __func__, pkg->hdr.nd_command);
+ return -EINVAL;
+ }
+ }
+
+ /* Command looks valid */
+ return 0;
+}
+
+static int papr_scm_service_dsm(struct papr_scm_priv *p,
+ struct nd_papr_scm_cmd_pkg *call_pkg)
+{
+ /* unknown subcommands return error in packages */
+ if (call_pkg->hdr.nd_command <= DSM_PAPR_SCM_MIN ||
+ call_pkg->hdr.nd_command >= DSM_PAPR_SCM_MAX) {
+ pr_debug("Invalid DSM command 0x%llx\n",
+ call_pkg->hdr.nd_command);
+ call_pkg->cmd_status = -EINVAL;
+ return 0;
+ }
+
+ /* Depending on the DSM command call appropriate service routine */
+ switch (call_pkg->hdr.nd_command) {
+ default:
+ pr_debug("Unsupported DSM command 0x%llx\n",
+ call_pkg->hdr.nd_command);
+ call_pkg->cmd_status = -ENOENT;
+ return 0;
+ }
+}
+
int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
{
struct nd_cmd_get_config_size *get_size_hdr;
struct papr_scm_priv *p;
+ struct nd_papr_scm_cmd_pkg *call_pkg = NULL;
+ int rc;
- /* Only dimm-specific calls are supported atm */
- if (!nvdimm)
- return -EINVAL;
+ /* Use a local variable in case cmd_rc pointer is NULL */
+ if (cmd_rc == NULL)
+ cmd_rc = &rc;
+
+ *cmd_rc = is_cmd_valid(nvdimm, cmd, buf, buf_len);
+ if (rc < 0) {
+ pr_debug("%s: Invalid cmd=0x%x. Err=%d\n", __func__,
+ cmd, *cmd_rc);
+ return *cmd_rc;
+ }
p = nvdimm_provider_data(nvdimm);
@@ -313,13 +392,19 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
*cmd_rc = papr_scm_meta_set(p, buf);
break;
+ case ND_CMD_CALL:
+ call_pkg = nd_to_papr_cmd_pkg(buf);
+ *cmd_rc = papr_scm_service_dsm(p, call_pkg);
+ break;
+
default:
- return -EINVAL;
+ dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd);
+ *cmd_rc = -EINVAL;
}
dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc);
- return 0;
+ return *cmd_rc;
}
static inline int papr_scm_node(int node)
--
2.24.1
^ permalink raw reply related
* [PATCH v4 2/4] ndctl/uapi: Introduce NVDIMM_FAMILY_PAPR_SCM as a new NVDIMM DSM family
From: Vaibhav Jain @ 2020-03-31 10:58 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331105829.266591-1-vaibhav@linux.ibm.com>
Add PAPR-scm family of DSM command-set to the white list of NVDIMM
command sets.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v3..v4 : None
v2..v3 : Updated the patch prefix to 'ndctl/uapi' [Aneesh]
v1..v2 : None
---
include/uapi/linux/ndctl.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index de5d90212409..99fb60600ef8 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -244,6 +244,7 @@ struct nd_cmd_pkg {
#define NVDIMM_FAMILY_HPE2 2
#define NVDIMM_FAMILY_MSFT 3
#define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR_SCM 5
#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
struct nd_cmd_pkg)
--
2.24.1
^ permalink raw reply related
* [PATCH v4 1/4] powerpc/papr_scm: Fetch nvdimm health information from PHYP
From: Vaibhav Jain @ 2020-03-31 10:58 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
In-Reply-To: <20200331105829.266591-1-vaibhav@linux.ibm.com>
Implement support for fetching nvdimm health information via
H_SCM_HEALTH hcall as documented in Ref[1]. The hcall returns a pair
of 64-bit big-endian integers which are then stored in 'struct
papr_scm_priv' and subsequently partially exposed to user-space via
newly introduced dimm specific attribute 'papr_flags'. Also a new asm
header named 'papr-scm.h' is added that describes the interface
between PHYP and guest kernel.
Following flags are reported via 'papr_flags' sysfs attribute contents
of which are space separated string flags indicating various nvdimm
states:
* "not_armed" : Indicating that nvdimm contents wont survive a power
cycle.
* "save_fail" : Indicating that nvdimm contents couldn't be flushed
during last shutdown event.
* "restore_fail": Indicating that nvdimm contents couldn't be restored
during dimm initialization.
* "encrypted" : Dimm contents are encrypted.
* "smart_notify": There is health event for the nvdimm.
* "scrubbed" : Indicating that contents of the nvdimm have been
scrubbed.
* "locked" : Indicating that nvdimm contents cant be modified
until next power cycle.
[1]: commit 58b278f568f0 ("powerpc: Provide initial documentation for
PAPR hcalls")
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Changelog:
v3..v4 : None
v2..v3 : Removed PAPR_SCM_DIMM_HEALTH_NON_CRITICAL as a condition for
NVDIMM unarmed [Aneesh]
v1..v2 : New patch in the series.
---
arch/powerpc/include/asm/papr_scm.h | 48 ++++++++++
arch/powerpc/platforms/pseries/papr_scm.c | 105 +++++++++++++++++++++-
2 files changed, 151 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/include/asm/papr_scm.h
diff --git a/arch/powerpc/include/asm/papr_scm.h b/arch/powerpc/include/asm/papr_scm.h
new file mode 100644
index 000000000000..868d3360f56a
--- /dev/null
+++ b/arch/powerpc/include/asm/papr_scm.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Structures and defines needed to manage nvdimms for spapr guests.
+ */
+#ifndef _ASM_POWERPC_PAPR_SCM_H_
+#define _ASM_POWERPC_PAPR_SCM_H_
+
+#include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+/* DIMM health bitmap bitmap indicators */
+/* SCM device is unable to persist memory contents */
+#define PAPR_SCM_DIMM_UNARMED PPC_BIT(0)
+/* SCM device failed to persist memory contents */
+#define PAPR_SCM_DIMM_SHUTDOWN_DIRTY PPC_BIT(1)
+/* SCM device contents are persisted from previous IPL */
+#define PAPR_SCM_DIMM_SHUTDOWN_CLEAN PPC_BIT(2)
+/* SCM device contents are not persisted from previous IPL */
+#define PAPR_SCM_DIMM_EMPTY PPC_BIT(3)
+/* SCM device memory life remaining is critically low */
+#define PAPR_SCM_DIMM_HEALTH_CRITICAL PPC_BIT(4)
+/* SCM device will be garded off next IPL due to failure */
+#define PAPR_SCM_DIMM_HEALTH_FATAL PPC_BIT(5)
+/* SCM contents cannot persist due to current platform health status */
+#define PAPR_SCM_DIMM_HEALTH_UNHEALTHY PPC_BIT(6)
+/* SCM device is unable to persist memory contents in certain conditions */
+#define PAPR_SCM_DIMM_HEALTH_NON_CRITICAL PPC_BIT(7)
+/* SCM device is encrypted */
+#define PAPR_SCM_DIMM_ENCRYPTED PPC_BIT(8)
+/* SCM device has been scrubbed and locked */
+#define PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED PPC_BIT(9)
+
+/* Bits status indicators for health bitmap indicating unarmed dimm */
+#define PAPR_SCM_DIMM_UNARMED_MASK (PAPR_SCM_DIMM_UNARMED | \
+ PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+
+/* Bits status indicators for health bitmap indicating unflushed dimm */
+#define PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK (PAPR_SCM_DIMM_SHUTDOWN_DIRTY)
+
+/* Bits status indicators for health bitmap indicating unrestored dimm */
+#define PAPR_SCM_DIMM_BAD_RESTORE_MASK (PAPR_SCM_DIMM_EMPTY)
+
+/* Bit status indicators for smart event notification */
+#define PAPR_SCM_DIMM_SMART_EVENT_MASK (PAPR_SCM_DIMM_HEALTH_CRITICAL | \
+ PAPR_SCM_DIMM_HEALTH_FATAL | \
+ PAPR_SCM_DIMM_HEALTH_UNHEALTHY)
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 0b4467e378e5..aaf2e4ab1f75 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <asm/plpar_wrappers.h>
+#include <asm/papr_scm.h>
#define BIND_ANY_ADDR (~0ul)
@@ -39,6 +40,13 @@ struct papr_scm_priv {
struct resource res;
struct nd_region *region;
struct nd_interleave_set nd_set;
+
+ /* Protect dimm data from concurrent access */
+ struct mutex dimm_mutex;
+
+ /* Health information for the dimm */
+ __be64 health_bitmap;
+ __be64 health_bitmap_valid;
};
static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -144,6 +152,35 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
return drc_pmem_bind(p);
}
+static int drc_pmem_query_health(struct papr_scm_priv *p)
+{
+ unsigned long ret[PLPAR_HCALL_BUFSIZE];
+ int64_t rc;
+
+ rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
+ if (rc != H_SUCCESS) {
+ dev_err(&p->pdev->dev,
+ "Failed to query health information, Err:%lld\n", rc);
+ return -ENXIO;
+ }
+
+ /* Protect modifications to papr_scm_priv with the mutex */
+ rc = mutex_lock_interruptible(&p->dimm_mutex);
+ if (rc)
+ return rc;
+
+ /* Store the retrieved health information in dimm platform data */
+ p->health_bitmap = ret[0];
+ p->health_bitmap_valid = ret[1];
+
+ dev_dbg(&p->pdev->dev,
+ "Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n",
+ be64_to_cpu(p->health_bitmap),
+ be64_to_cpu(p->health_bitmap_valid));
+
+ mutex_unlock(&p->dimm_mutex);
+ return 0;
+}
static int papr_scm_meta_get(struct papr_scm_priv *p,
struct nd_cmd_get_config_data_hdr *hdr)
@@ -304,6 +341,67 @@ static inline int papr_scm_node(int node)
return min_node;
}
+static ssize_t papr_flags_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvdimm *dimm = to_nvdimm(dev);
+ struct papr_scm_priv *p = nvdimm_provider_data(dimm);
+ __be64 health;
+ int rc;
+
+ rc = drc_pmem_query_health(p);
+ if (rc)
+ return rc;
+
+ /* Protect against modifications to papr_scm_priv with the mutex */
+ rc = mutex_lock_interruptible(&p->dimm_mutex);
+ if (rc)
+ return rc;
+
+ health = p->health_bitmap & p->health_bitmap_valid;
+
+ /* Check for various masks in bitmap and set the buffer */
+ if (health & PAPR_SCM_DIMM_UNARMED_MASK)
+ rc += sprintf(buf, "not_armed ");
+
+ if (health & PAPR_SCM_DIMM_BAD_SHUTDOWN_MASK)
+ rc += sprintf(buf + rc, "save_fail ");
+
+ if (health & PAPR_SCM_DIMM_BAD_RESTORE_MASK)
+ rc += sprintf(buf + rc, "restore_fail ");
+
+ if (health & PAPR_SCM_DIMM_ENCRYPTED)
+ rc += sprintf(buf + rc, "encrypted ");
+
+ if (health & PAPR_SCM_DIMM_SMART_EVENT_MASK)
+ rc += sprintf(buf + rc, "smart_notify ");
+
+ if (health & PAPR_SCM_DIMM_SCRUBBED_AND_LOCKED)
+ rc += sprintf(buf + rc, "scrubbed locked ");
+
+ if (rc > 0)
+ rc += sprintf(buf + rc, "\n");
+
+ mutex_unlock(&p->dimm_mutex);
+ return rc;
+}
+DEVICE_ATTR_RO(papr_flags);
+
+/* papr_scm specific dimm attributes */
+static struct attribute *papr_scm_nd_attributes[] = {
+ &dev_attr_papr_flags.attr,
+ NULL,
+};
+
+static struct attribute_group papr_scm_nd_attribute_group = {
+ .attrs = papr_scm_nd_attributes,
+};
+
+static const struct attribute_group *papr_scm_dimm_attr_groups[] = {
+ &papr_scm_nd_attribute_group,
+ NULL,
+};
+
static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
{
struct device *dev = &p->pdev->dev;
@@ -330,8 +428,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
dimm_flags = 0;
set_bit(NDD_ALIASING, &dimm_flags);
- p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
- PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
+ p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_attr_groups,
+ dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
if (!p->nvdimm) {
dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
goto err;
@@ -415,6 +513,9 @@ static int papr_scm_probe(struct platform_device *pdev)
if (!p)
return -ENOMEM;
+ /* Initialize the dimm mutex */
+ mutex_init(&p->dimm_mutex);
+
/* optional DT properties */
of_property_read_u32(dn, "ibm,metadata-size", &metadata_size);
--
2.24.1
^ permalink raw reply related
* [PATCH v4 0/4] powerpc/papr_scm: Add support for reporting nvdimm health
From: Vaibhav Jain @ 2020-03-31 10:58 UTC (permalink / raw)
To: linuxppc-dev, linux-nvdimm
Cc: Alastair D'Silva, Aneesh Kumar K . V, Jeff Moyer,
Oliver O'Halloran, Vishal Verma, Vaibhav Jain,
Michael Ellerman, Dan Williams
The PAPR standard[1][3] provides mechanisms to query the health and
performance stats of an NVDIMM via various hcalls as described in Ref[2].
Until now these stats were never available nor exposed to the user-space
tools like 'ndctl'. This is partly due to PAPR platform not having support
for ACPI and NFIT. Hence 'ndctl' is unable to query and report the dimm
health status and a user had no way to determine the current health status
of a NDVIMM.
To overcome this limitation, this patch-set updates papr_scm kernel module
to query and fetch nvdimm health stats using hcalls described in Ref[2].
This health and performance stats are then exposed to userspace via syfs
and Dimm-Specific-Methods(DSM) issued by libndctl.
These changes coupled with proposed ndtcl changes located at Ref[4] should
provide a way for the user to retrieve NVDIMM health status using ndtcl.
Below is a sample output using proposed kernel + ndctl for PAPR NVDIMM in
a emulation environment:
# ndctl list -DH
[
{
"dev":"nmem0",
"health":{
"health_state":"fatal",
"shutdown_state":"dirty"
}
}
]
Dimm health report output on a pseries guest lpar with vPMEM or HMS
based nvdimms that are in perfectly healthy conditions:
# ndctl list -d nmem0 -H
[
{
"dev":"nmem0",
"health":{
"health_state":"ok",
"shutdown_state":"clean"
}
}
]
PAPR Dimm-Specific-Methods(DSM)
================================
As the name suggests DSMs are used by vendor specific code in libndctl to
execute certain operations or fetch certain information for NVDIMMS. DSMs
can be sent to papr_scm module via libndctl (userspace) and libnvdimm
(kernel) using the ND_CMD_CALL ioctl which can be handled in the dimm
control function papr_scm_ndctl(). For PAPR this patchset proposes a single
DSM to retrieve DIMM health, defined in the newly introduced uapi header
named 'papr_scm_dsm.h'. Support for more DSMs will be added in future.
Structure of the patch-set
==========================
The patchset starts with implementing support for fetching nvdimm health
information from PHYP and partially exposing it to user-space via nvdimm
flags.
Second & Third patches deal with implementing support for servicing DSM
commands papr_scm.
Finally the Fourth patch implements support for servicing DSM
'DSM_PAPR_SCM_HEALTH' that returns the nvdimm health information to
libndctl.
Changelog:
==========
v3..v4:
* Restructured papr_scm_ndctl() to dispatch ND_CMD_CALL commands to a new
function named papr_scm_service_dsm() to serivice DSM requests. [Aneesh]
v2..v3:
* Updated the papr_scm_dsm.h header to be more confimant general kernel
guidelines for UAPI headers. [Aneesh]
* Changed the definition of macro PAPR_SCM_DIMM_UNARMED_MASK to not
include case when the nvdimm is unarmed because its a vPMEM
nvdimm. [Aneesh]
v1..v2:
* Restructured the patch-set based on review comments on V1 patch-set to
simplify the patch review. Multiple small patches have been combined into
single patches to reduce cross referencing that was needed in earlier
patch-set. Hence most of the patches in this patch-set as now new. [Aneesh]
* Removed the initial work done for fetch nvdimm performance statistics.
These changes will be re-proposed in a separate patch-set. [Aneesh]
* Simplified handling of versioning of 'struct
nd_papr_scm_dimm_health_stat_v1' as only one version of the structure is
currently in existence.
References:
[1]: "Power Architecture Platform Reference"
https://en.wikipedia.org/wiki/Power_Architecture_Platform_Reference
[2]: commit 58b278f568f0
("powerpc: Provide initial documentation for PAPR hcalls")
[3]: "Linux on Power Architecture Platform Reference"
https://members.openpowerfoundation.org/document/dl/469
[4]: https://patchwork.kernel.org/project/linux-nvdimm/list/?series=244625
Vaibhav Jain (4):
powerpc/papr_scm: Fetch nvdimm health information from PHYP
ndctl/uapi: Introduce NVDIMM_FAMILY_PAPR_SCM as a new NVDIMM DSM
family
powerpc/papr_scm,uapi: Add support for handling PAPR DSM commands
powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
arch/powerpc/include/asm/papr_scm.h | 48 ++++
arch/powerpc/include/uapi/asm/papr_scm_dsm.h | 201 ++++++++++++++
arch/powerpc/platforms/pseries/papr_scm.c | 277 ++++++++++++++++++-
include/uapi/linux/ndctl.h | 1 +
4 files changed, 519 insertions(+), 8 deletions(-)
create mode 100644 arch/powerpc/include/asm/papr_scm.h
create mode 100644 arch/powerpc/include/uapi/asm/papr_scm_dsm.h
--
2.24.1
^ permalink raw reply
* Re: [PATCH 0/2] powerpc: Remove support for ppc405/440 Xilinx platforms
From: Christophe Leroy @ 2020-03-31 10:30 UTC (permalink / raw)
To: Michal Simek, Michael Ellerman, Andy Shevchenko, Arnd Bergmann
Cc: Kate Stewart, Mark Rutland, Desnes A. Nunes do Rosario,
Geert Uytterhoeven, open list:DOCUMENTATION,
ALSA Development Mailing List, dri-devel, Jaroslav Kysela,
Richard Fontana, Paul Mackerras, Miquel Raynal,
Mauro Carvalho Chehab, Fabio Estevam, Sasha Levin,
Stephen Rothwell, Jonathan Corbet, Masahiro Yamada, YueHaibing,
Krzysztof Kozlowski, Allison Randal, Leonardo Bras, DTML,
Andrew Donnellan, Bartlomiej Zolnierkiewicz, Marc Zyngier,
Alistair Popple, Nicholas Piggin, Alexios Zavras, Mark Brown, git,
Linux Fbdev development list, Jonathan Cameron, Thomas Gleixner,
Linux ARM, Enrico Weigelt, Michal Simek, Wei Hu,
Christian Lamparter, Greg Kroah-Hartman, Nick Desaulniers,
Takashi Iwai, linux-kernel@vger.kernel.org, Armijn Hemel,
Rob Herring, linuxppc-dev, David S. Miller, Thiago Jung Bauermann
In-Reply-To: <d822c806-14c5-4ce7-b559-090b0685fa43@xilinx.com>
Le 31/03/2020 à 12:04, Michal Simek a écrit :
> On 31. 03. 20 11:49, Christophe Leroy wrote:
>>
>>
>> Le 31/03/2020 à 09:19, Christophe Leroy a écrit :
>>>
>>>
>>> Le 31/03/2020 à 08:59, Michal Simek a écrit :
>>>> On 31. 03. 20 8:56, Christophe Leroy wrote:
>>>>>
>>>>>
>>>>> Le 31/03/2020 à 07:30, Michael Ellerman a écrit :
>>>>>> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>>>>>>> Le 27/03/2020 à 15:14, Andy Shevchenko a écrit :
>>>>>>>> On Fri, Mar 27, 2020 at 02:22:55PM +0100, Arnd Bergmann wrote:
>>>>>>>>> On Fri, Mar 27, 2020 at 2:15 PM Andy Shevchenko
>>>>>>>>> <andriy.shevchenko@linux.intel.com> wrote:
>>>>>>>>>> On Fri, Mar 27, 2020 at 03:10:26PM +0200, Andy Shevchenko wrote:
>>>>>>>>>>> On Fri, Mar 27, 2020 at 01:54:33PM +0100, Arnd Bergmann wrote:
>>>>>>>>>>>> On Fri, Mar 27, 2020 at 1:12 PM Michal Simek
>>>>>>>>>>>> <michal.simek@xilinx.com> wrote:
>>>>>>>> ...
>>>>>>>>
>>>>>>>>>>>> It does raise a follow-up question about ppc40x though: is it
>>>>>>>>>>>> time to
>>>>>>>>>>>> retire all of it?
>>>>>>>>>>>
>>>>>>>>>>> Who knows?
>>>>>>>>>>>
>>>>>>>>>>> I have in possession nice WD My Book Live, based on this
>>>>>>>>>>> architecture, and I
>>>>>>>>>>> won't it gone from modern kernel support. OTOH I understand that
>>>>>>>>>>> amount of real
>>>>>>>>>>> users not too big.
>>>>>>>>>>
>>>>>>>>>> +Cc: Christian Lamparter, whom I owe for that WD box.
>>>>>>>>>
>>>>>>>>> According to https://openwrt.org/toh/wd/mybooklive, that one is
>>>>>>>>> based on
>>>>>>>>> APM82181/ppc464, so it is about several generations newer than
>>>>>>>>> what I
>>>>>>>>> asked about (ppc40x).
>>>>>>>>>
>>>>>>>>>>> Ah, and I have Amiga board, but that one is being used only for
>>>>>>>>>>> testing, so,
>>>>>>>>>>> I don't care much.
>>>>>>>>>
>>>>>>>>> I think there are a couple of ppc440 based Amiga boards, but again,
>>>>>>>>> not 405
>>>>>>>>> to my knowledge.
>>>>>>>>
>>>>>>>> Ah, you are right. No objections from ppc40x removal!
>>>>>>>
>>>>>>> Removing 40x would help cleaning things a bit. For instance 40x is
>>>>>>> the
>>>>>>> last platform still having PTE_ATOMIC_UPDATES. So if we can remove
>>>>>>> 40x
>>>>>>> we can get rid of PTE_ATOMIC_UPDATES completely.
>>>>>>>
>>>>>>> If no one objects, I can prepare a series to drop support for 40x
>>>>>>> completely.
>>>>>>>
>>>>>>> Michael, any thought ?
>>>>>>
>>>>>> I have no attachment to 40x, and I'd certainly be happy to have less
>>>>>> code in the tree, we struggle to keep even the modern platforms well
>>>>>> maintained.
>>>>>>
>>>>>> At the same time I don't want to render anyone's hardware obsolete
>>>>>> unnecessarily. But if there's really no one using 40x then we should
>>>>>> remove it, it could well be broken already.
>>>>>>
>>>>>> So I guess post a series to do the removal and we'll see if anyone
>>>>>> speaks up.
>>>>>>
>>>>>
>>>>> Ok, series sent out, see
>>>>> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=167757
>>>>
>>>> ok. I see you have done it completely independently of my patchset.
>>>> Would be better if you can base it on the top of my 2 patches because
>>>> they are in conflict now and I need to also remove virtex 44x platform
>>>> also with alsa driver.
>>>>
>>>
>>> I can't see your first patch, only the second one shows up in the
>>> series, see
>>> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=167757
>>>
>>
>>
>> Ok, I found your first patch on another patchwork, it doesn't touch any
>> file in arch/powerpc/
>
> There was just driver dependency on symbol which is removed by 2/2.
> Let's see what you get from kbuild if any symbol is removed but still
> used in drivers folder.
Nothing bad apparently, see build test at
http://kisskb.ellerman.id.au/kisskb/head/a4890e3fb046950e9a62dc3eff5b37469551e823/
Christophe
^ permalink raw reply
* Re: [PATCH 0/2] powerpc: Remove support for ppc405/440 Xilinx platforms
From: Michal Simek @ 2020-03-31 10:04 UTC (permalink / raw)
To: Christophe Leroy, Michal Simek, Michael Ellerman, Andy Shevchenko,
Arnd Bergmann
Cc: Kate Stewart, Mark Rutland, Desnes A. Nunes do Rosario,
Geert Uytterhoeven, open list:DOCUMENTATION,
ALSA Development Mailing List, dri-devel, Jaroslav Kysela,
Richard Fontana, Paul Mackerras, Miquel Raynal,
Mauro Carvalho Chehab, Fabio Estevam, Sasha Levin,
Stephen Rothwell, Jonathan Corbet, Masahiro Yamada, YueHaibing,
Krzysztof Kozlowski, Allison Randal, Leonardo Bras, DTML,
Andrew Donnellan, Bartlomiej Zolnierkiewicz, Marc Zyngier,
Alistair Popple, Nicholas Piggin, Alexios Zavras, Mark Brown, git,
Linux Fbdev development list, Jonathan Cameron, Thomas Gleixner,
Linux ARM, Enrico Weigelt, Michal Simek, Wei Hu,
Christian Lamparter, Greg Kroah-Hartman, Nick Desaulniers,
Takashi Iwai, linux-kernel@vger.kernel.org, Armijn Hemel,
Rob Herring, linuxppc-dev, David S. Miller, Thiago Jung Bauermann
In-Reply-To: <12a1f423-7e54-6423-1c8c-33e221664272@c-s.fr>
On 31. 03. 20 11:49, Christophe Leroy wrote:
>
>
> Le 31/03/2020 à 09:19, Christophe Leroy a écrit :
>>
>>
>> Le 31/03/2020 à 08:59, Michal Simek a écrit :
>>> On 31. 03. 20 8:56, Christophe Leroy wrote:
>>>>
>>>>
>>>> Le 31/03/2020 à 07:30, Michael Ellerman a écrit :
>>>>> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>>>>>> Le 27/03/2020 à 15:14, Andy Shevchenko a écrit :
>>>>>>> On Fri, Mar 27, 2020 at 02:22:55PM +0100, Arnd Bergmann wrote:
>>>>>>>> On Fri, Mar 27, 2020 at 2:15 PM Andy Shevchenko
>>>>>>>> <andriy.shevchenko@linux.intel.com> wrote:
>>>>>>>>> On Fri, Mar 27, 2020 at 03:10:26PM +0200, Andy Shevchenko wrote:
>>>>>>>>>> On Fri, Mar 27, 2020 at 01:54:33PM +0100, Arnd Bergmann wrote:
>>>>>>>>>>> On Fri, Mar 27, 2020 at 1:12 PM Michal Simek
>>>>>>>>>>> <michal.simek@xilinx.com> wrote:
>>>>>>> ...
>>>>>>>
>>>>>>>>>>> It does raise a follow-up question about ppc40x though: is it
>>>>>>>>>>> time to
>>>>>>>>>>> retire all of it?
>>>>>>>>>>
>>>>>>>>>> Who knows?
>>>>>>>>>>
>>>>>>>>>> I have in possession nice WD My Book Live, based on this
>>>>>>>>>> architecture, and I
>>>>>>>>>> won't it gone from modern kernel support. OTOH I understand that
>>>>>>>>>> amount of real
>>>>>>>>>> users not too big.
>>>>>>>>>
>>>>>>>>> +Cc: Christian Lamparter, whom I owe for that WD box.
>>>>>>>>
>>>>>>>> According to https://openwrt.org/toh/wd/mybooklive, that one is
>>>>>>>> based on
>>>>>>>> APM82181/ppc464, so it is about several generations newer than
>>>>>>>> what I
>>>>>>>> asked about (ppc40x).
>>>>>>>>
>>>>>>>>>> Ah, and I have Amiga board, but that one is being used only for
>>>>>>>>>> testing, so,
>>>>>>>>>> I don't care much.
>>>>>>>>
>>>>>>>> I think there are a couple of ppc440 based Amiga boards, but again,
>>>>>>>> not 405
>>>>>>>> to my knowledge.
>>>>>>>
>>>>>>> Ah, you are right. No objections from ppc40x removal!
>>>>>>
>>>>>> Removing 40x would help cleaning things a bit. For instance 40x is
>>>>>> the
>>>>>> last platform still having PTE_ATOMIC_UPDATES. So if we can remove
>>>>>> 40x
>>>>>> we can get rid of PTE_ATOMIC_UPDATES completely.
>>>>>>
>>>>>> If no one objects, I can prepare a series to drop support for 40x
>>>>>> completely.
>>>>>>
>>>>>> Michael, any thought ?
>>>>>
>>>>> I have no attachment to 40x, and I'd certainly be happy to have less
>>>>> code in the tree, we struggle to keep even the modern platforms well
>>>>> maintained.
>>>>>
>>>>> At the same time I don't want to render anyone's hardware obsolete
>>>>> unnecessarily. But if there's really no one using 40x then we should
>>>>> remove it, it could well be broken already.
>>>>>
>>>>> So I guess post a series to do the removal and we'll see if anyone
>>>>> speaks up.
>>>>>
>>>>
>>>> Ok, series sent out, see
>>>> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=167757
>>>
>>> ok. I see you have done it completely independently of my patchset.
>>> Would be better if you can base it on the top of my 2 patches because
>>> they are in conflict now and I need to also remove virtex 44x platform
>>> also with alsa driver.
>>>
>>
>> I can't see your first patch, only the second one shows up in the
>> series, see
>> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=167757
>>
>
>
> Ok, I found your first patch on another patchwork, it doesn't touch any
> file in arch/powerpc/
There was just driver dependency on symbol which is removed by 2/2.
Let's see what you get from kbuild if any symbol is removed but still
used in drivers folder.
>
> I sent a v2 series with your powerpc patch as patch 2/11
>
> See https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=167766
Thanks,
Michal
^ permalink raw reply
* [PATCH v19 24/24] selftests: vm: pkeys: Fix multilib builds for x86
From: Sandipan Das @ 2020-03-31 9:58 UTC (permalink / raw)
To: akpm
Cc: linux-arch, fweimer, shuah, aneesh.kumar, x86, linuxram, mhocko,
linux-mm, mingo, linux-kselftest, msuchanek, linuxppc-dev,
bauerman
In-Reply-To: <cover.1585646528.git.sandipan@linux.ibm.com>
This ensures that both 32-bit and 64-bit binaries are generated
when this is built on a x86_64 system. Most of the changes have
been borrowed from tools/testing/selftests/x86/Makefile.
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Tested-by: Dave Hansen <dave.hansen@intel.com>
---
tools/testing/selftests/vm/Makefile | 72 +++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 4e9c741be6af2..82031f84af212 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -18,7 +18,30 @@ TEST_GEN_FILES += on-fault-limit
TEST_GEN_FILES += thuge-gen
TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd
+
+ifeq ($(ARCH),x86_64)
+CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_32bit_program.c -m32)
+CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_64bit_program.c)
+CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_program.c -no-pie)
+
+TARGETS := protection_keys
+BINARIES_32 := $(TARGETS:%=%_32)
+BINARIES_64 := $(TARGETS:%=%_64)
+
+ifeq ($(CAN_BUILD_WITH_NOPIE),1)
+CFLAGS += -no-pie
+endif
+
+ifeq ($(CAN_BUILD_I386),1)
+TEST_GEN_FILES += $(BINARIES_32)
+endif
+
+ifeq ($(CAN_BUILD_X86_64),1)
+TEST_GEN_FILES += $(BINARIES_64)
+endif
+else
TEST_GEN_FILES += protection_keys
+endif
ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64))
TEST_GEN_FILES += va_128TBswitch
@@ -32,6 +55,55 @@ TEST_FILES := test_vmalloc.sh
KSFT_KHDR_INSTALL := 1
include ../lib.mk
+ifeq ($(ARCH),x86_64)
+BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
+BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
+
+define gen-target-rule-32
+$(1) $(1)_32: $(OUTPUT)/$(1)_32
+.PHONY: $(1) $(1)_32
+endef
+
+define gen-target-rule-64
+$(1) $(1)_64: $(OUTPUT)/$(1)_64
+.PHONY: $(1) $(1)_64
+endef
+
+ifeq ($(CAN_BUILD_I386),1)
+$(BINARIES_32): CFLAGS += -m32
+$(BINARIES_32): LDLIBS += -lrt -ldl -lm
+$(BINARIES_32): %_32: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-32,$(t))))
+endif
+
+ifeq ($(CAN_BUILD_X86_64),1)
+$(BINARIES_64): CFLAGS += -m64
+$(BINARIES_64): LDLIBS += -lrt -ldl
+$(BINARIES_64): %_64: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-64,$(t))))
+endif
+
+# x86_64 users should be encouraged to install 32-bit libraries
+ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01)
+all: warn_32bit_failure
+
+warn_32bit_failure:
+ @echo "Warning: you seem to have a broken 32-bit build" 2>&1; \
+ echo "environment. This will reduce test coverage of 64-bit" 2>&1; \
+ echo "kernels. If you are using a Debian-like distribution," 2>&1; \
+ echo "try:"; 2>&1; \
+ echo ""; \
+ echo " apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \
+ echo ""; \
+ echo "If you are using a Fedora-like distribution, try:"; \
+ echo ""; \
+ echo " yum install glibc-devel.*i686"; \
+ exit 0;
+endif
+endif
+
$(OUTPUT)/userfaultfd: LDLIBS += -lpthread
$(OUTPUT)/mlock-random-test: LDLIBS += -lcap
--
2.17.1
^ permalink raw reply related
* [PATCH v19 23/24] selftests: vm: pkeys: Use the correct page size on powerpc
From: Sandipan Das @ 2020-03-31 9:58 UTC (permalink / raw)
To: akpm
Cc: linux-arch, fweimer, shuah, aneesh.kumar, x86, linuxram, mhocko,
linux-mm, mingo, linux-kselftest, msuchanek, linuxppc-dev,
bauerman
In-Reply-To: <cover.1585646528.git.sandipan@linux.ibm.com>
Both 4K and 64K pages are supported on powerpc. Parts of
the selftest code perform alignment computations based on
the PAGE_SIZE macro which is currently hardcoded to 64K
for powerpc. This causes some test failures on kernels
configured with 4K page size.
In some cases, we need to enforce function alignment on
page size. Since this can only be done at build time,
64K is used as the alignment factor as that also ensures
4K alignment.
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
---
tools/testing/selftests/vm/pkey-powerpc.h | 2 +-
tools/testing/selftests/vm/protection_keys.c | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vm/pkey-powerpc.h b/tools/testing/selftests/vm/pkey-powerpc.h
index 02bd4dd7d467a..3a761e51a5878 100644
--- a/tools/testing/selftests/vm/pkey-powerpc.h
+++ b/tools/testing/selftests/vm/pkey-powerpc.h
@@ -36,7 +36,7 @@
pkey-31 and exec-only key */
#define PKEY_BITS_PER_PKEY 2
#define HPAGE_SIZE (1UL << 24)
-#define PAGE_SIZE (1UL << 16)
+#define PAGE_SIZE sysconf(_SC_PAGESIZE)
static inline u32 pkey_bit_position(int pkey)
{
diff --git a/tools/testing/selftests/vm/protection_keys.c b/tools/testing/selftests/vm/protection_keys.c
index a1cb9a71e77ce..fc19addcb5c82 100644
--- a/tools/testing/selftests/vm/protection_keys.c
+++ b/tools/testing/selftests/vm/protection_keys.c
@@ -146,7 +146,12 @@ void abort_hooks(void)
* will then fault, which makes sure that the fault code handles
* execute-only memory properly.
*/
+#ifdef __powerpc64__
+/* This way, both 4K and 64K alignment are maintained */
+__attribute__((__aligned__(65536)))
+#else
__attribute__((__aligned__(PAGE_SIZE)))
+#endif
void lots_o_noops_around_write(int *write_to_me)
{
dprintf3("running %s()\n", __func__);
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox