* [RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-1-vaibhav@linux.ibm.com>
The DSM 'DSM_PAPR_SCM_STATS' should return the PAPR defined buffer
that holds various dimm performance attributes as defined in Ref[1]
back to user-space in response to ND_CMD_CALL.
Presently the module doesn't interpret nor consume these stat as they
are only intended to be consumer and reported by
'libndctl'[2]. PAPR sped [1] states that input buffer to be provided
to H_SCM_PERFORMANCE_HEALTH hcall should be 4KiB in size. However due
to limitations of the libnvdimm envelop (which is 256 bytes in size)
such a large buffer cannot be copied back to user-space.
Hence we do an optimization of querying the size of the output buffer
from H_SCM_PERFORMANCE_HEALTH hcall and copy only the needed portion
of the buffer to the user-space payload package.
This patch implements this DSM by implementing a new function
papr_scm_get_stats that queries the DIMM stat information and then
copies PHYP provided buffer that holds these stat attributes to the
package payload whose layout is defined by 'struct
papr_scm_perf_stats'
References:
[1]: https://patchwork.ozlabs.org/patch/1154292/
[2]: https://github.com/pmem/ndctl
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 51 +++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 6c0bc8f027db..ac50968453b0 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -34,6 +34,7 @@
enum {
DSM_PAPR_MIN = 0x10000,
DSM_PAPR_SCM_HEALTH,
+ DSM_PAPR_SCM_STATS,
DSM_PAPR_MAX,
};
@@ -410,6 +411,51 @@ static int papr_scm_get_health(struct papr_scm_priv *p,
return 0;
}
+/* Fetch the DIMM stats and populate it in provided papr_scm package */
+static int papr_scm_get_stats(struct papr_scm_priv *p,
+ struct nd_pkg_papr_scm *pkg)
+{
+ struct papr_scm_perf_stats *retbuffer;
+ int rc;
+ size_t copysize;
+
+ /* Return buffer for phyp where stats are written */
+ retbuffer = kzalloc(PAPR_SCM_MAX_PERF_STAT, GFP_KERNEL);
+
+ if (!retbuffer)
+ return -ENOMEM;
+
+ rc = drc_pmem_query_stats(p, retbuffer);
+ if (rc)
+ goto out;
+
+ /*
+ * Parse the retbuffer, fetch the size returned and return the
+ * first nd_size_out bytes back to userspce.
+ */
+ pkg->hdr.nd_fw_size = be16_to_cpu(retbuffer->size);
+ copysize = min_t(__u32, pkg->hdr.nd_fw_size, pkg->hdr.nd_size_out);
+
+ memcpy(pkg->payload, retbuffer, copysize);
+
+ /* Verify if the returned buffer was copied completely */
+ if (pkg->hdr.nd_fw_size > copysize) {
+ rc = -ENOSPC;
+ goto out;
+ }
+
+out:
+ kfree(retbuffer);
+ /*
+ * 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;
+}
+
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)
{
@@ -460,6 +506,11 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
*cmd_rc = papr_scm_get_health(p, call_pkg);
break;
+ case DSM_PAPR_SCM_STATS:
+ call_pkg = (struct nd_pkg_papr_scm *) buf;
+ *cmd_rc = papr_scm_get_stats(p, call_pkg);
+ break;
+
default:
dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
*cmd_rc = -EINVAL;
--
2.24.1
^ permalink raw reply related
* [RFC PATCH 5/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-1-vaibhav@linux.ibm.com>
The DSM 'DSM_PAPR_SCM_HEALTH' should return the health-bitmap and
health-valid-bitmap information for a dimm back to userspace in
response to ND_CMD_CALL.
This patch implements this DSM by implementing a new function
papr_scm_get_health() that queries the DIMM health information and
then copies these bitmaps to the package payload whose layout is
defined by 'struct papr_scm_ndctl_health'.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 46 +++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index e1a2c0e61077..6c0bc8f027db 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -33,9 +33,16 @@
*/
enum {
DSM_PAPR_MIN = 0x10000,
+ DSM_PAPR_SCM_HEALTH,
DSM_PAPR_MAX,
};
+/* Struct as returned by kernel in response to PAPR_DSM_PAPR_SMART_HEALTH */
+struct papr_scm_ndctl_health {
+ __be64 health_bitmap;
+ __be64 health_bitmap_valid;
+} __packed;
+
/* Payload expected with ND_CMD_CALL ioctl from libnvdimm */
struct nd_pkg_papr_scm {
struct nd_cmd_pkg hdr; /* Package header containing sub-cmd */
@@ -369,6 +376,40 @@ static int cmd_to_func(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
return pkg->hdr.nd_command;
}
+/* Fetch the DIMM health info and populate it in provided papr_scm package */
+static int papr_scm_get_health(struct papr_scm_priv *p,
+ struct nd_pkg_papr_scm *pkg)
+{
+ int rc;
+ struct papr_scm_ndctl_health *health =
+ (struct papr_scm_ndctl_health *)pkg->payload;
+
+ pkg->hdr.nd_fw_size = sizeof(struct papr_scm_ndctl_health);
+
+ if (pkg->hdr.nd_size_out < sizeof(struct papr_scm_ndctl_health)) {
+ rc = -ENOSPC;
+ goto out;
+ }
+
+ rc = drc_pmem_query_health(p);
+ if (rc)
+ goto out;
+
+ /* Copy the health data to the payload */
+ health->health_bitmap = p->health_bitmap;
+ health->health_bitmap_valid = p->health_bitmap_valid;
+
+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;
+}
+
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)
{
@@ -414,6 +455,11 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
*cmd_rc = 0;
break;
+ case DSM_PAPR_SCM_HEALTH:
+ call_pkg = (struct nd_pkg_papr_scm *) buf;
+ *cmd_rc = papr_scm_get_health(p, call_pkg);
+ break;
+
default:
dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
*cmd_rc = -EINVAL;
--
2.24.1
^ permalink raw reply related
* [RFC PATCH 4/6] powerpc/papr_scm: Add support for handling PAPR DSM commands
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-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
defined in 'struct nd_pkg_papr_scm' which contains a 'struct
nd_cmd_pkg' as 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() easier via a simplified switch-case
block. For this a new function cmd_to_func() is implemented that reads
the args to papr_scm_ndctl() , performs sanity tests on them and
converts them to PAPR DSM commands which can then be handled via the
switch-case block.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 96 +++++++++++++++++++++--
1 file changed, 89 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index deaece6e4d18..e1a2c0e61077 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -20,10 +20,29 @@
#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))
#define PAPR_SCM_MAX_PERF_STAT 4096
+/*
+ * 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()
+ */
+enum {
+ DSM_PAPR_MIN = 0x10000,
+ DSM_PAPR_MAX,
+};
+
+/* Payload expected with ND_CMD_CALL ioctl from libnvdimm */
+struct nd_pkg_papr_scm {
+ struct nd_cmd_pkg hdr; /* Package header containing sub-cmd */
+ uint32_t cmd_status; /* Out: Sub-cmd status returned back */
+ uint8_t payload[]; /* Out: Sub-cmd data buffer */
+} __packed;
+
/* Buffer layout returned by phyp when reporting drc perf stats */
struct papr_scm_perf_stats {
uint8_t version; /* Should be 0x01 */
@@ -303,19 +322,74 @@ static int papr_scm_meta_set(struct papr_scm_priv *p,
return 0;
}
+/*
+ * Validate the input to dimm-control function and return papr_scm specific
+ * commands. This does sanity validation to ND_CMD_CALL sub-command packages.
+ */
+static int cmd_to_func(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+ unsigned int buf_len)
+{
+ unsigned long cmd_mask = PAPR_SCM_DIMM_CMD_MASK;
+ struct nd_pkg_papr_scm *pkg = (struct nd_pkg_papr_scm *)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) {
+
+ return cmd;
+
+ } else if (buf_len < sizeof(struct nd_pkg_papr_scm)) {
+
+ pr_debug("%s: Invalid pkg size=%u\n", __func__, buf_len);
+ return -EINVAL;
+
+ } else if (pkg->hdr.nd_family != NVDIMM_FAMILY_PAPR) {
+
+ pr_debug("%s: Invalid pkg family=0x%llx\n", __func__,
+ pkg->hdr.nd_family);
+ return -EINVAL;
+
+ } else if (pkg->hdr.nd_command <= DSM_PAPR_MIN ||
+ pkg->hdr.nd_command >= DSM_PAPR_MAX) {
+
+ /* for unknown subcommands return ND_CMD_CALL */
+ pr_debug("%s: Unknown sub-command=0x%llx\n", __func__,
+ pkg->hdr.nd_command);
+ return ND_CMD_CALL;
+ }
+
+ /* Return the DSM_PAPR_SCM_* command */
+ return pkg->hdr.nd_command;
+}
+
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_pkg_papr_scm *call_pkg = NULL;
+ int cmd_in, 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_in = cmd_to_func(nvdimm, cmd, buf, buf_len);
+ if (cmd_in < 0) {
+ pr_debug("%s: Invalid cmd=%u. Err=%d\n", __func__, cmd, cmd_in);
+ return cmd_in;
+ }
p = nvdimm_provider_data(nvdimm);
- switch (cmd) {
+ switch (cmd_in) {
case ND_CMD_GET_CONFIG_SIZE:
get_size_hdr = buf;
@@ -333,13 +407,21 @@ 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:
+ /* This happens if subcommand package sanity fails */
+ call_pkg = (struct nd_pkg_papr_scm *) buf;
+ call_pkg->cmd_status = -ENOENT;
+ *cmd_rc = 0;
+ break;
+
default:
- return -EINVAL;
+ dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
+ *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
* [RFC PATCH 3/6] UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-1-vaibhav@linux.ibm.com>
Add PAPR-scm family of DSM command-set to to the white list of NVDIMM
command sets.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
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..0e09dc5cec19 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 5
#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
struct nd_cmd_pkg)
--
2.24.1
^ permalink raw reply related
* [RFC PATCH 2/6] powerpc/papr_scm: Fetch dimm performance stats from PHYP
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-1-vaibhav@linux.ibm.com>
Implement support for fetching dimm performance metrics via
H_SCM_PERFORMANCE_HEALTH hcall as documented in Ref[1]. The hcall
returns a structure as described in Ref[1] and defined as newly
introduced 'struct papr_scm_perf_stats'. The struct has a header
followed by key-value pairs of performance attributes.
The module 'papr_scm' however doesn't interpret or parses these
performance attributes as it will be returning this buffer as it is to
user-space for further parsing. For now we only implement a dimm
specific sysfs attribute named 'papr_stats_version' that returns the
version of the structure returned from H_SCM_PERFORMANCE_HEALTH hcall.
Hence this patch implements a new function drc_pmem_query_stats() that
issues hcall H_SCM_PERFORMANCE_HEALTH ,requesting PHYP to store
performance stats in pre-allocated 'struct papr_scm_perf_stats' buffer
'stats'.
References:
[1]: https://patchwork.ozlabs.org/patch/1154292/
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 56 +++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 1a0cc66f3dc9..deaece6e4d18 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -22,6 +22,16 @@
(1ul << ND_CMD_GET_CONFIG_DATA) | \
(1ul << ND_CMD_SET_CONFIG_DATA))
+#define PAPR_SCM_MAX_PERF_STAT 4096
+
+/* Buffer layout returned by phyp when reporting drc perf stats */
+struct papr_scm_perf_stats {
+ uint8_t version; /* Should be 0x01 */
+ uint8_t reserved1;
+ __be16 size; /* Size of this struct in bytes */
+ uint8_t buffer[]; /* Performance matrics */
+} __packed;
+
struct papr_scm_priv {
struct platform_device *pdev;
struct device_node *dn;
@@ -148,6 +158,25 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
return drc_pmem_bind(p);
}
+static int drc_pmem_query_stats(struct papr_scm_priv *p,
+ struct papr_scm_perf_stats *stats)
+{
+ unsigned long ret[PLPAR_HCALL_BUFSIZE];
+ int64_t rc;
+
+ if (!stats)
+ return -EINVAL;
+
+ rc = plpar_hcall(H_SCM_PERFORMANCE_STATS, ret, p->drc_index,
+ __pa(stats));
+ if (rc != H_SUCCESS) {
+ dev_err(&p->pdev->dev,
+ "Failed to query performance stats, Err:%lld\n", rc);
+ return -ENXIO;
+ } else
+ return 0;
+}
+
static int drc_pmem_query_health(struct papr_scm_priv *p)
{
unsigned long ret[PLPAR_HCALL_BUFSIZE];
@@ -332,6 +361,32 @@ static inline int papr_scm_node(int node)
return min_node;
}
+static ssize_t papr_stats_version_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);
+ struct papr_scm_perf_stats *retbuffer;
+ int rc;
+
+ /* Return buffer for phyp where stats are written */
+ retbuffer = kzalloc(PAPR_SCM_MAX_PERF_STAT, GFP_KERNEL);
+ if (!retbuffer)
+ return -ENOMEM;
+
+ rc = drc_pmem_query_stats(p, retbuffer);
+ if (rc)
+ goto out;
+ else
+ rc = sprintf(buf, "%d\n", retbuffer->version);
+
+out:
+ kfree(retbuffer);
+ return rc;
+
+}
+DEVICE_ATTR_RO(papr_stats_version);
+
static ssize_t papr_health_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -353,6 +408,7 @@ DEVICE_ATTR_RO(papr_health);
/* papr_scm specific dimm attributes */
static struct attribute *papr_scm_nd_attributes[] = {
&dev_attr_papr_health.attr,
+ &dev_attr_papr_stats_version.attr,
NULL,
};
--
2.24.1
^ permalink raw reply related
* [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
In-Reply-To: <20200129152844.71286-1-vaibhav@linux.ibm.com>
Implement support for fetching dimm 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 exposed to userspace via dimm
attribute 'papr_health'.
References:
[1]: https://patchwork.ozlabs.org/patch/1154292/
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
arch/powerpc/platforms/pseries/papr_scm.c | 65 ++++++++++++++++++++++-
1 file changed, 63 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 0b4467e378e5..1a0cc66f3dc9 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -39,6 +39,10 @@ struct papr_scm_priv {
struct resource res;
struct nd_region *region;
struct nd_interleave_set nd_set;
+
+ /* Health information for the dimm */
+ __be64 health_bitmap;
+ __be64 health_bitmap_valid;
};
static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -144,6 +148,30 @@ 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;
+ }
+
+ /* 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));
+
+ return 0;
+}
static int papr_scm_meta_get(struct papr_scm_priv *p,
struct nd_cmd_get_config_data_hdr *hdr)
@@ -304,6 +332,39 @@ static inline int papr_scm_node(int node)
return min_node;
}
+static ssize_t papr_health_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);
+ int rc;
+
+ rc = drc_pmem_query_health(p);
+
+ if (rc)
+ return rc;
+ else
+ return sprintf(buf, "0x%016llX 0x%016llX\n",
+ be64_to_cpu(p->health_bitmap),
+ be64_to_cpu(p->health_bitmap_valid));
+}
+DEVICE_ATTR_RO(papr_health);
+
+/* papr_scm specific dimm attributes */
+static struct attribute *papr_scm_nd_attributes[] = {
+ &dev_attr_papr_health.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 +391,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;
--
2.24.1
^ permalink raw reply related
* [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
To: linuxppc-dev
Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
Aneesh Kumar K . V
The PAPR standard provides suitable 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 fetched in the papr_scm modules 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 RFC patch-set proposes a new set of
Dimm-Specific-Methods(DSM) for querying and fetching health and stat information
for dimms that support PAPR and provides an implementation in kernel for these
DSM in papr_scm modules. These changes coupled with draft/proposed ndtcl changes
located at Ref[4] should provide a way for user to retributive NVDIMM status
using ndtcl. Below is a sample output using proposed kernel + ndctl for PAPR
NVDIMM in an emulation environment:
# ndctl list -DH
[
{
"dev":"nmem0",
"health":{
"health_state":"fatal",
"life_used_percentage":60,
"shutdown_state":"dirty"
}
}
]
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 RFC proposes two DSMs that directly map to
hcalls provided by PHYP to query NVDIMM health and stats. These DSMs are:
* DSM_PAPR_SCM_HEALTH: Which map to hcall H_SCM_HEALTH and returns dimm health.
* DSM_PAPR_SCM_STATS: Which map to hcall H_SCM_PERFORMANCE_STATS and returns
dimm performance stats.
The ioctl ND_CMD_CALL can also transfer data between
user-space and kernel via 'envelopes'. The envelop is part of a
'struct nd_cmd_pkg' which in return is wrapped in a user defined struct which
in our case is called 'struct nd_pkg_papr_scm' (packaged). These struct is
defined as:
struct nd_pkg_papr_scm {
struct nd_cmd_pkg hdr; /* Package header containing sub-cmd */
uint32_t cmd_status; /* Out: Sub-cmd status returned back */
uint8_t payload[]; /* Out: Sub-cmd data buffer */
};
The 'payload' field of the package holds the libnvdimm defined 'envelope' which
is used to send/receive data from userspace buffer (libndctl). This RFC uses this
field to copy the results of hcalls that are executed in response to the DSM
commands.
Please note that results of hcalls are not interpreted (with few exceptions) in
papr_scm module at all. Instead they are directly copied to the 'payload' field
and sent to userspace(libndctl) for interpretation. This essentially means that
the papr_scm module simply acts as a conduit for libndctl to issue hcalls and
fetch its output. This should make parsing and interpreting with output buffers
of hcalls easier as it can be performed in userspace.
References:
[1]: "Power Architecture Platform Reference"
https://en.wikipedia.org/wiki/Power_Architecture_Platform_Reference
[2]: "[DOC,v2] powerpc: Provide initial documentation for PAPR hcalls"
https://patchwork.ozlabs.org/patch/1154292/
[3]: "Linux on Power Architecture Platform Reference"
https://members.openpowerfoundation.org/document/dl/469
[4]: https://github.com/vaibhav92/ndctl/tree/papr_scm_health
Vaibhav Jain (6):
powerpc/papr_scm: Provide support for fetching dimm health information
powerpc/papr_scm: Fetch dimm performance stats from PHYP
UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family
powerpc/papr_scm: Add support for handling PAPR DSM commands
powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS
arch/powerpc/platforms/pseries/papr_scm.c | 314 +++++++++++++++++++++-
include/uapi/linux/ndctl.h | 1 +
2 files changed, 306 insertions(+), 9 deletions(-)
--
2.24.1
^ permalink raw reply
* [PATCH v6 4/5] powerpc/numa: Early request for home node associativity
From: Srikar Dronamraju @ 2020-01-29 13:53 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Satheesh Rajendran, linuxppc-dev, Srikar Dronamraju,
Nicholas Piggin
In-Reply-To: <20200129135301.24739-1-srikar@linux.vnet.ibm.com>
Currently the kernel detects if its running on a shared lpar platform
and requests home node associativity before the scheduler sched_domains
are setup. However between the time NUMA setup is initialized and the
request for home node associativity, workqueue initializes its per node
cpumask. The per node workqueue possible cpumask may turn invalid
after home node associativity resulting in weird situations like
workqueue possible cpumask being a subset of workqueue online cpumask.
This can be fixed by requesting home node associativity earlier just
before NUMA setup. However at the NUMA setup time, kernel may not be in
a position to detect if its running on a shared lpar platform. So
request for home node associativity and if the request fails, fallback
on the device tree property.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
---
Changelog (v5->v6):
- Handled comments from Michael Ellerman
* hardware-id is now deciphered in vphn_get_nid
* No need to pass extra bool
Changelog (v2->v3):
- Handled comments from Nathan Lynch
* Use first thread of the core for cpu-to-node map.
* get hardware-id in numa_setup_cpu
Changelog (v1->v2):
- Handled comments from Nathan Lynch
* Dont depend on pacas to be setup for the hwid
arch/powerpc/mm/numa.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 63ec0c3..ee7400f 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -461,6 +461,41 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb)
return nid;
}
+#ifdef CONFIG_PPC_SPLPAR
+static int vphn_get_nid(long lcpu)
+{
+ __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+ long rc, hwid;
+
+ /*
+ * On a shared lpar, device tree will not have node associativity.
+ * At this time lppaca, or its __old_status field may not be
+ * updated. Hence kernel cannot detect if its on a shared lpar. So
+ * request an explicit associativity irrespective of whether the
+ * lpar is shared or dedicated. Use the device tree property as a
+ * fallback. cpu_to_phys_id is only valid between
+ * smp_setup_cpu_maps() and smp_setup_pacas().
+ */
+ if (firmware_has_feature(FW_FEATURE_VPHN)) {
+ if (cpu_to_phys_id)
+ hwid = cpu_to_phys_id[lcpu];
+ else
+ hwid = get_hard_smp_processor_id(lcpu);
+
+ rc = hcall_vphn(hwid, VPHN_FLAG_VCPU, associativity);
+ if (rc == H_SUCCESS)
+ return associativity_to_nid(associativity);
+ }
+
+ return NUMA_NO_NODE;
+}
+#else
+static int vphn_get_nid(long unused)
+{
+ return NUMA_NO_NODE;
+}
+#endif /* CONFIG_PPC_SPLPAR */
+
/*
* Figure out to which domain a cpu belongs and stick it there.
* Return the id of the domain used.
@@ -485,6 +520,10 @@ static int numa_setup_cpu(unsigned long lcpu)
return nid;
}
+ nid = vphn_get_nid(lcpu);
+ if (nid != NUMA_NO_NODE)
+ goto out_present;
+
cpu = of_get_cpu_node(lcpu, NULL);
if (!cpu) {
@@ -496,6 +535,7 @@ static int numa_setup_cpu(unsigned long lcpu)
}
nid = of_node_to_nid_single(cpu);
+ of_node_put(cpu);
out_present:
if (nid < 0 || !node_possible(nid))
@@ -515,7 +555,6 @@ static int numa_setup_cpu(unsigned long lcpu)
}
map_cpu_to_node(lcpu, nid);
- of_node_put(cpu);
out:
return nid;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 5/5] powerpc/numa: Remove late request for home node associativity
From: Srikar Dronamraju @ 2020-01-29 13:53 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Srikar Dronamraju, Nicholas Piggin, Abdul Haleem,
Satheesh Rajendran, linuxppc-dev
In-Reply-To: <20200129135301.24739-1-srikar@linux.vnet.ibm.com>
With commit ("powerpc/numa: Early request for home node associativity"),
commit 2ea626306810 ("powerpc/topology: Get topology for shared
processors at boot") which was requesting home node associativity
becomes redundant.
Hence remove the late request for home node associativity.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Reviewed-by: Nathan Lynch <nathanl@linux.ibm.com>
---
arch/powerpc/include/asm/topology.h | 4 ----
arch/powerpc/kernel/smp.c | 5 -----
arch/powerpc/mm/numa.c | 9 ---------
3 files changed, 18 deletions(-)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 2f7e1ea..9bd396f 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -98,7 +98,6 @@ static inline int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
extern int prrn_is_enabled(void);
extern int find_and_online_cpu_nid(int cpu);
extern int timed_topology_update(int nsecs);
-extern void __init shared_proc_topology_init(void);
#else
static inline int start_topology_update(void)
{
@@ -121,9 +120,6 @@ static inline int timed_topology_update(int nsecs)
return 0;
}
-#ifdef CONFIG_SMP
-static inline void shared_proc_topology_init(void) {}
-#endif
#endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */
#include <asm-generic/topology.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ea6adbf..cdd39a0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -1359,11 +1359,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
if (smp_ops && smp_ops->bringup_done)
smp_ops->bringup_done();
- /*
- * On a shared LPAR, associativity needs to be requested.
- * Hence, get numa topology before dumping cpu topology
- */
- shared_proc_topology_init();
dump_numa_cpu_topology();
#ifdef CONFIG_SCHED_SMT
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index ee7400f..01a03f2 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1632,15 +1632,6 @@ int prrn_is_enabled(void)
return prrn_enabled;
}
-void __init shared_proc_topology_init(void)
-{
- if (lppaca_shared_proc(get_lppaca())) {
- bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask),
- nr_cpumask_bits);
- numa_update_cpu_topology(false);
- }
-}
-
static int topology_read(struct seq_file *file, void *v)
{
if (vphn_enabled || prrn_enabled)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 2/5] powerpc/numa: Handle extra hcall_vphn error cases
From: Srikar Dronamraju @ 2020-01-29 13:52 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Srikar Dronamraju, Nicholas Piggin, Abdul Haleem,
Satheesh Rajendran, linuxppc-dev
In-Reply-To: <20200129135301.24739-1-srikar@linux.vnet.ibm.com>
Currently code handles H_FUNCTION, H_SUCCESS, H_HARDWARE return codes.
However hcall_vphn can return other return codes. Now it also handles
H_PARAMETER return code. Also the rest return codes are handled under the
default case.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Reviewed-by: Nathan Lynch <nathanl@linux.ibm.com>
---
Changelog (v2->v1):
Handled comments from Nathan:
- Split patch from patch 1.
- Corrected a problem where I missed calling stop_topology_update().
- Using pr_err_ratelimited instead of printk.
arch/powerpc/mm/numa.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 50d68d2..8fbe57c 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1191,23 +1191,30 @@ static long vphn_get_associativity(unsigned long cpu,
VPHN_FLAG_VCPU, associativity);
switch (rc) {
+ case H_SUCCESS:
+ dbg("VPHN hcall succeeded. Reset polling...\n");
+ timed_topology_update(0);
+ goto out;
+
case H_FUNCTION:
- printk_once(KERN_INFO
- "VPHN is not supported. Disabling polling...\n");
- stop_topology_update();
+ pr_err_ratelimited("VPHN unsupported. Disabling polling...\n");
break;
case H_HARDWARE:
- printk(KERN_ERR
- "hcall_vphn() experienced a hardware fault "
+ pr_err_ratelimited("hcall_vphn() experienced a hardware fault "
"preventing VPHN. Disabling polling...\n");
- stop_topology_update();
break;
- case H_SUCCESS:
- dbg("VPHN hcall succeeded. Reset polling...\n");
- timed_topology_update(0);
+ case H_PARAMETER:
+ pr_err_ratelimited("hcall_vphn() was passed an invalid parameter. "
+ "Disabling polling...\n");
+ break;
+ default:
+ pr_err_ratelimited("hcall_vphn() returned %ld. Disabling polling...\n"
+ , rc);
break;
}
+ stop_topology_update();
+out:
return rc;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 3/5] powerpc/numa: Use cpu node map of first sibling thread
From: Srikar Dronamraju @ 2020-01-29 13:52 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Srikar Dronamraju, Nicholas Piggin, Abdul Haleem,
Satheesh Rajendran, linuxppc-dev
In-Reply-To: <20200129135301.24739-1-srikar@linux.vnet.ibm.com>
All the sibling threads of a core have to be part of the same node.
To ensure that all the sibling threads map to the same node, always
lookup/update the cpu-to-node map of the first thread in the core.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Reviewed-by: Nathan Lynch <nathanl@linux.ibm.com>
---
Changelog: v3->v4
As suggested by Nathan, add a warning while mapping offline cpu.
arch/powerpc/mm/numa.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 8fbe57c..63ec0c3 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -467,15 +467,20 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb)
*/
static int numa_setup_cpu(unsigned long lcpu)
{
- int nid = NUMA_NO_NODE;
struct device_node *cpu;
+ int fcpu = cpu_first_thread_sibling(lcpu);
+ int nid = NUMA_NO_NODE;
/*
* If a valid cpu-to-node mapping is already available, use it
* directly instead of querying the firmware, since it represents
* the most recent mapping notified to us by the platform (eg: VPHN).
+ * Since cpu_to_node binding remains the same for all threads in the
+ * core. If a valid cpu-to-node mapping is already available, for
+ * the first thread in the core, use it.
*/
- if ((nid = numa_cpu_lookup_table[lcpu]) >= 0) {
+ nid = numa_cpu_lookup_table[fcpu];
+ if (nid >= 0) {
map_cpu_to_node(lcpu, nid);
return nid;
}
@@ -496,6 +501,19 @@ static int numa_setup_cpu(unsigned long lcpu)
if (nid < 0 || !node_possible(nid))
nid = first_online_node;
+ /*
+ * Update for the first thread of the core. All threads of a core
+ * have to be part of the same node. This not only avoids querying
+ * for every other thread in the core, but always avoids a case
+ * where virtual node associativity change causes subsequent threads
+ * of a core to be associated with different nid. However if first
+ * thread is already online, expect it to have a valid mapping.
+ */
+ if (fcpu != lcpu) {
+ WARN_ON(cpu_online(fcpu));
+ map_cpu_to_node(fcpu, nid);
+ }
+
map_cpu_to_node(lcpu, nid);
of_node_put(cpu);
out:
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 1/5] powerpc/vphn: Check for error from hcall_vphn
From: Srikar Dronamraju @ 2020-01-29 13:52 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Srikar Dronamraju, Nicholas Piggin, Abdul Haleem,
Satheesh Rajendran, linuxppc-dev
In-Reply-To: <20200129135301.24739-1-srikar@linux.vnet.ibm.com>
There is no value in unpacking associativity, if
H_HOME_NODE_ASSOCIATIVITY hcall has returned an error.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Reviewed-by: Nathan Lynch <nathanl@linux.ibm.com>
---
Changelog (v2->v1):
- Split the patch into 2(Suggested by Nathan).
arch/powerpc/platforms/pseries/vphn.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/pseries/vphn.c b/arch/powerpc/platforms/pseries/vphn.c
index 3f07bf6..cca474a 100644
--- a/arch/powerpc/platforms/pseries/vphn.c
+++ b/arch/powerpc/platforms/pseries/vphn.c
@@ -82,7 +82,8 @@ long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity)
long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, cpu);
- vphn_unpack_associativity(retbuf, associativity);
+ if (rc == H_SUCCESS)
+ vphn_unpack_associativity(retbuf, associativity);
return rc;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 0/5] Early node associativity
From: Srikar Dronamraju @ 2020-01-29 13:52 UTC (permalink / raw)
To: Michael Ellerman
Cc: Nathan Lynch, Srikar Dronamraju, Nicholas Piggin, Abdul Haleem,
Satheesh Rajendran, linuxppc-dev
Note: (Only patch 4 changes from v5)
Abdul reported a warning on a shared lpar.
"WARNING: workqueue cpumask: online intersect > possible intersect".
This is because per node workqueue possible mask is set very early in the
boot process even before the system was querying the home node
associativity. However per node workqueue online cpumask gets updated
dynamically. Hence there is a chance when per node workqueue online cpumask
is a superset of per node workqueue possible mask.
Link for v5: http://lkml.kernel.org/r/20191216144904.6776-1-srikar@linux.vnet.ibm.com
Changelog: v5->v6
- Handled comments from Michael Ellerman
- Rebased to v5.5-rc6
Link for v4: https://patchwork.ozlabs.org/patch/1161979
Changelog: v4->v5:
- Rebased to v5.5-rc2
Link for v3: http://lkml.kernel.org/r/20190906135020.19772-1-srikar@linux.vnet.ibm.com
Changelog: v3->v4
- Added a warning as suggested by Nathan Lynch.
Link for v2: http://lkml.kernel.org/r/20190829055023.6171-1-srikar@linux.vnet.ibm.com
Changelog: v2->v3
- Handled comments from Nathan Lynch.
Link for v1: https://patchwork.ozlabs.org/patch/1151658
Changelog: v1->v2
- Handled comments from Nathan Lynch.
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
Srikar Dronamraju (5):
powerpc/vphn: Check for error from hcall_vphn
powerpc/numa: Handle extra hcall_vphn error cases
powerpc/numa: Use cpu node map of first sibling thread
powerpc/numa: Early request for home node associativity
powerpc/numa: Remove late request for home node associativity
arch/powerpc/include/asm/topology.h | 4 --
arch/powerpc/kernel/smp.c | 5 --
arch/powerpc/mm/numa.c | 97 +++++++++++++++++++++++++++--------
arch/powerpc/platforms/pseries/vphn.c | 3 +-
4 files changed, 78 insertions(+), 31 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH v4] powerpc/smp: Use nid as fallback for package_id
From: Srikar Dronamraju @ 2020-01-29 13:51 UTC (permalink / raw)
To: Michael Ellerman
Cc: Vasant Hegde, Vaidyanathan Srinivasan, linuxppc-dev,
Srikar Dronamraju
Package_id is to find out all cores that are part of the same chip. On
PowerNV machines, package_id defaults to chip_id. However ibm,chip_id
property is not present in device-tree of PowerVM Lpars. Hence lscpu
output shows one core per socket and multiple cores.
To overcome this, use nid as the package_id on PowerVM Lpars.
Before the patch.
---------------
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 8
Core(s) per socket: 1 <----------------------
Socket(s): 16 <----------------------
NUMA node(s): 2
Model: 2.2 (pvr 004e 0202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: pHyp
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
L2 cache: 512K
L3 cache: 10240K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
#
# cat /sys/devices/system/cpu/cpu0/topology/physical_package_id
-1
#
After the patch
---------------
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 8 <------------------------------
Core(s) per socket: 8 <------------------------------
Socket(s): 2
NUMA node(s): 2
Model: 2.2 (pvr 004e 0202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: pHyp
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
L2 cache: 512K
L3 cache: 10240K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
#
# cat /sys/devices/system/cpu/cpu0/topology/physical_package_id
0
#
Now lscpu output is more in line with the system configuration.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Cc: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
---
Changelog from v3: https://lore.kernel.org/linuxppc-dev/20191216142119.5937-1-srikar@linux.vnet.ibm.com/t/#u
- Handled comments from Michael Ellerman.
- Rename function cpu_to_nid to get_physical_package_id
- Moved code back to arch/powerpc/kernel/smp.c from pseries/lpar.c
- Use export_symbol_gpl instead of export_symbol.
- Rebased to v5.5-rc6
Changelog from v2: https://patchwork.ozlabs.org/patch/1151649
- Rebased to v5.5-rc2
- Renamed the new function to cpu_to_nid
- Removed checks to fadump property. (Looked too excessive)
- Moved pseries specific code to pseries/lpar.c
Changelog from v1: https://patchwork.ozlabs.org/patch/1126145
- In v1 cpu_to_chip_id was overloaded to fallback on nid. Michael
Ellerman wasn't comfortable with nid being shown up as chip_id.
arch/powerpc/include/asm/topology.h | 6 ++++++
arch/powerpc/kernel/smp.c | 30 ++++++++++++++++++++++++++---
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 2f7e1ea5089e..e2e1ccd4a18d 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -134,7 +134,13 @@ static inline void shared_proc_topology_init(void) {}
#ifdef CONFIG_PPC64
#include <asm/smp.h>
+#ifdef CONFIG_PPC_SPLPAR
+int get_physical_package_id(int cpu);
+#define topology_physical_package_id(cpu) (get_physical_package_id(cpu))
+#else
#define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu))
+#endif
+
#define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
#define topology_core_id(cpu) (cpu_to_core_id(cpu))
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ea6adbf6a221..d75fc8fd8168 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -1185,10 +1185,34 @@ static inline void add_cpu_to_smallcore_masks(int cpu)
}
}
+int get_physical_package_id(int cpu)
+{
+ int ppid = cpu_to_chip_id(cpu);
+
+#ifdef CONFIG_PPC_SPLPAR
+ /*
+ * If the platform is PowerNV or Guest on KVM, ibm,chip-id is
+ * defined. Hence we would return the chip-id as the
+ * get_physical_package_id.
+ */
+ if (ppid == -1 && firmware_has_feature(FW_FEATURE_LPAR)) {
+ struct device_node *np = of_get_cpu_node(cpu, NULL);
+
+ if (np) {
+ ppid = of_node_to_nid(np);
+ of_node_put(np);
+ }
+ }
+#endif /* CONFIG_PPC_SPLPAR */
+
+ return ppid;
+}
+EXPORT_SYMBOL_GPL(get_physical_package_id);
+
static void add_cpu_to_masks(int cpu)
{
int first_thread = cpu_first_thread_sibling(cpu);
- int chipid = cpu_to_chip_id(cpu);
+ int ppid = get_physical_package_id(cpu);
int i;
/*
@@ -1217,11 +1241,11 @@ static void add_cpu_to_masks(int cpu)
for_each_cpu(i, cpu_l2_cache_mask(cpu))
set_cpus_related(cpu, i, cpu_core_mask);
- if (chipid == -1)
+ if (ppid == -1)
return;
for_each_cpu(i, cpu_online_mask)
- if (cpu_to_chip_id(i) == chipid)
+ if (get_physical_package_id(i) == ppid)
set_cpus_related(cpu, i, cpu_core_mask);
}
--
2.18.1
^ permalink raw reply related
* Re: powerpc Linux scv support and scv system call ABI proposal
From: Segher Boessenkool @ 2020-01-29 13:20 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: linuxppc-dev, Adhemerval Zanella
In-Reply-To: <1580273424.ea818exa2c.astroid@bobo.none>
On Wed, Jan 29, 2020 at 02:58:44PM +1000, Nicholas Piggin wrote:
> Adhemerval Zanella's on January 29, 2020 3:26 am:
> > __asm__ __volatile__ \
> > ("sc\n\t" \
> > "bns+ 1f\n\t" \
> > "neg %1, %1\n\t" \
> > "1:\n\t" \
> True, but the taken branch would be a 1 cycle bubble in fetch. Could
> avoid that by branching out of line then back for the error case. But
> mfocrf is fine (only sources one register), that's what should be used
> here I think.
neg %9,%1 ; isel %1,%9,%1,so
> That probably makes the performance argument for avoiding CR[SO] for
> error return indication less significant. Commonality with other
> architectures is probably the bigger reason for it.
Yes, and to have the syscall calling convention closer to the normal
function calling convention would be good, too.
Segher
^ permalink raw reply
* [PATCH] powerpc/32s: Fix kasan_early_hash_table() for CONFIG_VMAP_STACK
From: Christophe Leroy @ 2020-01-29 12:34 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
On book3s/32 CPUs that are handling MMU through a hash table,
MMU_init_hw() function was adapted for VMAP_STACK in order to
handle virtual addresses instead of physical addresses in the
low level hash functions.
When using KASAN, the same adaptations are required for the
early hash table set up by kasan_early_hash_table() function.
Fixes: cd08f109e262 ("powerpc/32s: Enable CONFIG_VMAP_STACK")
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/kasan/kasan_init_32.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/kasan_init_32.c
index d3cacd462560..16dd95bd0749 100644
--- a/arch/powerpc/mm/kasan/kasan_init_32.c
+++ b/arch/powerpc/mm/kasan/kasan_init_32.c
@@ -185,8 +185,11 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
static void __init kasan_early_hash_table(void)
{
- modify_instruction_site(&patch__hash_page_A0, 0xffff, __pa(early_hash) >> 16);
- modify_instruction_site(&patch__flush_hash_A0, 0xffff, __pa(early_hash) >> 16);
+ unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
+ __pa(early_hash);
+
+ modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
+ modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
Hash = (struct hash_pte *)early_hash;
}
--
2.25.0
^ permalink raw reply related
* Re: [PATCH V12] mm/debug: Add tests validating architecture page table helpers
From: Qian Cai @ 2020-01-29 11:09 UTC (permalink / raw)
To: Catalin Marinas
Cc: Mark Rutland, linux-ia64, linux-sh, Peter Zijlstra, James Hogan,
Heiko Carstens, Michal Hocko, Linux-MM, Paul Mackerras,
sparclinux, Ingo Molnar, linux-s390, Jason Gunthorpe,
the arch/x86 maintainers, Russell King - ARM Linux,
Matthew Wilcox, Steven Price, Tetsuo Handa, Vlastimil Babka,
linux-snps-arc, Kees Cook, Anshuman Khandual, Gerald Schaefer,
Mark Brown, Kirill A . Shutemov, Dan Williams, linux-arm-kernel,
Sri Krishna chowdary, Masahiro Yamada, Greg Kroah-Hartman,
Ard Biesheuvel, Dave Hansen, linux-mips, Ralf Baechle,
linux-kernel, Paul Burton, Mike Rapoport, Thomas Gleixner,
Vineet Gupta, Martin Schwidefsky, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <20200129103640.GA668562@arrakis.emea.arm.com>
> On Jan 29, 2020, at 5:36 AM, Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> On Tue, Jan 28, 2020 at 02:07:10PM -0500, Qian Cai wrote:
>> On Jan 28, 2020, at 12:47 PM, Catalin Marinas <catalin.marinas@arm.com> wrote:
>>> The primary goal here is not finding regressions but having clearly
>>> defined semantics of the page table accessors across architectures. x86
>>> and arm64 are a good starting point and other architectures will be
>>> enabled as they are aligned to the same semantics.
>>
>> This still does not answer the fundamental question. If this test is
>> simply inefficient to find bugs,
>
> Who said this is inefficient (other than you)?
Inefficient of finding bugs. It said only found a bug or two in its lifetime?
>
>> who wants to spend time to use it regularly?
>
> Arch maintainers, mm maintainers introducing new macros or assuming
> certain new semantics of the existing macros.
>
>> If this is just one off test that may get running once in a few years
>> (when introducing a new arch), how does it justify the ongoing cost to
>> maintain it?
>
> You are really missing the point. It's not only for a new arch but
> changes to existing arch code. And if the arch code churn in this area
> is relatively small, I'd expect a similarly small cost of maintaining
> this test.
>
> If you only turn DEBUG_VM on once every few years, don't generalise this
> to the rest of the kernel developers (as others pointed out, this test
> is default y if DEBUG_VM).
Quite the opposite, I am running DEBUG_VM almost daily for regression
workload while I felt strongly this thing does not add any value mixing there.
So, I would suggest to decouple this away from DEBUG_VM, and clearly
document that this test is not something intended for automated regression
workloads, so those people don’t need to waste time running this.
>
> Anyway, I think that's a pointless discussion, so not going to reply
> further (unless you have technical content to add).
>
> --
> Catalin
^ permalink raw reply
* [PATCH v2] powerpc/uaccess: simplify the get_fs() set_fs() logic
From: Christophe Leroy @ 2020-01-29 11:00 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
On powerpc, we only have USER_DS and KERNEL_DS
Today, this is managed as an 'unsigned long' data space limit
which is used to compare the passed address with, plus a bit
in the thread_info flags that is set whenever modifying the limit
to enable the verification in addr_limit_user_check()
The limit is either the last address of user space when USER_DS is
set, and the last address of address space when KERNEL_DS is set.
In both cases, the limit is a compiletime constant.
get_fs() returns the limit, which is part of thread_info struct
set_fs() updates the limit then set the TI_FSCHECK flag.
addr_limit_user_check() check the flag, and if it is set it checks
the limit is the user limit, then unsets the TI_FSCHECK flag.
In addition, when the flag is set the syscall exit work is involved.
This exit work is heavy compared to normal syscall exit as it goes
through normal exception exit instead of the fast syscall exit.
Rename this TI_FSCHECK flag to TIF_KERNEL_DS flag which tells whether
KERNEL_DS or USER_DS is set. Get mm_segment_t be redifined as a bool
struct that is either false (for USER_DS) or true (for KERNEL_DS).
When TIF_KERNEL_DS is set, the limit is ~0UL. Otherwise it is
TASK_SIZE_USER (resp TASK_SIZE_USER64 on PPC64). When KERNEL_DS is
set, there is no range to check. Define TI_FSCHECK as an alias to
TIF_KERNEL_DS.
On exit, involve exit work when the bit is set, i.e. when KERNEL_DS
is set. addr_limit_user_check() will clear the bit and kill the
user process.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/processor.h | 5 +---
arch/powerpc/include/asm/thread_info.h | 9 ++++---
arch/powerpc/include/asm/uaccess.h | 35 +++++++++++++-------------
arch/powerpc/lib/sstep.c | 2 +-
4 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 8387698bd5b6..e9e3c3b0f05e 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -84,7 +84,7 @@ void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
void release_thread(struct task_struct *);
typedef struct {
- unsigned long seg;
+ bool is_kernel_ds;
} mm_segment_t;
#define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET]
@@ -148,7 +148,6 @@ struct thread_struct {
unsigned long ksp_vsid;
#endif
struct pt_regs *regs; /* Pointer to saved register state */
- mm_segment_t addr_limit; /* for get_fs() validation */
#ifdef CONFIG_BOOKE
/* BookE base exception scratch space; align on cacheline */
unsigned long normsave[8] ____cacheline_aligned;
@@ -289,7 +288,6 @@ struct thread_struct {
#define INIT_THREAD { \
.ksp = INIT_SP, \
.ksp_limit = INIT_SP_LIMIT, \
- .addr_limit = KERNEL_DS, \
.pgdir = swapper_pg_dir, \
.fpexc_mode = MSR_FE0 | MSR_FE1, \
SPEFSCR_INIT \
@@ -298,7 +296,6 @@ struct thread_struct {
#define INIT_THREAD { \
.ksp = INIT_SP, \
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
- .addr_limit = KERNEL_DS, \
.fpexc_mode = 0, \
.fscr = FSCR_TAR | FSCR_EBB \
}
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index a2270749b282..a681ce624ab7 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -69,7 +69,7 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \
{ \
.preempt_count = INIT_PREEMPT_COUNT, \
- .flags = 0, \
+ .flags = _TIF_KERNEL_DS, \
}
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
@@ -90,7 +90,8 @@ void arch_setup_new_exec(void);
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_FSCHECK 3 /* Check FS is USER_DS on return */
+#define TIF_KERNEL_DS 3 /* KERNEL_DS is set */
+#define TIF_FSCHECK TIF_KERNEL_DS
#define TIF_SYSCALL_EMU 4 /* syscall emulation active */
#define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */
#define TIF_PATCH_PENDING 6 /* pending live patching update */
@@ -130,7 +131,7 @@ void arch_setup_new_exec(void);
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE)
#define _TIF_NOHZ (1<<TIF_NOHZ)
-#define _TIF_FSCHECK (1<<TIF_FSCHECK)
+#define _TIF_KERNEL_DS (1 << TIF_KERNEL_DS)
#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)
#define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \
@@ -139,7 +140,7 @@ void arch_setup_new_exec(void);
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
_TIF_RESTORE_TM | _TIF_PATCH_PENDING | \
- _TIF_FSCHECK)
+ _TIF_KERNEL_DS)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index c92fe7fe9692..391c3a26f980 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -21,43 +21,44 @@
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define KERNEL_DS MAKE_MM_SEG(~0UL)
-#ifdef __powerpc64__
-/* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */
-#define USER_DS MAKE_MM_SEG(TASK_SIZE_USER64 - 1)
-#else
-#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
-#endif
+#define KERNEL_DS MAKE_MM_SEG(true)
+#define USER_DS MAKE_MM_SEG(false)
+
+#define get_fs() (MAKE_MM_SEG(test_thread_flag(TIF_KERNEL_DS)))
-#define get_fs() (current->thread.addr_limit)
+#define segment_eq(a, b) ((a).is_kernel_ds == (b).is_kernel_ds)
static inline void set_fs(mm_segment_t fs)
{
- current->thread.addr_limit = fs;
- /* On user-mode return check addr_limit (fs) is correct */
- set_thread_flag(TIF_FSCHECK);
+ update_thread_flag(TIF_KERNEL_DS, segment_eq(fs, KERNEL_DS));
}
-#define segment_eq(a, b) ((a).seg == (b).seg)
-
-#define user_addr_max() (get_fs().seg)
+#define user_addr_max() (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : END_OF_USER_DS - 1)
#ifdef __powerpc64__
+
+#define END_OF_USER_DS TASK_SIZE_USER64
+
/*
* This check is sufficient because there is a large enough
* gap between user addresses and the kernel addresses
*/
#define __access_ok(addr, size, segment) \
- (((addr) <= (segment).seg) && ((size) <= (segment).seg))
+ segment_eq(segment, KERNEL_DS) ? \
+ 1 : (addr) < END_OF_USER_DS && ((size) < END_OF_USER_DS)
#else
+#define END_OF_USER_DS TASK_SIZE
+
static inline int __access_ok(unsigned long addr, unsigned long size,
mm_segment_t seg)
{
- if (addr > seg.seg)
+ if (segment_eq(seg, KERNEL_DS))
+ return 1;
+ if (addr >= END_OF_USER_DS)
return 0;
- return (size == 0 || size - 1 <= seg.seg - addr);
+ return addr + size <= END_OF_USER_DS;
}
#endif
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index c077acb983a1..bf005dd9407e 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -110,7 +110,7 @@ static nokprobe_inline long address_ok(struct pt_regs *regs,
return 1;
if (__access_ok(ea, 1, USER_DS))
/* Access overlaps the end of the user region */
- regs->dar = USER_DS.seg;
+ regs->dar = END_OF_USER_DS;
else
regs->dar = ea;
return 0;
--
2.25.0
^ permalink raw reply related
* [PATCH v1] powerpc/uaccess: simplify the get_fs() set_fs() logic
From: Christophe Leroy @ 2020-01-29 11:00 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
On powerpc, we only have USER_DS and KERNEL_DS
Today, this is managed as an 'unsigned long' data space limit
which is used to compare the passed address with, plus a bit
in the thread_info flags that is set whenever modifying the limit
to enable the verification in addr_limit_user_check()
The limit is either the last address of user space when USER_DS is
set, and the last address of address space when KERNEL_DS is set.
In both cases, the limit is a compiletime constant.
get_fs() returns the limit, which is part of thread_info struct
set_fs() updates the limit then set the TI_FSCHECK flag.
addr_limit_user_check() check the flag, and if it is set it checks
the limit is the user limit, then unsets the TI_FSCHECK flag.
In addition, when the flag is set the syscall exit work is involved.
Remove this TI_FSCHECK flag, and replace it by a TIF_KERNEL_DS flag
which tells whether KERNEL_DS or USER_DS is set. When TIF_KERNEL_DS
is set, the limit is ~0UL. Otherwise it is TASK_SIZE_USER (resp
TASK_SIZE_USER64 on PPC64). When KERNEL_DS is set, there is no range
to check.
On exit, involve exit work when the bit is set, i.e. when KERNEL_DS
is set. As TI_FSCHECK is not set anymore, test will be done everytime
exit work is run, but doing the check is now as costly as checking
whether the check is to be done.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
This version is first version. The intention was to not modify things
much, but the resulting assembly is bad, so lets take v2 instead.
---
arch/powerpc/include/asm/processor.h | 3 ---
arch/powerpc/include/asm/thread_info.h | 8 ++++----
arch/powerpc/include/asm/uaccess.h | 10 ++++------
3 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 8387698bd5b6..0747f930a680 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -148,7 +148,6 @@ struct thread_struct {
unsigned long ksp_vsid;
#endif
struct pt_regs *regs; /* Pointer to saved register state */
- mm_segment_t addr_limit; /* for get_fs() validation */
#ifdef CONFIG_BOOKE
/* BookE base exception scratch space; align on cacheline */
unsigned long normsave[8] ____cacheline_aligned;
@@ -289,7 +288,6 @@ struct thread_struct {
#define INIT_THREAD { \
.ksp = INIT_SP, \
.ksp_limit = INIT_SP_LIMIT, \
- .addr_limit = KERNEL_DS, \
.pgdir = swapper_pg_dir, \
.fpexc_mode = MSR_FE0 | MSR_FE1, \
SPEFSCR_INIT \
@@ -298,7 +296,6 @@ struct thread_struct {
#define INIT_THREAD { \
.ksp = INIT_SP, \
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
- .addr_limit = KERNEL_DS, \
.fpexc_mode = 0, \
.fscr = FSCR_TAR | FSCR_EBB \
}
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index a2270749b282..8980bbddc4d6 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -69,7 +69,7 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \
{ \
.preempt_count = INIT_PREEMPT_COUNT, \
- .flags = 0, \
+ .flags = _TIF_KERNEL_DS, \
}
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
@@ -90,7 +90,7 @@ void arch_setup_new_exec(void);
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_FSCHECK 3 /* Check FS is USER_DS on return */
+#define TIF_KERNEL_DS 3 /* KERNEL_DS is set */
#define TIF_SYSCALL_EMU 4 /* syscall emulation active */
#define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */
#define TIF_PATCH_PENDING 6 /* pending live patching update */
@@ -130,7 +130,7 @@ void arch_setup_new_exec(void);
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE)
#define _TIF_NOHZ (1<<TIF_NOHZ)
-#define _TIF_FSCHECK (1<<TIF_FSCHECK)
+#define _TIF_KERNEL_DS (1 << TIF_KERNEL_DS)
#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)
#define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \
@@ -139,7 +139,7 @@ void arch_setup_new_exec(void);
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
_TIF_RESTORE_TM | _TIF_PATCH_PENDING | \
- _TIF_FSCHECK)
+ _TIF_KERNEL_DS)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index c92fe7fe9692..17f87573c407 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -29,17 +29,15 @@
#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
#endif
-#define get_fs() (current->thread.addr_limit)
+#define segment_eq(a, b) ((a).seg == (b).seg)
+
+#define get_fs() (test_thread_flag(TIF_KERNEL_DS) ? KERNEL_DS : USER_DS)
static inline void set_fs(mm_segment_t fs)
{
- current->thread.addr_limit = fs;
- /* On user-mode return check addr_limit (fs) is correct */
- set_thread_flag(TIF_FSCHECK);
+ update_thread_flag(TIF_KERNEL_DS, segment_eq(fs, KERNEL_DS));
}
-#define segment_eq(a, b) ((a).seg == (b).seg)
-
#define user_addr_max() (get_fs().seg)
#ifdef __powerpc64__
--
2.25.0
^ permalink raw reply related
* Re: [PATCH V12] mm/debug: Add tests validating architecture page table helpers
From: Catalin Marinas @ 2020-01-29 10:36 UTC (permalink / raw)
To: Qian Cai
Cc: Mark Rutland, linux-ia64, linux-sh, Peter Zijlstra, James Hogan,
Heiko Carstens, Michal Hocko, linux-mm, Paul Mackerras,
sparclinux, Ingo Molnar, linux-s390, Jason Gunthorpe, x86,
Russell King - ARM Linux, Matthew Wilcox, Steven Price,
Tetsuo Handa, Vlastimil Babka, linux-snps-arc, Kees Cook,
Anshuman Khandual, Gerald Schaefer, Mark Brown,
Kirill A . Shutemov, Dan Williams, linux-arm-kernel,
Sri Krishna chowdary, Masahiro Yamada, Greg Kroah-Hartman,
Ard Biesheuvel, Dave Hansen, linux-mips, Ralf Baechle,
linux-kernel, Paul Burton, Mike Rapoport, Thomas Gleixner,
Vineet Gupta, Martin Schwidefsky, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <69091BA4-18C4-4425-A5E2-31FBE4654AF9@lca.pw>
On Tue, Jan 28, 2020 at 02:07:10PM -0500, Qian Cai wrote:
> On Jan 28, 2020, at 12:47 PM, Catalin Marinas <catalin.marinas@arm.com> wrote:
> > The primary goal here is not finding regressions but having clearly
> > defined semantics of the page table accessors across architectures. x86
> > and arm64 are a good starting point and other architectures will be
> > enabled as they are aligned to the same semantics.
>
> This still does not answer the fundamental question. If this test is
> simply inefficient to find bugs,
Who said this is inefficient (other than you)?
> who wants to spend time to use it regularly?
Arch maintainers, mm maintainers introducing new macros or assuming
certain new semantics of the existing macros.
> If this is just one off test that may get running once in a few years
> (when introducing a new arch), how does it justify the ongoing cost to
> maintain it?
You are really missing the point. It's not only for a new arch but
changes to existing arch code. And if the arch code churn in this area
is relatively small, I'd expect a similarly small cost of maintaining
this test.
If you only turn DEBUG_VM on once every few years, don't generalise this
to the rest of the kernel developers (as others pointed out, this test
is default y if DEBUG_VM).
Anyway, I think that's a pointless discussion, so not going to reply
further (unless you have technical content to add).
--
Catalin
^ permalink raw reply
* Re: [PATCH v16 00/23] selftests, powerpc, x86: Memory Protection Keys
From: Sandipan Das @ 2020-01-29 9:56 UTC (permalink / raw)
To: Dave Hansen
Cc: linux-arch, fweimer, aneesh.kumar, x86, linuxram, linuxppc-dev,
mhocko, linux-mm, mingo, linux-kselftest, msuchanek, shuah,
bauerman
In-Reply-To: <fb83ce52-b92a-ed42-dc06-a86ca8431ff6@linux.ibm.com>
Hi Dave,
On 28/01/20 3:08 pm, Sandipan Das wrote:
> On 27/01/20 9:12 pm, Dave Hansen wrote:
>>
>> How have you tested this patch (and the whole series for that matter)?
>>
>
> I replaced the second patch with this one and did a build test.
> Till v16, I had tested the whole series (build + run) on both a POWER8
> system (with 4K and 64K page sizes) and a Skylake SP system but for
> x86_64 only. Following that, I could only do a build test locally on
> my laptop for i386 and x86_64 on my laptop as I did not have access to
> the Skylake system anymore.
>
>
I got a chance to use the Skylake system today and tested (build + run)
the whole series (v17 with the fixed Makefile) for both i386 and x86_64.
Everything passed.
- Sandipan
^ permalink raw reply
* Re: [RFC PATCH v4 10/11] lib: vdso: Allow arches to override the ns shift operation
From: Christophe Leroy @ 2020-01-29 7:26 UTC (permalink / raw)
To: Thomas Gleixner, Andy Lutomirski
Cc: nathanl, Arnd Bergmann, X86 ML, LKML, open list:MIPS,
Paul Mackerras, Vincenzo Frascino, linuxppc-dev, linux-arm-kernel
In-Reply-To: <87mua64tv0.fsf@nanos.tec.linutronix.de>
Le 29/01/2020 à 08:14, Thomas Gleixner a écrit :
> Andy Lutomirski <luto@kernel.org> writes:
>
>> On Thu, Jan 16, 2020 at 11:57 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>>>
>>> Andy Lutomirski <luto@kernel.org> writes:
>>>> On Thu, Jan 16, 2020 at 9:58 AM Christophe Leroy
>>>>
>>>> Would mul_u64_u64_shr() be a good alternative? Could we adjust it to
>>>> assume the shift is less than 32? That function exists to benefit
>>>> 32-bit arches.
>>>
>>> We'd want mul_u64_u32_shr() for this. The rules for mult and shift are:
>>>
>>
>> That's what I meant to type...
>
> Just that it does not work. The math is:
>
> ns = d->nsecs; // That's the nsec value shifted left by d->shift
>
> ns += ((cur - d->last) & d->mask) * mult;
>
> ns >>= d->shift;
>
> So we cannot use mul_u64_u32_shr() because we need the addition there
> before shifting. And no, we can't drop the fractional part of
> d->nsecs. Been there, done that, got sporadic time going backwards
> problems as a reward. Need to look at that again as stuff has changed
> over time.
>
> On x86 we enforce that mask is 64bit, so the & operation is not there,
> but due to the nasties of TSC we have that conditional
>
> if (cur > last)
> return (cur - last) * mult;
> return 0;
>
> Christophe, on PPC the decrementer/RTC clocksource masks are 64bit as
> well, so you can spare that & operation there too.
>
Yes, I did it already. It spares reading d->mast, that the main advantage.
Christophe
^ permalink raw reply
* Re: [RFC PATCH v4 10/11] lib: vdso: Allow arches to override the ns shift operation
From: Thomas Gleixner @ 2020-01-29 7:14 UTC (permalink / raw)
To: Andy Lutomirski
Cc: nathanl, Arnd Bergmann, X86 ML, LKML, open list:MIPS,
Paul Mackerras, Andrew Lutomirski, Vincenzo Frascino,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <CALCETrX5B0SEJN2WG7rzuzbGhWa_dEwVVpMu6deXof3H+K_LdQ@mail.gmail.com>
Andy Lutomirski <luto@kernel.org> writes:
> On Thu, Jan 16, 2020 at 11:57 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>>
>> Andy Lutomirski <luto@kernel.org> writes:
>> > On Thu, Jan 16, 2020 at 9:58 AM Christophe Leroy
>> >
>> > Would mul_u64_u64_shr() be a good alternative? Could we adjust it to
>> > assume the shift is less than 32? That function exists to benefit
>> > 32-bit arches.
>>
>> We'd want mul_u64_u32_shr() for this. The rules for mult and shift are:
>>
>
> That's what I meant to type...
Just that it does not work. The math is:
ns = d->nsecs; // That's the nsec value shifted left by d->shift
ns += ((cur - d->last) & d->mask) * mult;
ns >>= d->shift;
So we cannot use mul_u64_u32_shr() because we need the addition there
before shifting. And no, we can't drop the fractional part of
d->nsecs. Been there, done that, got sporadic time going backwards
problems as a reward. Need to look at that again as stuff has changed
over time.
On x86 we enforce that mask is 64bit, so the & operation is not there,
but due to the nasties of TSC we have that conditional
if (cur > last)
return (cur - last) * mult;
return 0;
Christophe, on PPC the decrementer/RTC clocksource masks are 64bit as
well, so you can spare that & operation there too.
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH] powerpc/xmon: Fix compile error in print_insn* functions
From: Michael Ellerman @ 2020-01-29 5:17 UTC (permalink / raw)
To: Sukadev Bhattiprolu; +Cc: linuxppc-dev
In-Reply-To: <20200123010455.GA15080@us.ibm.com>
On Thu, 2020-01-23 at 01:04:55 UTC, Sukadev Bhattiprolu wrote:
> >From 72a7497a8673c93a4b80aa4fc38b88a8e90aa650 Mon Sep 17 00:00:00 2001
> From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> Date: Wed, 22 Jan 2020 18:57:18 -0600
> Subject: [PATCH 1/1] powerpc/xmon: Fix compile error in print_insn* functions
>
> Fix couple of compile errors I stumbled upon with CONFIG_XMON=y and
> CONFIG_XMON_DISASSEMBLY=n
>
> Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/493a55f1e7724dee5e71bc726d5b819292094587
cheers
^ permalink raw reply
* Re: [PATCH v4] powerpc: use probe_user_read() and probe_user_write()
From: Michael Ellerman @ 2020-01-29 5:17 UTC (permalink / raw)
To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <e041f5eedb23f09ab553be8a91c3de2087147320.1579800517.git.christophe.leroy@c-s.fr>
On Thu, 2020-01-23 at 17:30:47 UTC, Christophe Leroy wrote:
> Instead of opencoding, use probe_user_read() to failessly read
> a user location and probe_user_write() for writing to user.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/def0bfdbd6039e96a9eb2baaa4470b079daab0d4
cheers
^ permalink raw reply
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