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 <xypron.g...@gmx.de>
    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 <jmcne...@invisible.ca>
@@ -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());

Reply via email to