From patchwork Fri Jun 22 07:52:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10481439 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 10B3260388 for ; Fri, 22 Jun 2018 07:53:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 041A328E18 for ; Fri, 22 Jun 2018 07:53:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ED10328E48; Fri, 22 Jun 2018 07:53:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7591F28E47 for ; Fri, 22 Jun 2018 07:53:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751187AbeFVHw7 (ORCPT ); Fri, 22 Jun 2018 03:52:59 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:41840 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751042AbeFVHw6 (ORCPT ); Fri, 22 Jun 2018 03:52:58 -0400 Received: by mail-wr0-f193.google.com with SMTP id h10-v6so5681116wrq.8 for ; Fri, 22 Jun 2018 00:52:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xg6I/N+SYXziOfRG5OVxZyF2OqOKsFg8pNoHQMqpD2E=; b=MURbYCHbVE0uJNogIXaZSfhvhVOIhHrMDQYu4SXU3uuoKVFmf2QMY5x/gzc69ssZTM yajhTcq4rSXLXtl34LjIMcRyuBB72NsqJNdTaAl7vkuP1Yp4cxebRyClCXn791J6lmAS y0T0ViOmYhE0JLYpd2a/7/4ewiEduirri5W+8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xg6I/N+SYXziOfRG5OVxZyF2OqOKsFg8pNoHQMqpD2E=; b=cW5i6uDqNL7pTYu/X0F8yNH+s/6UjQVX23twRmDFowPyQcYEG22DvoK4tLMvHP6nsu ohpBIRJHH+f5GeMx7L9w4JaIGBjABt0At5K70U+7h0wLtzzsOdi+Q2IBXoQf+0mXinlF SbqXW8SoSk/JAkk3ucCJsWwTjY4GVONc/P3MvmP5yCuEx/GlTslo5PBqg/Hh0tpGYB+2 JIjvo9yXkcU7i/zisbJhdxGDAFPiokc4GRNbntv41uERDiK8pJRu1VQGPkL3c1PnlyxQ mUtY8Ezo9DQrc2PVZEXdDR2BI23THB8qUsE9eFDmLk/H8Enrk5Mbp3S4rM4BhsPlvnv4 7mIw== X-Gm-Message-State: APt69E11k++KAh0L5AESCA8H75M4QFZRF+rCmH1RZ3xP1FBEbjyqZGvU NwvrWg/9ICrOclX72SbnkaHAOg== X-Google-Smtp-Source: AAOMgpdzTbSYiT8V05/vuXTonl2invA++sv5ZG0fZi8bs5QP6gnPuauh6xmJgLXVq5/D75jOeqKdOA== X-Received: by 2002:adf:88ca:: with SMTP id g10-v6mr571571wrg.62.1529653977514; Fri, 22 Jun 2018 00:52:57 -0700 (PDT) Received: from dogfood.home ([2a01:cb1d:112:6f00:d0d9:3abb:8cc4:581c]) by smtp.gmail.com with ESMTPSA id s10-v6sm1593986wmb.12.2018.06.22.00.52.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 Jun 2018 00:52:56 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: lersek@redhat.com, Ard Biesheuvel , linux-fbdev@vger.kernel.org, Bartlomiej Zolnierkiewicz , Peter Jones Subject: [PATCH v2 2/2] fbdev/efifb: honour UEFI memory map attributes when mapping the fb Date: Fri, 22 Jun 2018 09:52:50 +0200 Message-Id: <20180622075250.14075-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180622075250.14075-1-ard.biesheuvel@linaro.org> References: <20180622075250.14075-1-ard.biesheuvel@linaro.org> Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If the framebuffer address provided by the Graphics Output Protocol (GOP) is covered by the UEFI memory map, it will tell us which memory attributes are permitted when mapping this region. In some cases, (KVM guest on ARM), violating this will result in loss of coherency, which means that updates sent to the framebuffer by the guest will not be observeable by the host, and the emulated display simply does not work. So if the memory map contains such a description, take the attributes field into account, and add support for creating WT or WB mappings of the framebuffer region. Cc: linux-fbdev@vger.kernel.org Cc: Bartlomiej Zolnierkiewicz Cc: Peter Jones Tested-by: Laszlo Ersek Signed-off-by: Ard Biesheuvel Acked-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/efifb.c | 52 ++++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 46a4484e3da7..d5e0a74e6124 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c @@ -20,7 +20,7 @@ #include /* For DRM_MODE_PANEL_ORIENTATION_* */ static bool request_mem_succeeded = false; -static bool nowc = false; +static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC; static struct fb_var_screeninfo efifb_defined = { .activate = FB_ACTIVATE_NOW, @@ -68,8 +68,12 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, static void efifb_destroy(struct fb_info *info) { - if (info->screen_base) - iounmap(info->screen_base); + if (info->screen_base) { + if (mem_flags & (EFI_MEMORY_WT | EFI_MEMORY_WB)) + memunmap(info->screen_base); + else + iounmap(info->screen_base); + } if (request_mem_succeeded) release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); @@ -104,7 +108,7 @@ static int efifb_setup(char *options) else if (!strncmp(this_opt, "width:", 6)) screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); else if (!strcmp(this_opt, "nowc")) - nowc = true; + mem_flags &= ~EFI_MEMORY_WC; } } @@ -164,6 +168,8 @@ static int efifb_probe(struct platform_device *dev) unsigned int size_remap; unsigned int size_total; char *option = NULL; + efi_memory_desc_t md; + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled) return -ENODEV; @@ -272,12 +278,35 @@ static int efifb_probe(struct platform_device *dev) info->apertures->ranges[0].base = efifb_fix.smem_start; info->apertures->ranges[0].size = size_remap; - if (nowc) - info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); - else - info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); + if (!efi_mem_desc_lookup(efifb_fix.smem_start, &md)) { + if ((efifb_fix.smem_start + efifb_fix.smem_len) > + (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) { + pr_err("efifb: video memory @ 0x%lx spans multiple EFI memory regions\n", + efifb_fix.smem_start); + err = -EIO; + goto err_release_fb; + } + /* + * If the UEFI memory map covers the efifb region, we may only + * remap it using the attributes the memory map prescribes. + */ + mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB; + mem_flags &= md.attribute; + } + if (mem_flags & EFI_MEMORY_WC) + info->screen_base = ioremap_wc(efifb_fix.smem_start, + efifb_fix.smem_len); + else if (mem_flags & EFI_MEMORY_UC) + info->screen_base = ioremap(efifb_fix.smem_start, + efifb_fix.smem_len); + else if (mem_flags & EFI_MEMORY_WT) + info->screen_base = memremap(efifb_fix.smem_start, + efifb_fix.smem_len, MEMREMAP_WT); + else if (mem_flags & EFI_MEMORY_WB) + info->screen_base = memremap(efifb_fix.smem_start, + efifb_fix.smem_len, MEMREMAP_WB); if (!info->screen_base) { - pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", + pr_err("efifb: abort, cannot remap video memory 0x%x @ 0x%lx\n", efifb_fix.smem_len, efifb_fix.smem_start); err = -EIO; goto err_release_fb; @@ -371,7 +400,10 @@ static int efifb_probe(struct platform_device *dev) err_groups: sysfs_remove_groups(&dev->dev.kobj, efifb_groups); err_unmap: - iounmap(info->screen_base); + if (mem_flags & (EFI_MEMORY_WT | EFI_MEMORY_WB)) + memunmap(info->screen_base); + else + iounmap(info->screen_base); err_release_fb: framebuffer_release(info); err_release_mem: