aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/cache.h4
-rw-r--r--arch/arm64/include/asm/cacheflush.h3
-rw-r--r--arch/arm64/include/asm/cpucaps.h4
-rw-r--r--arch/arm64/kernel/cpufeature.c36
-rw-r--r--arch/arm64/mm/cache.S21
5 files changed, 60 insertions, 8 deletions
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
index b2e6ece23713..5df5cfe1c143 100644
--- a/arch/arm64/include/asm/cache.h
+++ b/arch/arm64/include/asm/cache.h
@@ -20,8 +20,12 @@
20 20
21#define CTR_L1IP_SHIFT 14 21#define CTR_L1IP_SHIFT 14
22#define CTR_L1IP_MASK 3 22#define CTR_L1IP_MASK 3
23#define CTR_DMINLINE_SHIFT 16
24#define CTR_ERG_SHIFT 20
23#define CTR_CWG_SHIFT 24 25#define CTR_CWG_SHIFT 24
24#define CTR_CWG_MASK 15 26#define CTR_CWG_MASK 15
27#define CTR_IDC_SHIFT 28
28#define CTR_DIC_SHIFT 29
25 29
26#define CTR_L1IP(ctr) (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK) 30#define CTR_L1IP(ctr) (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
27 31
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index bef9f418f089..7dfcec4700fe 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -133,6 +133,9 @@ extern void flush_dcache_page(struct page *);
133 133
134static inline void __flush_icache_all(void) 134static inline void __flush_icache_all(void)
135{ 135{
136 if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
137 return;
138
136 asm("ic ialluis"); 139 asm("ic ialluis");
137 dsb(ish); 140 dsb(ish);
138} 141}
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 39134c46bb13..ff9fb3aba17b 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -46,7 +46,9 @@
46#define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 46#define ARM64_HARDEN_BP_POST_GUEST_EXIT 25
47#define ARM64_HAS_RAS_EXTN 26 47#define ARM64_HAS_RAS_EXTN 26
48#define ARM64_WORKAROUND_843419 27 48#define ARM64_WORKAROUND_843419 27
49#define ARM64_HAS_CACHE_IDC 28
50#define ARM64_HAS_CACHE_DIC 29
49 51
50#define ARM64_NCAPS 28 52#define ARM64_NCAPS 30
51 53
52#endif /* __ASM_CPUCAPS_H */ 54#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f96b3449034b..bdab55223866 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -199,12 +199,12 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
199}; 199};
200 200
201static const struct arm64_ftr_bits ftr_ctr[] = { 201static const struct arm64_ftr_bits ftr_ctr[] = {
202 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */ 202 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */
203 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 29, 1, 1), /* DIC */ 203 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 1, 1),
204 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 28, 1, 1), /* IDC */ 204 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IDC_SHIFT, 1, 1),
205 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ 205 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_CWG_SHIFT, 4, 0),
206 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 20, 4, 0), /* ERG */ 206 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_ERG_SHIFT, 4, 0),
207 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ 207 ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DMINLINE_SHIFT, 4, 1),
208 /* 208 /*
209 * Linux can handle differing I-cache policies. Userspace JITs will 209 * Linux can handle differing I-cache policies. Userspace JITs will
210 * make use of *minLine. 210 * make use of *minLine.
@@ -852,6 +852,18 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
852 ID_AA64PFR0_FP_SHIFT) < 0; 852 ID_AA64PFR0_FP_SHIFT) < 0;
853} 853}
854 854
855static bool has_cache_idc(const struct arm64_cpu_capabilities *entry,
856 int __unused)
857{
858 return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_IDC_SHIFT);
859}
860
861static bool has_cache_dic(const struct arm64_cpu_capabilities *entry,
862 int __unused)
863{
864 return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_DIC_SHIFT);
865}
866
855#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 867#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
856static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ 868static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
857 869
@@ -1088,6 +1100,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
1088 .enable = cpu_clear_disr, 1100 .enable = cpu_clear_disr,
1089 }, 1101 },
1090#endif /* CONFIG_ARM64_RAS_EXTN */ 1102#endif /* CONFIG_ARM64_RAS_EXTN */
1103 {
1104 .desc = "Data cache clean to the PoU not required for I/D coherence",
1105 .capability = ARM64_HAS_CACHE_IDC,
1106 .def_scope = SCOPE_SYSTEM,
1107 .matches = has_cache_idc,
1108 },
1109 {
1110 .desc = "Instruction cache invalidation not required for I/D coherence",
1111 .capability = ARM64_HAS_CACHE_DIC,
1112 .def_scope = SCOPE_SYSTEM,
1113 .matches = has_cache_dic,
1114 },
1091 {}, 1115 {},
1092}; 1116};
1093 1117
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 758bde7e2fa6..30334d81b021 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -50,6 +50,10 @@ ENTRY(flush_icache_range)
50 */ 50 */
51ENTRY(__flush_cache_user_range) 51ENTRY(__flush_cache_user_range)
52 uaccess_ttbr0_enable x2, x3, x4 52 uaccess_ttbr0_enable x2, x3, x4
53alternative_if ARM64_HAS_CACHE_IDC
54 dsb ishst
55 b 7f
56alternative_else_nop_endif
53 dcache_line_size x2, x3 57 dcache_line_size x2, x3
54 sub x3, x2, #1 58 sub x3, x2, #1
55 bic x4, x0, x3 59 bic x4, x0, x3
@@ -60,8 +64,13 @@ user_alt 9f, "dc cvau, x4", "dc civac, x4", ARM64_WORKAROUND_CLEAN_CACHE
60 b.lo 1b 64 b.lo 1b
61 dsb ish 65 dsb ish
62 66
677:
68alternative_if ARM64_HAS_CACHE_DIC
69 isb
70 b 8f
71alternative_else_nop_endif
63 invalidate_icache_by_line x0, x1, x2, x3, 9f 72 invalidate_icache_by_line x0, x1, x2, x3, 9f
64 mov x0, #0 738: mov x0, #0
651: 741:
66 uaccess_ttbr0_disable x1, x2 75 uaccess_ttbr0_disable x1, x2
67 ret 76 ret
@@ -80,6 +89,12 @@ ENDPROC(__flush_cache_user_range)
80 * - end - virtual end address of region 89 * - end - virtual end address of region
81 */ 90 */
82ENTRY(invalidate_icache_range) 91ENTRY(invalidate_icache_range)
92alternative_if ARM64_HAS_CACHE_DIC
93 mov x0, xzr
94 isb
95 ret
96alternative_else_nop_endif
97
83 uaccess_ttbr0_enable x2, x3, x4 98 uaccess_ttbr0_enable x2, x3, x4
84 99
85 invalidate_icache_by_line x0, x1, x2, x3, 2f 100 invalidate_icache_by_line x0, x1, x2, x3, 2f
@@ -116,6 +131,10 @@ ENDPIPROC(__flush_dcache_area)
116 * - size - size in question 131 * - size - size in question
117 */ 132 */
118ENTRY(__clean_dcache_area_pou) 133ENTRY(__clean_dcache_area_pou)
134alternative_if ARM64_HAS_CACHE_IDC
135 dsb ishst
136 ret
137alternative_else_nop_endif
119 dcache_by_line_op cvau, ish, x0, x1, x2, x3 138 dcache_by_line_op cvau, ish, x0, x1, x2, x3
120 ret 139 ret
121ENDPROC(__clean_dcache_area_pou) 140ENDPROC(__clean_dcache_area_pou)