diff options
-rw-r--r-- | arch/arm64/include/asm/cache.h | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/cacheflush.h | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpucaps.h | 4 | ||||
-rw-r--r-- | arch/arm64/kernel/cpufeature.c | 36 | ||||
-rw-r--r-- | arch/arm64/mm/cache.S | 21 |
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 | ||
134 | static inline void __flush_icache_all(void) | 134 | static 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 | ||
201 | static const struct arm64_ftr_bits ftr_ctr[] = { | 201 | static 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 | ||
855 | static 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 | |||
861 | static 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 |
856 | static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ | 868 | static 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 | */ |
51 | ENTRY(__flush_cache_user_range) | 51 | ENTRY(__flush_cache_user_range) |
52 | uaccess_ttbr0_enable x2, x3, x4 | 52 | uaccess_ttbr0_enable x2, x3, x4 |
53 | alternative_if ARM64_HAS_CACHE_IDC | ||
54 | dsb ishst | ||
55 | b 7f | ||
56 | alternative_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 | ||
67 | 7: | ||
68 | alternative_if ARM64_HAS_CACHE_DIC | ||
69 | isb | ||
70 | b 8f | ||
71 | alternative_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 | 73 | 8: mov x0, #0 |
65 | 1: | 74 | 1: |
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 | */ |
82 | ENTRY(invalidate_icache_range) | 91 | ENTRY(invalidate_icache_range) |
92 | alternative_if ARM64_HAS_CACHE_DIC | ||
93 | mov x0, xzr | ||
94 | isb | ||
95 | ret | ||
96 | alternative_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 | */ |
118 | ENTRY(__clean_dcache_area_pou) | 133 | ENTRY(__clean_dcache_area_pou) |
134 | alternative_if ARM64_HAS_CACHE_IDC | ||
135 | dsb ishst | ||
136 | ret | ||
137 | alternative_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 |
121 | ENDPROC(__clean_dcache_area_pou) | 140 | ENDPROC(__clean_dcache_area_pou) |