aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/Kconfig11
-rw-r--r--arch/arm64/include/asm/assembler.h6
-rw-r--r--arch/arm64/include/asm/cacheflush.h1
-rw-r--r--arch/arm64/include/asm/cpucaps.h3
-rw-r--r--arch/arm64/kernel/cpufeature.c11
-rw-r--r--arch/arm64/mm/cache.S14
-rw-r--r--arch/arm64/mm/flush.c16
7 files changed, 61 insertions, 1 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dfd908630631..0b0576a54724 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -960,6 +960,17 @@ config ARM64_UAO
960 regular load/store instructions if the cpu does not implement the 960 regular load/store instructions if the cpu does not implement the
961 feature. 961 feature.
962 962
963config ARM64_PMEM
964 bool "Enable support for persistent memory"
965 select ARCH_HAS_PMEM_API
966 help
967 Say Y to enable support for the persistent memory API based on the
968 ARMv8.2 DCPoP feature.
969
970 The feature is detected at runtime, and the kernel will use DC CVAC
971 operations if DC CVAP is not supported (following the behaviour of
972 DC CVAP itself if the system does not define a point of persistence).
973
963endmenu 974endmenu
964 975
965config ARM64_MODULE_CMODEL_LARGE 976config ARM64_MODULE_CMODEL_LARGE
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 1b67c3782d00..5d8903c45031 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -353,6 +353,12 @@ alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
353alternative_else 353alternative_else
354 dc civac, \kaddr 354 dc civac, \kaddr
355alternative_endif 355alternative_endif
356 .elseif (\op == cvap)
357alternative_if ARM64_HAS_DCPOP
358 sys 3, c7, c12, 1, \kaddr // dc cvap
359alternative_else
360 dc cvac, \kaddr
361alternative_endif
356 .else 362 .else
357 dc \op, \kaddr 363 dc \op, \kaddr
358 .endif 364 .endif
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index b4b43a94dffd..76d1cc85d5b1 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -69,6 +69,7 @@ extern void flush_icache_range(unsigned long start, unsigned long end);
69extern void __flush_dcache_area(void *addr, size_t len); 69extern void __flush_dcache_area(void *addr, size_t len);
70extern void __inval_dcache_area(void *addr, size_t len); 70extern void __inval_dcache_area(void *addr, size_t len);
71extern void __clean_dcache_area_poc(void *addr, size_t len); 71extern void __clean_dcache_area_poc(void *addr, size_t len);
72extern void __clean_dcache_area_pop(void *addr, size_t len);
72extern void __clean_dcache_area_pou(void *addr, size_t len); 73extern void __clean_dcache_area_pou(void *addr, size_t len);
73extern long __flush_cache_user_range(unsigned long start, unsigned long end); 74extern long __flush_cache_user_range(unsigned long start, unsigned long end);
74extern void sync_icache_aliases(void *kaddr, unsigned long len); 75extern void sync_icache_aliases(void *kaddr, unsigned long len);
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 8d2272c6822c..8da621627d7c 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -39,7 +39,8 @@
39#define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 39#define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18
40#define ARM64_WORKAROUND_858921 19 40#define ARM64_WORKAROUND_858921 19
41#define ARM64_WORKAROUND_CAVIUM_30115 20 41#define ARM64_WORKAROUND_CAVIUM_30115 20
42#define ARM64_HAS_DCPOP 21
42 43
43#define ARM64_NCAPS 21 44#define ARM64_NCAPS 22
44 45
45#endif /* __ASM_CPUCAPS_H */ 46#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index a2542ef3ff25..cd52d365d1f0 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -889,6 +889,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
889 .min_field_value = 0, 889 .min_field_value = 0,
890 .matches = has_no_fpsimd, 890 .matches = has_no_fpsimd,
891 }, 891 },
892#ifdef CONFIG_ARM64_PMEM
893 {
894 .desc = "Data cache clean to Point of Persistence",
895 .capability = ARM64_HAS_DCPOP,
896 .def_scope = SCOPE_SYSTEM,
897 .matches = has_cpuid_feature,
898 .sys_reg = SYS_ID_AA64ISAR1_EL1,
899 .field_pos = ID_AA64ISAR1_DPB_SHIFT,
900 .min_field_value = 1,
901 },
902#endif
892 {}, 903 {},
893}; 904};
894 905
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index ed47fbbb4b05..7f1dbe962cf5 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -172,6 +172,20 @@ ENDPIPROC(__clean_dcache_area_poc)
172ENDPROC(__dma_clean_area) 172ENDPROC(__dma_clean_area)
173 173
174/* 174/*
175 * __clean_dcache_area_pop(kaddr, size)
176 *
177 * Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
178 * are cleaned to the PoP.
179 *
180 * - kaddr - kernel address
181 * - size - size in question
182 */
183ENTRY(__clean_dcache_area_pop)
184 dcache_by_line_op cvap, sy, x0, x1, x2, x3
185 ret
186ENDPIPROC(__clean_dcache_area_pop)
187
188/*
175 * __dma_flush_area(start, size) 189 * __dma_flush_area(start, size)
176 * 190 *
177 * clean & invalidate D / U line 191 * clean & invalidate D / U line
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index 21a8d828cbf4..280f90ff33a2 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -83,3 +83,19 @@ EXPORT_SYMBOL(flush_dcache_page);
83 * Additional functions defined in assembly. 83 * Additional functions defined in assembly.
84 */ 84 */
85EXPORT_SYMBOL(flush_icache_range); 85EXPORT_SYMBOL(flush_icache_range);
86
87#ifdef CONFIG_ARCH_HAS_PMEM_API
88static inline void arch_wb_cache_pmem(void *addr, size_t size)
89{
90 /* Ensure order against any prior non-cacheable writes */
91 dmb(osh);
92 __clean_dcache_area_pop(addr, size);
93}
94EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
95
96static inline void arch_invalidate_pmem(void *addr, size_t size)
97{
98 __inval_dcache_area(addr, size);
99}
100EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
101#endif