From patchwork Wed Mar 4 08:00:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 446132 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 81FD91400DD for ; Wed, 4 Mar 2015 19:03:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934811AbbCDICv (ORCPT ); Wed, 4 Mar 2015 03:02:51 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:42676 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933881AbbCDIBo (ORCPT ); Wed, 4 Mar 2015 03:01:44 -0500 Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id t2481UvW032471 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 4 Mar 2015 08:01:31 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by ucsinet22.oracle.com (8.14.5+Sun/8.14.5) with ESMTP id t2481Th8015873 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 4 Mar 2015 08:01:30 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id t2481TRK016803; Wed, 4 Mar 2015 08:01:29 GMT Received: from linux-siqj.site (/10.154.130.125) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 04 Mar 2015 00:01:24 -0800 From: Yinghai Lu To: Matt Fleming , "H. Peter Anvin" , Bjorn Helgaas Cc: Thomas Gleixner , Ingo Molnar , Jiri Kosina , Borislav Petkov , Baoquan He , linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, linux-pci@vger.kernel.org, Yinghai Lu Subject: [PATCH v2 14/15] x86, boot: copy rom to kernel space Date: Wed, 4 Mar 2015 00:00:47 -0800 Message-Id: <1425456048-16236-15-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1425456048-16236-1-git-send-email-yinghai@kernel.org> References: <1425456048-16236-1-git-send-email-yinghai@kernel.org> X-Source-IP: ucsinet22.oracle.com [156.151.31.94] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org As EFI stub code could put them high when on 32bit or with exactmap= on 64bit conf. Check is the range is mapped, otherwise allocate new one and have the rom data copied. So we could really avoid ioremap. Signed-off-by: Yinghai Lu --- arch/x86/pci/common.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 93577fb..a5de331 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -694,6 +694,48 @@ struct firmware_setup_pci_entry { static LIST_HEAD(setup_pci_entries); +static phys_addr_t check_copy(phys_addr_t start, unsigned long size) +{ + unsigned long start_pfn = PFN_DOWN(start); + unsigned long end_pfn = PFN_UP(start + size); + unsigned char *p, *q; + phys_addr_t pa_p, pa_q; + long sz = size; + + if (pfn_range_is_mapped(start_pfn, end_pfn)) + return start; + + /* allocate and copy */ + pa_p = memblock_alloc(size, PAGE_SIZE); + if (!pa_p) + return start; + + p = phys_to_virt(pa_p); + + pa_q = start; + while (sz > 0) { + long chunk_size = 64<<10; + + if (chunk_size > sz) + chunk_size = sz; + + q = early_memremap(pa_q, chunk_size); + if (!q) { + memblock_free(pa_p, size); + return start; + } + memcpy(p, q, chunk_size); + early_memunmap(q, chunk_size); + p += chunk_size; + pa_q += chunk_size; + sz -= chunk_size; + } + + early_memunmap(start, size); + + return pa_p; +} + int __init fill_setup_pci_entries(void) { struct setup_data *data; @@ -723,8 +765,9 @@ int __init fill_setup_pci_entries(void) entry->vendor = rom->vendor; entry->devid = rom->devid; entry->pcilen = rom->pcilen; - entry->romdata = pa_data + - offsetof(struct pci_setup_rom, romdata); + entry->romdata = check_copy(pa_data + + offsetof(struct pci_setup_rom, romdata), + rom->pcilen); list_add(&entry->list, &setup_pci_entries);