Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932176AbcKPMJz (ORCPT ); Wed, 16 Nov 2016 07:09:55 -0500 Received: from terminus.zytor.com ([198.137.202.10]:35032 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751688AbcKPMJw (ORCPT ); Wed, 16 Nov 2016 07:09:52 -0500 Date: Wed, 16 Nov 2016 04:07:44 -0800 From: tip-bot for David Herrmann Message-ID: Cc: matt.fleming@intel.com, teg@jklm.no, tglx@linutronix.de, hpa@zytor.com, peterz@infradead.org, mingo@kernel.org, linux-kernel@vger.kernel.org, torvalds@linux-foundation.org, dh.herrmann@gmail.com Reply-To: torvalds@linux-foundation.org, dh.herrmann@gmail.com, linux-kernel@vger.kernel.org, mingo@kernel.org, peterz@infradead.org, teg@jklm.no, matt.fleming@intel.com, hpa@zytor.com, tglx@linutronix.de In-Reply-To: <20161115120158.15388-3-dh.herrmann@gmail.com> References: <20161115120158.15388-3-dh.herrmann@gmail.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] x86/sysfb: Fix lfb_size calculation Git-Commit-ID: f96acec8c8020807429d21324547f4b904c37177 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3018 Lines: 80 Commit-ID: f96acec8c8020807429d21324547f4b904c37177 Gitweb: http://git.kernel.org/tip/f96acec8c8020807429d21324547f4b904c37177 Author: David Herrmann AuthorDate: Tue, 15 Nov 2016 13:01:58 +0100 Committer: Ingo Molnar CommitDate: Wed, 16 Nov 2016 09:38:23 +0100 x86/sysfb: Fix lfb_size calculation The screen_info.lfb_size field is shifted by 16 bits *only* in case of VBE. This has historical reasons since VBE advertised it similarly. However, in case of EFI framebuffers, the size is no longer shifted. Fix the x86 simple-framebuffer setup code to use the correct size in the non-VBE case. While at it, avoid variable abbreviations and rename 'len' to 'length', and use the correct types matching the screen_info definition. Signed-off-by: David Herrmann Acked-by: Thomas Gleixner Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Tom Gundersen Link: http://lkml.kernel.org/r/20161115120158.15388-3-dh.herrmann@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/sysfb_simplefb.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c index 35b8641..85195d4 100644 --- a/arch/x86/kernel/sysfb_simplefb.c +++ b/arch/x86/kernel/sysfb_simplefb.c @@ -66,8 +66,8 @@ __init int create_simplefb(const struct screen_info *si, { struct platform_device *pd; struct resource res; - unsigned long len; - u64 base; + u64 base, size; + u32 length; /* * If the 64BIT_BASE capability is set, ext_lfb_base will contain the @@ -82,11 +82,20 @@ __init int create_simplefb(const struct screen_info *si, return -EINVAL; } - /* don't use lfb_size as it may contain the whole VMEM instead of only - * the part that is occupied by the framebuffer */ - len = mode->height * mode->stride; - len = PAGE_ALIGN(len); - if (len > (u64)si->lfb_size << 16) { + /* + * Don't use lfb_size as IORESOURCE size, since it may contain the + * entire VMEM, and thus require huge mappings. Use just the part we + * need, that is, the part where the framebuffer is located. But verify + * that it does not exceed the advertised VMEM. + * Note that in case of VBE, the lfb_size is shifted by 16 bits for + * historical reasons. + */ + size = si->lfb_size; + if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) + size <<= 16; + length = mode->height * mode->stride; + length = PAGE_ALIGN(length); + if (length > size) { printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n"); return -EINVAL; } @@ -96,7 +105,7 @@ __init int create_simplefb(const struct screen_info *si, res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; res.name = simplefb_resname; res.start = base; - res.end = res.start + len - 1; + res.end = res.start + length - 1; if (res.end <= res.start) return -EINVAL;