Flush the D-cache before we disable the cache. This makes more sense and
authorkettenis <kettenis@openbsd.org>
Sun, 3 Mar 2024 17:00:14 +0000 (17:00 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 3 Mar 2024 17:00:14 +0000 (17:00 +0000)
fixes booting on my A10S-OLinuXino-MICRO board.  Since the cache is still
enabled, the CPU might bring back some of the cache lines we just flushed.
So invalidate the cache after disabling.

ok deraadt@

sys/arch/armv7/stand/efiboot/conf.c
sys/arch/armv7/stand/efiboot/exec.c

index 78a416f..e7ffa3d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.33 2022/12/22 15:44:02 kettenis Exp $      */
+/*     $OpenBSD: conf.c,v 1.34 2024/03/03 17:00:14 kettenis Exp $      */
 
 /*
  * Copyright (c) 1996 Michael Shalayeff
@@ -42,7 +42,7 @@
 #include "efidev.h"
 #include "efipxe.h"
 
-const char version[] = "1.20";
+const char version[] = "1.21";
 int    debug = 0;
 
 struct fs_ops file_system[] = {
index 31f3b67..29cee33 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: exec.c,v 1.16 2020/05/17 14:32:12 kettenis Exp $      */
+/*     $OpenBSD: exec.c,v 1.17 2024/03/03 17:00:14 kettenis Exp $      */
 
 /*
  * Copyright (c) 2006, 2016 Mark Kettenis
@@ -86,6 +86,47 @@ dcache_wbinv_all(void)
        __asm volatile("dsb");
 }
 
+void
+dcache_inv_all(void)
+{
+       uint32_t clidr;
+       uint32_t ccsidr;
+       uint32_t val;
+       int nways, nsets;
+       int wshift, sshift;
+       int way, set;
+       int level;
+       
+       __asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r"(clidr));
+       for (level = 0; level < CLIDR_LOC(clidr); level++) {
+               if (CLIDR_CTYPE(clidr, level) == CLIDR_CTYPE_NOCACHE)
+                       break;
+               if (CLIDR_CTYPE(clidr, level) == CLIDR_CTYPE_ICACHE)
+                       continue;
+
+               __asm volatile("mcr p15, 2, %0, c0, c0, 0" :: "r"(level << 1));
+               __asm volatile("isb");
+               __asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r"(ccsidr));
+
+               nways = CCSIDR_ASSOCIATIVITY(ccsidr) + 1;
+               nsets = CCSIDR_NUMSETS(ccsidr) + 1;
+
+               sshift = CCSIDR_LINESZ(ccsidr) + 4;
+               wshift = __builtin_clz(CCSIDR_ASSOCIATIVITY(ccsidr));
+
+               for (way = 0; way < nways; way++) {
+                       for (set = 0; set < nsets; set++) {
+                               val = (way << wshift) | (set << sshift) |
+                                   (level << 1);
+                               __asm volatile("mcr p15, 0, %0, c7, c6, 2"
+                                   :: "r"(val));
+                       }
+               }
+       }
+
+       __asm volatile("dsb");
+}
+
 void
 icache_inv_all(void)
 {
@@ -182,8 +223,9 @@ run_loadfile(uint64_t *marks, int howto)
 
        efi_cleanup();
 
-       dcache_disable();
        dcache_wbinv_all();
+       dcache_disable();
+       dcache_inv_all();
        icache_disable();
        icache_inv_all();
        mmu_disable();