:: commit 04d22b1e528937578297294159e9eb82e7e68509

Kacper Słomiński <kacper.slominski72@gmail.com> — 2022-11-23 00:03

parents: ffaaabf14a

limine: Fix caching mode detection for multiple framebuffers on AArch64

diff --git a/common/protos/limine.c b/common/protos/limine.c
index 36992b2e..b6a82386 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -852,18 +852,21 @@ FEAT_END
 #endif
 
 #if defined (__aarch64__)
-    uint64_t fb_attr = 0x00;
-    if (fb.framebuffer_addr) {
+    // Find the most restrictive caching mode from all framebuffers to use
+    uint64_t fb_attr = (uint64_t)-1;
+
+    for (size_t i = 0; i < fbs_count; i++) {
         int el = current_el();
         uint64_t res;
 
+        // Figure out the caching mode used for this particular framebuffer
         if (el == 1) {
             asm volatile (
                     "at s1e1w, %1\n\t"
                     "isb\n\t"
                     "mrs %0, par_el1"
                     : "=r"(res)
-                    : "r"(fb.framebuffer_addr)
+                    : "r"(fbs[i].framebuffer_addr)
                     : "memory");
         } else if (el == 2) {
             asm volatile (
@@ -871,7 +874,7 @@ FEAT_END
                     "isb\n\t"
                     "mrs %0, par_el1"
                     : "=r"(res)
-                    : "r"(fb.framebuffer_addr)
+                    : "r"(fbs[i].framebuffer_addr)
                     : "memory");
         } else {
             panic(false, "Unexpected EL in limine_load");
@@ -880,8 +883,26 @@ FEAT_END
         if (res & 1)
             panic(false, "Address translation for framebuffer failed");
 
-        fb_attr = res >> 56;
+        uint64_t new_attr = res >> 56;
+
+        // Use whatever we find first
+        if (fb_attr == (uint64_t)-1)
+            fb_attr = new_attr;
+        // Prefer Device memory over Normal memory
+        else if ((fb_attr & 0b11110000) && !(new_attr & 0b11110000))
+            fb_attr = new_attr;
+        // Prefer tighter Device memory (lower values)
+        else if (!(fb_attr & 0b11110000) && !(new_attr & 0b11110000) && fb_attr > new_attr)
+            fb_attr = new_attr;
+        // Use Normal non-cacheable otherwise (avoid trying to figure out how to downgrade inner vs outer).
+        else if ((fb_attr & 0b11110000) && (new_attr & 0b11110000))
+            fb_attr = 0b01000100; // Inner&outer Non-cacheable
+        // Otherwise do nothing (fb_attr is already more restrictive than new_attr).
     }
+
+    // If no framebuffers are found, just zero out the MAIR entry
+    if (fb_attr == (uint64_t)-1)
+        fb_attr = 0;
 #endif
 
     void *stack = ext_mem_alloc(stack_size) + stack_size;
tab: 248 wrap: offon