aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2022-08-22 17:02:13 +0000
committerAndrew Turner <andrew@FreeBSD.org>2022-08-25 11:17:28 +0000
commit7a060a8895b8e6c1cd0afded15da27c373eb0de9 (patch)
tree230c2dc84c063c1fb170c38771e681d00ae8b932
parent278111b8a54141bdaf4c4a045539db21febf053f (diff)
downloadsrc-7a060a8895b8e6c1cd0afded15da27c373eb0de9.tar.gz
src-7a060a8895b8e6c1cd0afded15da27c373eb0de9.zip
Add an IDC only arm64 icache sync function
When the IDC flag is set in the cache type register we don't need to clean the data cache to the point of unification. Previously we supported this flag being set only when the DIC flags was also set. Add a new handler for when this is not the case. Reviewed by: kib Sponsored by: The FreeBSD Foundation, Ampere (hardware) Differential Revision: https://reviews.freebsd.org/D36296
-rw-r--r--sys/arm64/arm64/cpufunc_asm.S12
-rw-r--r--sys/arm64/arm64/identcpu.c4
-rw-r--r--sys/arm64/include/cpufunc.h1
3 files changed, 17 insertions, 0 deletions
diff --git a/sys/arm64/arm64/cpufunc_asm.S b/sys/arm64/arm64/cpufunc_asm.S
index 2f28c4f68271..927bcafcf1e1 100644
--- a/sys/arm64/arm64/cpufunc_asm.S
+++ b/sys/arm64/arm64/cpufunc_asm.S
@@ -144,6 +144,18 @@ ENTRY(arm64_dic_idc_icache_sync_range)
END(arm64_dic_idc_icache_sync_range)
/*
+ * void arm64_idc_aliasing_icache_sync_range(vm_offset_t, vm_size_t)
+ * When the CTR_EL0.IDC bit is set cleaning to PoU becomes a dsb.
+ */
+ENTRY(arm64_idc_aliasing_icache_sync_range)
+ dsb ishst
+ ic ialluis
+ dsb ish
+ isb
+ ret
+END(arm64_idc_aliasing_icache_sync_range)
+
+/*
* void arm64_aliasing_icache_sync_range(vm_offset_t, vm_size_t)
*/
ENTRY(arm64_aliasing_icache_sync_range)
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index ef9bf022f491..ba8da5d48fee 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -1849,6 +1849,10 @@ identify_cpu_sysinit(void *dummy __unused)
arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range;
if (bootverbose)
printf("Enabling DIC & IDC ICache sync\n");
+ } else if (idc) {
+ arm64_icache_sync_range = &arm64_idc_aliasing_icache_sync_range;
+ if (bootverbose)
+ printf("Enabling IDC ICache sync\n");
}
if ((elf_hwcap & HWCAP_ATOMICS) != 0) {
diff --git a/sys/arm64/include/cpufunc.h b/sys/arm64/include/cpufunc.h
index 16133903841f..691474bac90e 100644
--- a/sys/arm64/include/cpufunc.h
+++ b/sys/arm64/include/cpufunc.h
@@ -241,6 +241,7 @@ extern void (*arm64_icache_sync_range)(vm_offset_t, vm_size_t);
void arm64_nullop(void);
void arm64_tlb_flushID(void);
void arm64_dic_idc_icache_sync_range(vm_offset_t, vm_size_t);
+void arm64_idc_aliasing_icache_sync_range(vm_offset_t, vm_size_t);
void arm64_aliasing_icache_sync_range(vm_offset_t, vm_size_t);
int arm64_icache_sync_range_checked(vm_offset_t, vm_size_t);
void arm64_dcache_wbinv_range(vm_offset_t, vm_size_t);