On Monday 11 February 2008 14:08:43 Ingo Molnar wrote:Yes EFI needs to know this to decide if it should ioremap or not. I repeat: "This is needed for other code that needs to know the true mapping alias state (in this case EFI)." and "This is important for code that really needs to know about all mapping aliases. Needed for followup patches (in this case EFI)" Ok patch with hungarized variables appended. -Andi --- Account overlapped mappings in end_pfn_map When end_pfn is not aligned to 2MB (or 1GB) then the kernel might map more memory than end_pfn. Account this in end_pfn_mapped. This is needed for other code that needs to know the true mapping alias state (in this case EFI). But it's also more correct in general Cc: ying.huang@intel.com Signed-off-by: Andi Kleen <ak@suse.de> --- arch/x86/kernel/setup_64.c | 4 +++- arch/x86/mm/init_64.c | 33 +++++++++++++++++++++++---------- include/asm-x86/proto.h | 2 +- 3 files changed, 27 insertions(+), 12 deletions(-) Index: linux/arch/x86/mm/init_64.c =================================================================== --- linux.orig/arch/x86/mm/init_64.c +++ linux/arch/x86/mm/init_64.c @@ -287,7 +287,7 @@ __meminit void early_iounmap(void *addr, __flush_tlb_all(); } -static void __meminit +static unsigned long __meminit phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) { int i = pmd_index(address); @@ -309,21 +309,25 @@ phys_pmd_init(pmd_t *pmd_page, unsigned set_pte((pte_t *)pmd, pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); } + return address; } -static void __meminit +static unsigned long __meminit phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) { + unsigned long true_end; pmd_t *pmd = pmd_offset(pud, 0); spin_lock(&init_mm.page_table_lock); - phys_pmd_init(pmd, address, end); + true_end = phys_pmd_init(pmd, address, end); spin_unlock(&init_mm.page_table_lock); __flush_tlb_all(); + return true_end; } -static void __meminit +static unsigned long __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) { + unsigned long true_end = end; int i = pud_index(addr); for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) { @@ -342,13 +346,14 @@ phys_pud_init(pud_t *pud_page, unsigned if (pud_val(*pud)) { if (!pud_large(*pud)) - phys_pmd_update(pud, addr, end); + true_end = phys_pmd_update(pud, addr, end); continue; } if (direct_gbpages) { set_pte((pte_t *)pud, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); + true_end = (addr & PUD_MASK) + PUD_SIZE; continue; } @@ -356,12 +361,14 @@ phys_pud_init(pud_t *pud_page, unsigned spin_lock(&init_mm.page_table_lock); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - phys_pmd_init(pmd, addr, end); + true_end = phys_pmd_init(pmd, addr, end); spin_unlock(&init_mm.page_table_lock); unmap_low_page(pmd); } __flush_tlb_all(); + + return true_end >> PAGE_SHIFT; } static void __init find_early_table_space(unsigned long end) @@ -406,9 +413,10 @@ static void __init init_gbpages(void) * This runs before bootmem is initialized and gets pages directly from * the physical memory. To access them they are temporarily mapped. */ -void __init_refok init_memory_mapping(unsigned long start, unsigned long end) +unsigned long __init_refok +init_memory_mapping(unsigned long start, unsigned long end) { - unsigned long next; + unsigned long next, true_end = end; pr_debug("init_memory_mapping\n"); @@ -446,7 +454,7 @@ void __init_refok init_memory_mapping(un next = start + PGDIR_SIZE; if (next > end) next = end; - phys_pud_init(pud, __pa(start), __pa(next)); + true_end = phys_pud_init(pud, __pa(start), __pa(next)); set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(pud); } @@ -458,6 +466,8 @@ void __init_refok init_memory_mapping(un if (!after_bootmem) reserve_early(table_start << PAGE_SHIFT, table_end << PAGE_SHIFT, "PGTABLE"); + + return true_end; } #ifndef CONFIG_NUMA @@ -499,9 +509,12 @@ int arch_add_memory(int nid, u64 start, struct zone *zone = pgdat->node_zones + ZONE_NORMAL; unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; + unsigned long true_end_pfn; int ret; - init_memory_mapping(start, start + size-1); + true_end_pfn = init_memory_mapping(start, start + size-1); + if (true_end_pfn > end_pfn_map) + end_pfn_map = true_end_pfn; ret = __add_pages(zone, start_pfn, nr_pages); WARN_ON(1); Index: linux/include/asm-x86/proto.h =================================================================== --- linux.orig/include/asm-x86/proto.h +++ linux/include/asm-x86/proto.h @@ -7,7 +7,8 @@ extern void early_idt_handler(void); -extern void init_memory_mapping(unsigned long start, unsigned long end); +extern unsigned long init_memory_mapping(unsigned long start, + unsigned long end); extern void system_call(void); extern void syscall_init(void); Index: linux/arch/x86/kernel/setup_64.c =================================================================== --- linux.orig/arch/x86/kernel/setup_64.c +++ linux/arch/x86/kernel/setup_64.c @@ -341,7 +341,7 @@ void __init setup_arch(char **cmdline_p) check_efer(); - init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); + end_pfn_map = init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); if (efi_enabled) efi_init(); --
| Greg Kroah-Hartman | [PATCH 001/196] Chinese: Add the known_regression URI to the HOWTO |
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Amit K. Arora | [RFC] Heads up on sys_fallocate() |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
git: | |
| David Miller | [GIT]: Networking |
| Gerrit Renker | [PATCH 27/37] dccp: Integration of dynamic feature activation - part 2 (server side) |
| David Miller | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Frans Pop | svc: failed to register lockdv1 RPC service (errno 97). |
