aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2007-10-16 04:24:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:51 -0400
commit0889eba5b38f66d7d892a167d88284daddd3d43b (patch)
treeadb578bb92cc18dbf842a9bde67e3861db030557
parent29c71111d0557385328211b130246a90f9223b46 (diff)
x86_64: SPARSEMEM_VMEMMAP 2M page size support
x86_64 uses 2M page table entries to map its 1-1 kernel space. We also implement the virtual memmap using 2M page table entries. So there is no additional runtime overhead over FLATMEM, initialisation is slightly more complex. As FLATMEM still references memory to obtain the mem_map pointer and SPARSEMEM_VMEMMAP uses a compile time constant, SPARSEMEM_VMEMMAP should be superior. With this SPARSEMEM becomes the most efficient way of handling virt_to_page, pfn_to_page and friends for UP, SMP and NUMA on x86_64. [apw@shadowen.org: code resplit, style fixups] [apw@shadowen.org: vmemmap x86_64: ensure end of section memmap is initialised] Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andy Whitcroft <apw@shadowen.org> Acked-by: Mel Gorman <mel@csn.ul.ie> Cc: Andi Kleen <ak@suse.de> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/x86_64/mm.txt1
-rw-r--r--arch/x86/mm/init_64.c45
-rw-r--r--arch/x86_64/Kconfig1
-rw-r--r--include/asm-x86/page_64.h1
-rw-r--r--include/asm-x86/pgtable_64.h1
5 files changed, 49 insertions, 0 deletions
diff --git a/Documentation/x86_64/mm.txt b/Documentation/x86_64/mm.txt
index f42798ed1c54..b89b6d2bebfa 100644
--- a/Documentation/x86_64/mm.txt
+++ b/Documentation/x86_64/mm.txt
@@ -9,6 +9,7 @@ ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
9ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory 9ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory
10ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole 10ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole
11ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space 11ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space
12ffffe20000000000 - ffffe2ffffffffff (=40 bits) virtual memory map (1TB)
12... unused hole ... 13... unused hole ...
13ffffffff80000000 - ffffffff82800000 (=40 MB) kernel text mapping, from phys 0 14ffffffff80000000 - ffffffff82800000 (=40 MB) kernel text mapping, from phys 0
14... unused hole ... 15... unused hole ...
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 458893b376f8..7d4fc633a9c9 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -748,3 +748,48 @@ const char *arch_vma_name(struct vm_area_struct *vma)
748 return "[vsyscall]"; 748 return "[vsyscall]";
749 return NULL; 749 return NULL;
750} 750}
751
752#ifdef CONFIG_SPARSEMEM_VMEMMAP
753/*
754 * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
755 */
756int __meminit vmemmap_populate(struct page *start_page,
757 unsigned long size, int node)
758{
759 unsigned long addr = (unsigned long)start_page;
760 unsigned long end = (unsigned long)(start_page + size);
761 unsigned long next;
762 pgd_t *pgd;
763 pud_t *pud;
764 pmd_t *pmd;
765
766 for (; addr < end; addr = next) {
767 next = pmd_addr_end(addr, end);
768
769 pgd = vmemmap_pgd_populate(addr, node);
770 if (!pgd)
771 return -ENOMEM;
772 pud = vmemmap_pud_populate(pgd, addr, node);
773 if (!pud)
774 return -ENOMEM;
775
776 pmd = pmd_offset(pud, addr);
777 if (pmd_none(*pmd)) {
778 pte_t entry;
779 void *p = vmemmap_alloc_block(PMD_SIZE, node);
780 if (!p)
781 return -ENOMEM;
782
783 entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
784 mk_pte_huge(entry);
785 set_pmd(pmd, __pmd(pte_val(entry)));
786
787 printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
788 addr, addr + PMD_SIZE - 1, p, node);
789 } else
790 vmemmap_verify((pte_t *)pmd, node, addr, next);
791 }
792
793 return 0;
794}
795#endif
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index cf013cb85ea4..8c83dbe4c4d0 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -409,6 +409,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
409config ARCH_SPARSEMEM_ENABLE 409config ARCH_SPARSEMEM_ENABLE
410 def_bool y 410 def_bool y
411 depends on (NUMA || EXPERIMENTAL) 411 depends on (NUMA || EXPERIMENTAL)
412 select SPARSEMEM_VMEMMAP_ENABLE
412 413
413config ARCH_MEMORY_PROBE 414config ARCH_MEMORY_PROBE
414 def_bool y 415 def_bool y
diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
index 88adf1afb0a2..c3b52bcb171e 100644
--- a/include/asm-x86/page_64.h
+++ b/include/asm-x86/page_64.h
@@ -134,6 +134,7 @@ extern unsigned long __phys_addr(unsigned long);
134 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 134 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
135 135
136#define __HAVE_ARCH_GATE_AREA 1 136#define __HAVE_ARCH_GATE_AREA 1
137#define vmemmap ((struct page *)VMEMMAP_START)
137 138
138#include <asm-generic/memory_model.h> 139#include <asm-generic/memory_model.h>
139#include <asm-generic/page.h> 140#include <asm-generic/page.h>
diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
index 57dd6b3107ea..a79f5355e3b0 100644
--- a/include/asm-x86/pgtable_64.h
+++ b/include/asm-x86/pgtable_64.h
@@ -137,6 +137,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
137#define MAXMEM _AC(0x3fffffffffff, UL) 137#define MAXMEM _AC(0x3fffffffffff, UL)
138#define VMALLOC_START _AC(0xffffc20000000000, UL) 138#define VMALLOC_START _AC(0xffffc20000000000, UL)
139#define VMALLOC_END _AC(0xffffe1ffffffffff, UL) 139#define VMALLOC_END _AC(0xffffe1ffffffffff, UL)
140#define VMEMMAP_START _AC(0xffffe20000000000, UL)
140#define MODULES_VADDR _AC(0xffffffff88000000, UL) 141#define MODULES_VADDR _AC(0xffffffff88000000, UL)
141#define MODULES_END _AC(0xfffffffffff00000, UL) 142#define MODULES_END _AC(0xfffffffffff00000, UL)
142#define MODULES_LEN (MODULES_END - MODULES_VADDR) 143#define MODULES_LEN (MODULES_END - MODULES_VADDR)