The original implementation to flush all cache after unlocking the nvdimm
resides in drivers/acpi/nfit/intel.c. This is a temporary stop gap until
nvdimm with security operations arrives on other archs. With support CXL
pmem supporting security operations, specifically "unlock" dimm, the need
for an arch supported helper function to invalidate all CPU cache for
nvdimm has arrived. Remove original implementation from acpi/nfit and add
cross arch support for this operation.

Add CONFIG_ARCH_HAS_NVDIMM_INVAL_CACHE Kconfig and allow x86_64 to opt in
and provide the support via wbinvd_on_all_cpus() call.

Signed-off-by: Dave Jiang <[email protected]>
---
 arch/x86/Kconfig             |    1 +
 arch/x86/mm/pat/set_memory.c |    8 ++++++++
 drivers/acpi/nfit/intel.c    |   28 +++++-----------------------
 include/linux/libnvdimm.h    |    8 ++++++++
 lib/Kconfig                  |    3 +++
 5 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index be0b95e51df6..8dbe89eba639 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -83,6 +83,7 @@ config X86
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
        select ARCH_HAS_PMEM_API                if X86_64
+       select ARCH_HAS_NVDIMM_INVAL_CACHE      if X86_64
        select ARCH_HAS_PTE_DEVMAP              if X86_64
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_UACCESS_FLUSHCACHE      if X86_64
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 1abd5438f126..e4cd1286deef 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -330,6 +330,14 @@ void arch_invalidate_pmem(void *addr, size_t size)
 EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
 #endif
 
+#ifdef CONFIG_ARCH_HAS_NVDIMM_INVAL_CACHE
+void arch_invalidate_nvdimm_cache(void)
+{
+       wbinvd_on_all_cpus();
+}
+EXPORT_SYMBOL_GPL(arch_invalidate_nvdimm_cache);
+#endif
+
 static void __cpa_flush_all(void *arg)
 {
        unsigned long cache = (unsigned long)arg;
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index 8dd792a55730..242d2e9203e9 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -190,8 +190,6 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
        }
 }
 
-static void nvdimm_invalidate_cache(void);
-
 static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key_data)
 {
@@ -228,7 +226,7 @@ static int __maybe_unused intel_security_unlock(struct 
nvdimm *nvdimm,
        }
 
        /* DIMM unlocked, invalidate all CPU caches before we read it */
-       nvdimm_invalidate_cache();
+       arch_invalidate_nvdimm_cache();
 
        return 0;
 }
@@ -298,7 +296,7 @@ static int __maybe_unused intel_security_erase(struct 
nvdimm *nvdimm,
                return -ENOTTY;
 
        /* flush all cache before we erase DIMM */
-       nvdimm_invalidate_cache();
+       arch_invalidate_nvdimm_cache();
        memcpy(nd_cmd.cmd.passphrase, key->data,
                        sizeof(nd_cmd.cmd.passphrase));
        rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
@@ -318,7 +316,7 @@ static int __maybe_unused intel_security_erase(struct 
nvdimm *nvdimm,
        }
 
        /* DIMM erased, invalidate all CPU caches before we read it */
-       nvdimm_invalidate_cache();
+       arch_invalidate_nvdimm_cache();
        return 0;
 }
 
@@ -355,7 +353,7 @@ static int __maybe_unused 
intel_security_query_overwrite(struct nvdimm *nvdimm)
        }
 
        /* flush all cache before we make the nvdimms available */
-       nvdimm_invalidate_cache();
+       arch_invalidate_nvdimm_cache();
        return 0;
 }
 
@@ -381,7 +379,7 @@ static int __maybe_unused intel_security_overwrite(struct 
nvdimm *nvdimm,
                return -ENOTTY;
 
        /* flush all cache before we erase DIMM */
-       nvdimm_invalidate_cache();
+       arch_invalidate_nvdimm_cache();
        memcpy(nd_cmd.cmd.passphrase, nkey->data,
                        sizeof(nd_cmd.cmd.passphrase));
        rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
@@ -401,22 +399,6 @@ static int __maybe_unused intel_security_overwrite(struct 
nvdimm *nvdimm,
        }
 }
 
-/*
- * TODO: define a cross arch wbinvd equivalent when/if
- * NVDIMM_FAMILY_INTEL command support arrives on another arch.
- */
-#ifdef CONFIG_X86
-static void nvdimm_invalidate_cache(void)
-{
-       wbinvd_on_all_cpus();
-}
-#else
-static void nvdimm_invalidate_cache(void)
-{
-       WARN_ON_ONCE("cache invalidation required after unlock\n");
-}
-#endif
-
 static const struct nvdimm_security_ops __intel_security_ops = {
        .get_flags = intel_security_flags,
        .freeze = intel_security_freeze,
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 0d61e07b6827..455d54ec3c86 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -308,4 +308,12 @@ static inline void arch_invalidate_pmem(void *addr, size_t 
size)
 }
 #endif
 
+#ifdef CONFIG_ARCH_HAS_NVDIMM_INVAL_CACHE
+void arch_invalidate_nvdimm_cache(void);
+#else
+static inline void arch_invalidate_nvdimm_cache(void)
+{
+}
+#endif
+
 #endif /* __LIBNVDIMM_H__ */
diff --git a/lib/Kconfig b/lib/Kconfig
index eaaad4d85bf2..d4bc48eea635 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -652,6 +652,9 @@ config ARCH_NO_SG_CHAIN
 config ARCH_HAS_PMEM_API
        bool
 
+config ARCH_HAS_NVDIMM_INVAL_CACHE
+       bool
+
 config MEMREGION
        bool
 



Reply via email to