From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932798AbbJ3UYq (ORCPT ); Fri, 30 Oct 2015 16:24:46 -0400 Received: from mga11.intel.com ([192.55.52.93]:56883 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752740AbbJ3UYp (ORCPT ); Fri, 30 Oct 2015 16:24:45 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,220,1444719600"; d="scan'208";a="839590321" Subject: [for 4.3-final PATCH v2] memremap: fix highmem support From: Dan Williams To: linux-arm-kernel@lists.infradead.org Cc: rmk+kernel@arm.linux.org.uk, "Rafael J. Wysocki" , linux-kernel@vger.kernel.org, Ard Biesheuvel Date: Fri, 30 Oct 2015 16:19:03 -0400 Message-ID: <20151030201758.13415.13264.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently memremap checks if the range is "System RAM" and returns the kernel linear address. This is broken for highmem platforms where a range may be "System RAM", but is not part of the kernel linear mapping. Fallback to ioremap_cache() in these cases, to let the arch code attempt to handle it. Note that ARM ioremap will WARN when attempting to remap ram, and in that case the caller needs to be fixed. For this reason, existing ioremap_cache() usages for ARM are already trained to avoid attempts to remap ram. The impact of this bug is low for now since the pmem driver is the only user of memremap(), but this is important to fix before more conversions to memremap arrive in 4.4. Cc: Rafael J. Wysocki Reported-by: Ard Biesheuvel Signed-off-by: Dan Williams --- kernel/memremap.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/memremap.c b/kernel/memremap.c index 72b0c66628b6..9d6b55587eaa 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -24,6 +24,16 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size) } #endif +static void *try_ram_remap(resource_size_t offset, size_t size) +{ + struct page *page = pfn_to_page(offset >> PAGE_SHIFT); + + /* In the simple case just return the existing linear address */ + if (!PageHighMem(page)) + return __va(offset); + return NULL; /* fallback to ioremap_cache */ +} + /** * memremap() - remap an iomem_resource as cacheable memory * @offset: iomem resource start address @@ -66,8 +76,8 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) * the requested range is potentially in "System RAM" */ if (is_ram == REGION_INTERSECTS) - addr = __va(offset); - else + addr = try_ram_remap(offset, size); + if (!addr) addr = ioremap_cache(offset, size); }