Module Name: src
Committed By: skrll
Date: Wed Sep 18 19:43:29 UTC 2024
Modified Files:
src/sys/stand/efiboot/bootarm: cache.S efibootarm.c
Log Message:
Clean and invalidate the full data cache as the armv6_start.S code assumes
that the caches are disabled on entry which armv7_exec_kernel ensures.
When caches are disabled armv6_start.S will invalidate (not clean) the
cache and this can lose u-boot data for the u-boots that now don't
perform their own cache maintenance.
An example of such a u-boot is the banana pro that chuq@ has tried which
has
commit 8b5dea33584261cc5d600614970d1cbed6d99f91
Author: Heinrich Schuchardt <[email protected]>
Date: Wed Mar 3 14:05:05 2021 +0100
efi_loader: disable GRUB_ARM32_WORKAROUND on ARCH_SUNXI
applied.
Improving things so that the architected caches could remain on would be
better, but that's a much bigger change / set of changes.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/stand/efiboot/bootarm/cache.S
cvs rdiff -u -r1.4 -r1.5 src/sys/stand/efiboot/bootarm/efibootarm.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/stand/efiboot/bootarm/cache.S
diff -u src/sys/stand/efiboot/bootarm/cache.S:1.1 src/sys/stand/efiboot/bootarm/cache.S:1.2
--- src/sys/stand/efiboot/bootarm/cache.S:1.1 Sat Mar 30 12:48:50 2019
+++ src/sys/stand/efiboot/bootarm/cache.S Wed Sep 18 19:43:29 2024
@@ -53,6 +53,67 @@ ENTRY(armv7_dcache_wbinv_range)
bx lr
END(armv7_dcache_wbinv_range)
+/* LINTSTUB: void armv7_dcache_wbinv_all(void); */
+ENTRY_NP(armv7_dcache_wbinv_all)
+ mrc p15, 1, r0, c0, c0, 1 @ read CLIDR
+ tst r0, #0x07000000
+ bxeq lr
+ mov r3, #0 @ start with L1
+
+.Lstart_wbinv:
+ add r2, r3, r3, lsr #1 @ r2 = level * 3 / 2
+ mov r1, r0, lsr r2 @ r1 = cache type
+ tst r1, #6 @ is it unified or data?
+ beq .Lnext_level_wbinv @ nope, skip level
+
+ mcr p15, 2, r3, c0, c0, 0 @ select cache level
+ isb
+ mrc p15, 1, r0, c0, c0, 0 @ read CCSIDR
+
+ ubfx ip, r0, #0, #3 @ get linesize from CCSIDR
+ add ip, ip, #4 @ apply bias
+ ubfx r2, r0, #13, #15 @ get numsets - 1 from CCSIDR
+ lsl r2, r2, ip @ shift to set position
+ orr r3, r3, r2 @ merge set into way/set/level
+ mov r1, #1
+ lsl r1, r1, ip @ r1 = set decr
+
+ ubfx ip, r0, #3, #10 @ get numways - 1 from [to be discarded] CCSIDR
+ clz r2, ip @ number of bits to MSB of way
+ lsl ip, ip, r2 @ shift by that into way position
+ mov r0, #1 @
+ lsl r2, r0, r2 @ r2 now contains the way decr
+ mov r0, r3 @ get sets/level (no way yet)
+ orr r3, r3, ip @ merge way into way/set/level
+ bfc r0, #0, #4 @ clear low 4 bits (level) to get numset - 1
+ sub r2, r2, r0 @ subtract from way decr
+
+ /* r3 = ways/sets/level, r2 = way decr, r1 = set decr, r0 and ip are free */
+1: mcr p15, 0, r3, c7, c14, 2 @ DCCISW (data cache clean and invalidate by set/way)
+ cmp r3, #15 @ are we done with this level (way/set == 0)
+ bls .Lnext_level_wbinv @ yes, go to next level
+ ubfx r0, r3, #4, #18 @ extract set bits
+ cmp r0, #0 @ compare
+ subne r3, r3, r1 @ non-zero?, decrement set #
+ subeq r3, r3, r2 @ zero?, decrement way # and restore set count
+ b 1b
+
+.Lnext_level_wbinv:
+ dsb
+ mrc p15, 1, r0, c0, c0, 1 @ read CLIDR
+ ubfx ip, r0, #24, #3 @ narrow to LoC
+ add r3, r3, #2 @ go to next level
+ cmp r3, ip, lsl #1 @ compare
+ blt .Lstart_wbinv @ not done, next level (r0 == CLIDR)
+
+.Ldone_wbinv:
+ mov r0, #0 @ default back to cache level 0
+ mcr p15, 2, r0, c0, c0, 0 @ select cache level
+ dsb
+ isb
+ bx lr
+END(armv7_dcache_wbinv_all)
+
/* * LINTSTUB: void armv7_icache_inv_all(void); */
ENTRY_NP(armv7_icache_inv_all)
mov r0, #0
Index: src/sys/stand/efiboot/bootarm/efibootarm.c
diff -u src/sys/stand/efiboot/bootarm/efibootarm.c:1.4 src/sys/stand/efiboot/bootarm/efibootarm.c:1.5
--- src/sys/stand/efiboot/bootarm/efibootarm.c:1.4 Thu Aug 15 06:15:17 2024
+++ src/sys/stand/efiboot/bootarm/efibootarm.c Wed Sep 18 19:43:29 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: efibootarm.c,v 1.4 2024/08/15 06:15:17 skrll Exp $ */
+/* $NetBSD: efibootarm.c,v 1.5 2024/09/18 19:43:29 skrll Exp $ */
/*-
* Copyright (c) 2019 Jared McNeill <[email protected]>
@@ -35,6 +35,7 @@
/* cache.S */
void armv7_dcache_wbinv_range(vaddr_t, vsize_t);
+void armv7_dcache_wbinv_all(void);
void armv7_icache_inv_all(void);
void armv7_exec_kernel(register_t, register_t);
@@ -47,13 +48,7 @@ efi_dcache_flush(u_long start, u_long si
void
efi_boot_kernel(u_long marks[MARK_MAX])
{
- u_long kernel_size;
-
- kernel_size = marks[MARK_END] - marks[MARK_START];
-
- armv7_dcache_wbinv_range(marks[MARK_START], kernel_size);
- if (efi_fdt_size() > 0)
- armv7_dcache_wbinv_range((u_long)efi_fdt_data(), efi_fdt_size());
+ armv7_dcache_wbinv_all();
armv7_icache_inv_all();
armv7_exec_kernel((register_t)marks[MARK_ENTRY], (register_t)efi_fdt_data());