This adds a kernel config option that controls whether MAP_SYNC is enabled by default. With POWER10, architecture is adding new pmem flush and sync instructions. The kernel should prevent the usage of MAP_SYNC if applications are not using the new instructions on newer hardware.
This config allows user to control whether MAP_SYNC should be enabled by default or not. Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com> --- arch/powerpc/platforms/Kconfig.cputype | 9 +++++++++ arch/powerpc/platforms/pseries/papr_scm.c | 17 ++++++++++++++++- drivers/nvdimm/of_pmem.c | 7 +++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index d349603fb889..abcc163b8dc6 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -383,6 +383,15 @@ config PPC_KUEP If you're unsure, say Y. +config ARCH_MAP_SYNC_DISABLE + bool "Disable synchronous fault support (MAP_SYNC)" + default y + help + Disable support for synchronous fault with nvdimm namespaces. + + If you're unsure, say Y. + + config PPC_HAVE_KUAP bool diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index ad506e7003c9..b970d2dbe589 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -30,6 +30,7 @@ struct papr_scm_priv { uint64_t block_size; int metadata_size; bool is_volatile; + bool disable_map_sync; uint64_t bound_addr; @@ -353,11 +354,18 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.num_mappings = 1; ndr_desc.nd_set = &p->nd_set; ndr_desc.flush = papr_scm_flush_sync; + set_bit(ND_REGION_SYNC_ENABLED, &ndr_desc.flags); if (p->is_volatile) p->region = nvdimm_volatile_region_create(p->bus, &ndr_desc); else { set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags); + /* + * for a persistent region, check if the platform needs to + * force MAP_SYNC disable. + */ + if (p->disable_map_sync) + clear_bit(ND_REGION_SYNC_ENABLED, &ndr_desc.flags); p->region = nvdimm_pmem_region_create(p->bus, &ndr_desc); } if (!p->region) { @@ -378,7 +386,7 @@ err: nvdimm_bus_unregister(p->bus); static int papr_scm_probe(struct platform_device *pdev) { - struct device_node *dn = pdev->dev.of_node; + struct device_node *dn; u32 drc_index, metadata_size; u64 blocks, block_size; struct papr_scm_priv *p; @@ -386,6 +394,10 @@ static int papr_scm_probe(struct platform_device *pdev) u64 uuid[2]; int rc; + dn = dev_of_node(&pdev->dev); + if (!dn) + return -ENXIO; + /* check we have all the required DT properties */ if (of_property_read_u32(dn, "ibm,my-drc-index", &drc_index)) { dev_err(&pdev->dev, "%pOF: missing drc-index!\n", dn); @@ -415,6 +427,9 @@ static int papr_scm_probe(struct platform_device *pdev) /* optional DT properties */ of_property_read_u32(dn, "ibm,metadata-size", &metadata_size); + if (of_device_is_compatible(dn, "ibm,pmemory-v2")) + p->disable_map_sync = true; + p->dn = dn; p->drc_index = drc_index; p->block_size = block_size; diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c index 6826a274a1f1..a6cc3488e552 100644 --- a/drivers/nvdimm/of_pmem.c +++ b/drivers/nvdimm/of_pmem.c @@ -59,12 +59,19 @@ static int of_pmem_region_probe(struct platform_device *pdev) ndr_desc.res = &pdev->resource[i]; ndr_desc.of_node = np; set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags); + set_bit(ND_REGION_SYNC_ENABLED, &ndr_desc.flags); if (is_volatile) region = nvdimm_volatile_region_create(bus, &ndr_desc); else { set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags); + /* + * for a persistent region, check for newer device + */ + if (of_device_is_compatible(np, "pmem-region-v2")) + clear_bit(ND_REGION_SYNC_ENABLED, &ndr_desc.flags); region = nvdimm_pmem_region_create(bus, &ndr_desc); + } if (!region) -- 2.26.2