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
