Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757138Ab2HIVYE (ORCPT ); Thu, 9 Aug 2012 17:24:04 -0400 Received: from co1ehsobe006.messaging.microsoft.com ([216.32.180.189]:56822 "EHLO co1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753749Ab2HIVX2 (ORCPT ); Thu, 9 Aug 2012 17:23:28 -0400 X-Forefront-Antispam-Report: CIP:163.181.249.109;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp02.amd.com;RD:none;EFVD:NLI X-SpamScore: 0 X-BigFish: VPS0(zzzz1202hzz8275bhz2dh668h839hd24he5bhf0ah107ah) X-WSS-ID: 0M8IBEX-02-FMG-02 X-M-MSG: From: Jacob Shin To: X86-ML CC: LKML , Yinghai Lu , "H. Peter Anvin" , Andreas Herrmann , Jacob Shin Subject: [PATCH 1/5] x86: Only direct map addresses that are marked as E820_RAM Date: Thu, 9 Aug 2012 16:23:05 -0500 Message-ID: <1344547389-4599-2-git-send-email-jacob.shin@amd.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1344547389-4599-1-git-send-email-jacob.shin@amd.com> References: <1344547389-4599-1-git-send-email-jacob.shin@amd.com> MIME-Version: 1.0 Content-Type: text/plain X-OriginatorOrg: amd.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5095 Lines: 176 Currently direct mappings are created for [ 0 to max_low_pfn< --- arch/x86/include/asm/page_types.h | 9 ++++ arch/x86/kernel/setup.c | 87 +++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h index e21fdd1..0b8aa52 100644 --- a/arch/x86/include/asm/page_types.h +++ b/arch/x86/include/asm/page_types.h @@ -3,6 +3,7 @@ #include #include +#include /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 @@ -40,12 +41,20 @@ #endif /* CONFIG_X86_64 */ #ifndef __ASSEMBLY__ +#include extern int devmem_is_allowed(unsigned long pagenr); extern unsigned long max_low_pfn_mapped; extern unsigned long max_pfn_mapped; +extern struct range pfn_mapped[E820_X_MAX]; +extern int nr_pfn_mapped; + +extern void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn); +extern int pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn); +extern int pfn_is_mapped(unsigned long pfn); + static inline phys_addr_t get_max_mapped(void) { return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f4b9b80..4f26944 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -115,13 +115,55 @@ #include /* - * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. - * The direct mapping extends to max_pfn_mapped, so that we can directly access - * apertures, ACPI and other tables without having to play with fixmaps. + * max_low_pfn_mapped: highest direct mapped pfn under 4GB + * max_pfn_mapped: highest direct mapped pfn over 4GB + * + * The direct mapping only covers E820_RAM regions, so the ranges and gaps are + * represented by pfn_mapped */ unsigned long max_low_pfn_mapped; unsigned long max_pfn_mapped; +struct range pfn_mapped[E820_X_MAX]; +int nr_pfn_mapped; + +void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn) +{ + nr_pfn_mapped = add_range_with_merge(pfn_mapped, E820_X_MAX, + nr_pfn_mapped, start_pfn, end_pfn); + + if (end_pfn > max_pfn_mapped) + max_pfn_mapped = end_pfn; + + if ((end_pfn <= (1UL << (32 - PAGE_SHIFT))) && + (end_pfn > max_low_pfn_mapped)) + max_low_pfn_mapped = end_pfn; +} + +int pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn) +{ + int i; + + for (i = 0; i < nr_pfn_mapped; i++) + if ((start_pfn >= pfn_mapped[i].start) && + (end_pfn <= pfn_mapped[i].end)) + break; + + return i < nr_pfn_mapped; +} + +int pfn_is_mapped(unsigned long pfn) +{ + int i; + + for (i = 0; i < nr_pfn_mapped; i++) + if ((pfn >= pfn_mapped[i].start) && + (pfn < pfn_mapped[i].end)) + break; + + return i < nr_pfn_mapped; +} + #ifdef CONFIG_DMI RESERVE_BRK(dmi_alloc, 65536); #endif @@ -673,6 +715,9 @@ early_param("reservelow", parse_reservelow); void __init setup_arch(char **cmdline_p) { + int i; + unsigned long init_pfn, pfn; + #ifdef CONFIG_X86_32 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); visws_early_detect(); @@ -913,14 +958,40 @@ void __init setup_arch(char **cmdline_p) init_gbpages(); - /* max_pfn_mapped is updated here */ - max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<addr; + u64 end = ei->addr + ei->size; + + if (ei->type != E820_RAM) + continue; + + if (end <= (init_pfn << PAGE_SHIFT)) + continue; + + if (start < (init_pfn << PAGE_SHIFT)) + start = init_pfn << PAGE_SHIFT; + +#ifdef CONFIG_X86_32 + if ((start >> PAGE_SHIFT) >= max_low_pfn) + continue; + + if ((end >> PAGE_SHIFT) > max_low_pfn) + end = max_low_pfn << PAGE_SHIFT; +#endif + pfn = init_memory_mapping(start, end); + add_pfn_range_mapped(start >> PAGE_SHIFT, pfn); + } #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn<