diff options
-rw-r--r-- | arch/arm64/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm64/include/asm/assembler.h | 6 | ||||
-rw-r--r-- | arch/arm64/include/asm/cacheflush.h | 1 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpucaps.h | 3 | ||||
-rw-r--r-- | arch/arm64/kernel/cpufeature.c | 11 | ||||
-rw-r--r-- | arch/arm64/mm/cache.S | 14 | ||||
-rw-r--r-- | arch/arm64/mm/flush.c | 16 |
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 | ||
963 | config 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 | |||
963 | endmenu | 974 | endmenu |
964 | 975 | ||
965 | config ARM64_MODULE_CMODEL_LARGE | 976 | config 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 | |||
353 | alternative_else | 353 | alternative_else |
354 | dc civac, \kaddr | 354 | dc civac, \kaddr |
355 | alternative_endif | 355 | alternative_endif |
356 | .elseif (\op == cvap) | ||
357 | alternative_if ARM64_HAS_DCPOP | ||
358 | sys 3, c7, c12, 1, \kaddr // dc cvap | ||
359 | alternative_else | ||
360 | dc cvac, \kaddr | ||
361 | alternative_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); | |||
69 | extern void __flush_dcache_area(void *addr, size_t len); | 69 | extern void __flush_dcache_area(void *addr, size_t len); |
70 | extern void __inval_dcache_area(void *addr, size_t len); | 70 | extern void __inval_dcache_area(void *addr, size_t len); |
71 | extern void __clean_dcache_area_poc(void *addr, size_t len); | 71 | extern void __clean_dcache_area_poc(void *addr, size_t len); |
72 | extern void __clean_dcache_area_pop(void *addr, size_t len); | ||
72 | extern void __clean_dcache_area_pou(void *addr, size_t len); | 73 | extern void __clean_dcache_area_pou(void *addr, size_t len); |
73 | extern long __flush_cache_user_range(unsigned long start, unsigned long end); | 74 | extern long __flush_cache_user_range(unsigned long start, unsigned long end); |
74 | extern void sync_icache_aliases(void *kaddr, unsigned long len); | 75 | extern 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) | |||
172 | ENDPROC(__dma_clean_area) | 172 | ENDPROC(__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 | */ | ||
183 | ENTRY(__clean_dcache_area_pop) | ||
184 | dcache_by_line_op cvap, sy, x0, x1, x2, x3 | ||
185 | ret | ||
186 | ENDPIPROC(__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 | */ |
85 | EXPORT_SYMBOL(flush_icache_range); | 85 | EXPORT_SYMBOL(flush_icache_range); |
86 | |||
87 | #ifdef CONFIG_ARCH_HAS_PMEM_API | ||
88 | static 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 | } | ||
94 | EXPORT_SYMBOL_GPL(arch_wb_cache_pmem); | ||
95 | |||
96 | static inline void arch_invalidate_pmem(void *addr, size_t size) | ||
97 | { | ||
98 | __inval_dcache_area(addr, size); | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(arch_invalidate_pmem); | ||
101 | #endif | ||