git: 6fdb5daba679 - stable/13 - efifb: add a tunable to select the framebuffer cache attribute

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 17 Mar 2023 05:48:39 UTC
The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=6fdb5daba679128b11b6ce3a401fb74d0db07fd8

commit 6fdb5daba679128b11b6ce3a401fb74d0db07fd8
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2023-03-01 06:04:49 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2023-03-17 05:01:45 +0000

    efifb: add a tunable to select the framebuffer cache attribute
    
    Mapping the framebuffer with WC (Write Combined) memory type can, in
    practice, cause some memory transactions to be rate-limited at a
    fraction of the fb write rate.  WC allows one core to queue up many
    globally visible write transactions, and in the process some unrelated
    transactions may end up having to wait for all of the queued up PCI
    writes to be flushed.
    
    Add an hw.efifb.cache_attr tunable to allow mapping the framebuffer as
    uncacheable instead.  We should likely be taking a more careful approach
    of checking the memory map to determine which cacheability attributes
    are feasible, but the knob lets us use our historically functional
    behavior while offering a convenient way to switch on a stock kernel.
    
    The only valid values for hw.efifb.cache_attr at this time are "uc" and
    "wc".
    
    Original patch by Marc De La Gueronniere <mdelagueronniere@verisign.com>
    along with previous testing.
    
    Reviewed by:    imp
    Sponsored by:   Verisign, Inc.
    Sponsored by:   Klara, Inc.
    
    (cherry picked from commit 8dff0b6761407357c5bb42ee799c5c9f465557a3)
---
 sys/dev/vt/hw/efifb/efifb.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c
index 3aaeebcb1b5e..20822629d0c5 100644
--- a/sys/dev/vt/hw/efifb/efifb.c
+++ b/sys/dev/vt/hw/efifb/efifb.c
@@ -103,7 +103,32 @@ vt_efifb_init(struct vt_device *vd)
 	struct fb_info	*info;
 	struct efi_fb	*efifb;
 	caddr_t		kmdp;
+	int		memattr;
 	int		roff, goff, boff;
+	char		attr[16];
+
+	/*
+	 * XXX TODO: I think there's more nuance here than we're acknowledging,
+	 * and we should look into it.  It may be that the framebuffer lives in
+	 * a segment of memory that doesn't support one or both of these.  We
+	 * should likely be consulting the memory map for any applicable
+	 * cacheability attributes before making a final decision.
+	 */
+	memattr = VM_MEMATTR_WRITE_COMBINING;
+	if (TUNABLE_STR_FETCH("hw.efifb.cache_attr", attr, sizeof(attr))) {
+		/*
+		 * We'll allow WC but it's currently the default, UC is the only
+		 * other tested one at this time.
+		 */
+		if (strcasecmp(attr, "wc") != 0 &&
+		    strcasecmp(attr, "uc") != 0) {
+			printf("efifb: unsupported cache attr specified: %s\n",
+			    attr);
+			printf("efifb: expected \"wc\" or \"uc\"\n");
+		} else if (strcasecmp(attr, "uc") == 0) {
+			memattr = VM_MEMATTR_UNCACHEABLE;
+		}
+	}
 
 	info = vd->vd_softc;
 	if (info == NULL)
@@ -141,7 +166,7 @@ vt_efifb_init(struct vt_device *vd)
 	info->fb_size = info->fb_height * info->fb_stride;
 	info->fb_pbase = efifb->fb_addr;
 	info->fb_vbase = (intptr_t)pmap_mapdev_attr(info->fb_pbase,
-	    info->fb_size, VM_MEMATTR_WRITE_COMBINING);
+	    info->fb_size, memattr);
 
 	vt_fb_init(vd);