diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-03-08 05:16:07 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:14:22 -0500 |
| commit | d1112018b4bc82adf5c8a9c15a08954328f023ae (patch) | |
| tree | 4d94ef6c153f028cfaaff711cf7d4f07aa90e9b4 | |
| parent | ee29074d3bd23848905f52c515974e0cd0219faa (diff) | |
[SPARC64]: Move over to sparsemem.
This has been pending for a long time, and the fact
that we waste a ton of ram on some configurations
kind of pushed things over the edge.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc64/Kconfig | 6 | ||||
| -rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 7 | ||||
| -rw-r--r-- | arch/sparc64/mm/init.c | 134 | ||||
| -rw-r--r-- | include/asm-sparc64/numnodes.h | 6 | ||||
| -rw-r--r-- | include/asm-sparc64/page.h | 9 | ||||
| -rw-r--r-- | include/asm-sparc64/pgtable.h | 3 | ||||
| -rw-r--r-- | include/asm-sparc64/sparsemem.h | 12 |
7 files changed, 123 insertions, 54 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 4c0a50a765..a253a39c3f 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
| @@ -186,6 +186,12 @@ endchoice | |||
| 186 | 186 | ||
| 187 | endmenu | 187 | endmenu |
| 188 | 188 | ||
| 189 | config ARCH_SPARSEMEM_ENABLE | ||
| 190 | def_bool y | ||
| 191 | |||
| 192 | config ARCH_SPARSEMEM_DEFAULT | ||
| 193 | def_bool y | ||
| 194 | |||
| 189 | source "mm/Kconfig" | 195 | source "mm/Kconfig" |
| 190 | 196 | ||
| 191 | config GENERIC_ISA_DMA | 197 | config GENERIC_ISA_DMA |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index e87fe7dfc7..9914a17651 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
| @@ -95,9 +95,6 @@ extern int __ashrdi3(int, int); | |||
| 95 | 95 | ||
| 96 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); | 96 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); |
| 97 | 97 | ||
| 98 | extern unsigned long phys_base; | ||
| 99 | extern unsigned long pfn_base; | ||
| 100 | |||
| 101 | extern unsigned int sys_call_table[]; | 98 | extern unsigned int sys_call_table[]; |
| 102 | 99 | ||
| 103 | extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); | 100 | extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); |
| @@ -346,11 +343,7 @@ EXPORT_SYMBOL(__strncpy_from_user); | |||
| 346 | EXPORT_SYMBOL(__clear_user); | 343 | EXPORT_SYMBOL(__clear_user); |
| 347 | 344 | ||
| 348 | /* Various address conversion macros use this. */ | 345 | /* Various address conversion macros use this. */ |
| 349 | EXPORT_SYMBOL(phys_base); | ||
| 350 | EXPORT_SYMBOL(pfn_base); | ||
| 351 | EXPORT_SYMBOL(sparc64_valid_addr_bitmap); | 346 | EXPORT_SYMBOL(sparc64_valid_addr_bitmap); |
| 352 | EXPORT_SYMBOL(page_to_pfn); | ||
| 353 | EXPORT_SYMBOL(pfn_to_page); | ||
| 354 | 347 | ||
| 355 | /* No version information on this, heavily used in inline asm, | 348 | /* No version information on this, heavily used in inline asm, |
| 356 | * and will always be 'void __ret_efault(void)'. | 349 | * and will always be 'void __ret_efault(void)'. |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index a63939347b..5f67b53b3a 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
| @@ -130,11 +130,9 @@ static void __init read_obp_memory(const char *property, | |||
| 130 | 130 | ||
| 131 | unsigned long *sparc64_valid_addr_bitmap __read_mostly; | 131 | unsigned long *sparc64_valid_addr_bitmap __read_mostly; |
| 132 | 132 | ||
| 133 | /* Ugly, but necessary... -DaveM */ | 133 | /* Kernel physical address base and size in bytes. */ |
| 134 | unsigned long phys_base __read_mostly; | ||
| 135 | unsigned long kern_base __read_mostly; | 134 | unsigned long kern_base __read_mostly; |
| 136 | unsigned long kern_size __read_mostly; | 135 | unsigned long kern_size __read_mostly; |
| 137 | unsigned long pfn_base __read_mostly; | ||
| 138 | 136 | ||
| 139 | /* get_new_mmu_context() uses "cache + 1". */ | 137 | /* get_new_mmu_context() uses "cache + 1". */ |
| 140 | DEFINE_SPINLOCK(ctx_alloc_lock); | 138 | DEFINE_SPINLOCK(ctx_alloc_lock); |
| @@ -368,16 +366,6 @@ void __kprobes flush_icache_range(unsigned long start, unsigned long end) | |||
| 368 | } | 366 | } |
| 369 | } | 367 | } |
| 370 | 368 | ||
| 371 | unsigned long page_to_pfn(struct page *page) | ||
| 372 | { | ||
| 373 | return (unsigned long) ((page - mem_map) + pfn_base); | ||
| 374 | } | ||
| 375 | |||
| 376 | struct page *pfn_to_page(unsigned long pfn) | ||
| 377 | { | ||
| 378 | return (mem_map + (pfn - pfn_base)); | ||
| 379 | } | ||
| 380 | |||
| 381 | void show_mem(void) | 369 | void show_mem(void) |
| 382 | { | 370 | { |
| 383 | printk("Mem-info:\n"); | 371 | printk("Mem-info:\n"); |
| @@ -773,9 +761,78 @@ void sparc_ultra_dump_dtlb(void) | |||
| 773 | 761 | ||
| 774 | extern unsigned long cmdline_memory_size; | 762 | extern unsigned long cmdline_memory_size; |
| 775 | 763 | ||
| 776 | unsigned long __init bootmem_init(unsigned long *pages_avail) | 764 | /* Find a free area for the bootmem map, avoiding the kernel image |
| 765 | * and the initial ramdisk. | ||
| 766 | */ | ||
| 767 | static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn, | ||
| 768 | unsigned long end_pfn) | ||
| 777 | { | 769 | { |
| 778 | unsigned long bootmap_size, start_pfn, end_pfn; | 770 | unsigned long avoid_start, avoid_end, bootmap_size; |
| 771 | int i; | ||
| 772 | |||
| 773 | bootmap_size = ((end_pfn - start_pfn) + 7) / 8; | ||
| 774 | bootmap_size = ALIGN(bootmap_size, sizeof(long)); | ||
| 775 | |||
| 776 | avoid_start = avoid_end = 0; | ||
| 777 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 778 | avoid_start = initrd_start; | ||
| 779 | avoid_end = PAGE_ALIGN(initrd_end); | ||
| 780 | #endif | ||
| 781 | |||
| 782 | #ifdef CONFIG_DEBUG_BOOTMEM | ||
| 783 | prom_printf("choose_bootmap_pfn: kern[%lx:%lx] avoid[%lx:%lx]\n", | ||
| 784 | kern_base, PAGE_ALIGN(kern_base + kern_size), | ||
| 785 | avoid_start, avoid_end); | ||
| 786 | #endif | ||
| 787 | for (i = 0; i < pavail_ents; i++) { | ||
| 788 | unsigned long start, end; | ||
| 789 | |||
| 790 | start = pavail[i].phys_addr; | ||
| 791 | end = start + pavail[i].reg_size; | ||
| 792 | |||
| 793 | while (start < end) { | ||
| 794 | if (start >= kern_base && | ||
| 795 | start < PAGE_ALIGN(kern_base + kern_size)) { | ||
| 796 | start = PAGE_ALIGN(kern_base + kern_size); | ||
| 797 | continue; | ||
| 798 | } | ||
| 799 | if (start >= avoid_start && start < avoid_end) { | ||
| 800 | start = avoid_end; | ||
| 801 | continue; | ||
| 802 | } | ||
| 803 | |||
| 804 | if ((end - start) < bootmap_size) | ||
| 805 | break; | ||
| 806 | |||
| 807 | if (start < kern_base && | ||
| 808 | (start + bootmap_size) > kern_base) { | ||
| 809 | start = PAGE_ALIGN(kern_base + kern_size); | ||
| 810 | continue; | ||
| 811 | } | ||
| 812 | |||
| 813 | if (start < avoid_start && | ||
| 814 | (start + bootmap_size) > avoid_start) { | ||
| 815 | start = avoid_end; | ||
| 816 | continue; | ||
| 817 | } | ||
| 818 | |||
| 819 | /* OK, it doesn't overlap anything, use it. */ | ||
| 820 | #ifdef CONFIG_DEBUG_BOOTMEM | ||
| 821 | prom_printf("choose_bootmap_pfn: Using %lx [%lx]\n", | ||
| 822 | start >> PAGE_SHIFT, start); | ||
| 823 | #endif | ||
| 824 | return start >> PAGE_SHIFT; | ||
| 825 | } | ||
| 826 | } | ||
| 827 | |||
| 828 | prom_printf("Cannot find free area for bootmap, aborting.\n"); | ||
| 829 | prom_halt(); | ||
| 830 | } | ||
| 831 | |||
| 832 | static unsigned long __init bootmem_init(unsigned long *pages_avail, | ||
| 833 | unsigned long phys_base) | ||
| 834 | { | ||
| 835 | unsigned long bootmap_size, end_pfn; | ||
| 779 | unsigned long end_of_phys_memory = 0UL; | 836 | unsigned long end_of_phys_memory = 0UL; |
| 780 | unsigned long bootmap_pfn, bytes_avail, size; | 837 | unsigned long bootmap_pfn, bytes_avail, size; |
| 781 | int i; | 838 | int i; |
| @@ -813,14 +870,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) | |||
| 813 | 870 | ||
| 814 | *pages_avail = bytes_avail >> PAGE_SHIFT; | 871 | *pages_avail = bytes_avail >> PAGE_SHIFT; |
| 815 | 872 | ||
| 816 | /* Start with page aligned address of last symbol in kernel | ||
| 817 | * image. The kernel is hard mapped below PAGE_OFFSET in a | ||
| 818 | * 4MB locked TLB translation. | ||
| 819 | */ | ||
| 820 | start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT; | ||
| 821 | |||
| 822 | bootmap_pfn = start_pfn; | ||
| 823 | |||
| 824 | end_pfn = end_of_phys_memory >> PAGE_SHIFT; | 873 | end_pfn = end_of_phys_memory >> PAGE_SHIFT; |
| 825 | 874 | ||
| 826 | #ifdef CONFIG_BLK_DEV_INITRD | 875 | #ifdef CONFIG_BLK_DEV_INITRD |
| @@ -837,23 +886,23 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) | |||
| 837 | "(0x%016lx > 0x%016lx)\ndisabling initrd\n", | 886 | "(0x%016lx > 0x%016lx)\ndisabling initrd\n", |
| 838 | initrd_end, end_of_phys_memory); | 887 | initrd_end, end_of_phys_memory); |
| 839 | initrd_start = 0; | 888 | initrd_start = 0; |
| 840 | } | 889 | initrd_end = 0; |
| 841 | if (initrd_start) { | ||
| 842 | if (initrd_start >= (start_pfn << PAGE_SHIFT) && | ||
| 843 | initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE) | ||
| 844 | bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT; | ||
| 845 | } | 890 | } |
| 846 | } | 891 | } |
| 847 | #endif | 892 | #endif |
| 848 | /* Initialize the boot-time allocator. */ | 893 | /* Initialize the boot-time allocator. */ |
| 849 | max_pfn = max_low_pfn = end_pfn; | 894 | max_pfn = max_low_pfn = end_pfn; |
| 850 | min_low_pfn = pfn_base; | 895 | min_low_pfn = (phys_base >> PAGE_SHIFT); |
| 896 | |||
| 897 | bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn); | ||
| 851 | 898 | ||
| 852 | #ifdef CONFIG_DEBUG_BOOTMEM | 899 | #ifdef CONFIG_DEBUG_BOOTMEM |
| 853 | prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", | 900 | prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", |
| 854 | min_low_pfn, bootmap_pfn, max_low_pfn); | 901 | min_low_pfn, bootmap_pfn, max_low_pfn); |
| 855 | #endif | 902 | #endif |
| 856 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); | 903 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, |
| 904 | (phys_base >> PAGE_SHIFT), | ||
| 905 | end_pfn); | ||
| 857 | 906 | ||
| 858 | /* Now register the available physical memory with the | 907 | /* Now register the available physical memory with the |
| 859 | * allocator. | 908 | * allocator. |
| @@ -901,6 +950,20 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) | |||
| 901 | reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); | 950 | reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); |
| 902 | *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; | 951 | *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; |
| 903 | 952 | ||
| 953 | for (i = 0; i < pavail_ents; i++) { | ||
| 954 | unsigned long start_pfn, end_pfn; | ||
| 955 | |||
| 956 | start_pfn = pavail[i].phys_addr >> PAGE_SHIFT; | ||
| 957 | end_pfn = (start_pfn + (pavail[i].reg_size >> PAGE_SHIFT)); | ||
| 958 | #ifdef CONFIG_DEBUG_BOOTMEM | ||
| 959 | prom_printf("memory_present(0, %lx, %lx)\n", | ||
| 960 | start_pfn, end_pfn); | ||
| 961 | #endif | ||
| 962 | memory_present(0, start_pfn, end_pfn); | ||
| 963 | } | ||
| 964 | |||
| 965 | sparse_init(); | ||
| 966 | |||
| 904 | return end_pfn; | 967 | return end_pfn; |
| 905 | } | 968 | } |
| 906 | 969 | ||
| @@ -1180,7 +1243,7 @@ static void sun4v_pgprot_init(void); | |||
| 1180 | 1243 | ||
| 1181 | void __init paging_init(void) | 1244 | void __init paging_init(void) |
| 1182 | { | 1245 | { |
| 1183 | unsigned long end_pfn, pages_avail, shift; | 1246 | unsigned long end_pfn, pages_avail, shift, phys_base; |
| 1184 | unsigned long real_end, i; | 1247 | unsigned long real_end, i; |
| 1185 | 1248 | ||
| 1186 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; | 1249 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; |
| @@ -1211,8 +1274,6 @@ void __init paging_init(void) | |||
| 1211 | for (i = 0; i < pavail_ents; i++) | 1274 | for (i = 0; i < pavail_ents; i++) |
| 1212 | phys_base = min(phys_base, pavail[i].phys_addr); | 1275 | phys_base = min(phys_base, pavail[i].phys_addr); |
| 1213 | 1276 | ||
| 1214 | pfn_base = phys_base >> PAGE_SHIFT; | ||
| 1215 | |||
| 1216 | set_bit(0, mmu_context_bmap); | 1277 | set_bit(0, mmu_context_bmap); |
| 1217 | 1278 | ||
| 1218 | shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); | 1279 | shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); |
| @@ -1248,7 +1309,9 @@ void __init paging_init(void) | |||
| 1248 | 1309 | ||
| 1249 | /* Setup bootmem... */ | 1310 | /* Setup bootmem... */ |
| 1250 | pages_avail = 0; | 1311 | pages_avail = 0; |
| 1251 | last_valid_pfn = end_pfn = bootmem_init(&pages_avail); | 1312 | last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base); |
| 1313 | |||
| 1314 | max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); | ||
| 1252 | 1315 | ||
| 1253 | kernel_physical_mapping_init(); | 1316 | kernel_physical_mapping_init(); |
| 1254 | 1317 | ||
| @@ -1261,7 +1324,7 @@ void __init paging_init(void) | |||
| 1261 | for (znum = 0; znum < MAX_NR_ZONES; znum++) | 1324 | for (znum = 0; znum < MAX_NR_ZONES; znum++) |
| 1262 | zones_size[znum] = zholes_size[znum] = 0; | 1325 | zones_size[znum] = zholes_size[znum] = 0; |
| 1263 | 1326 | ||
| 1264 | npages = end_pfn - pfn_base; | 1327 | npages = end_pfn - (phys_base >> PAGE_SHIFT); |
| 1265 | zones_size[ZONE_DMA] = npages; | 1328 | zones_size[ZONE_DMA] = npages; |
| 1266 | zholes_size[ZONE_DMA] = npages - pages_avail; | 1329 | zholes_size[ZONE_DMA] = npages - pages_avail; |
| 1267 | 1330 | ||
| @@ -1336,7 +1399,6 @@ void __init mem_init(void) | |||
| 1336 | 1399 | ||
| 1337 | taint_real_pages(); | 1400 | taint_real_pages(); |
| 1338 | 1401 | ||
| 1339 | max_mapnr = last_valid_pfn - pfn_base; | ||
| 1340 | high_memory = __va(last_valid_pfn << PAGE_SHIFT); | 1402 | high_memory = __va(last_valid_pfn << PAGE_SHIFT); |
| 1341 | 1403 | ||
| 1342 | #ifdef CONFIG_DEBUG_BOOTMEM | 1404 | #ifdef CONFIG_DEBUG_BOOTMEM |
diff --git a/include/asm-sparc64/numnodes.h b/include/asm-sparc64/numnodes.h new file mode 100644 index 0000000000..017e7e74f5 --- /dev/null +++ b/include/asm-sparc64/numnodes.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef _SPARC64_NUMNODES_H | ||
| 2 | #define _SPARC64_NUMNODES_H | ||
| 3 | |||
| 4 | #define NODES_SHIFT 0 | ||
| 5 | |||
| 6 | #endif /* !(_SPARC64_NUMNODES_H) */ | ||
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index c277ac56b9..f6b49256fe 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h | |||
| @@ -125,17 +125,10 @@ typedef unsigned long pgprot_t; | |||
| 125 | #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) | 125 | #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) |
| 126 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) | 126 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) |
| 127 | 127 | ||
| 128 | /* PFNs are real physical page numbers. However, mem_map only begins to record | 128 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
| 129 | * per-page information starting at pfn_base. This is to handle systems where | ||
| 130 | * the first physical page in the machine is at some huge physical address, | ||
| 131 | * such as 4GB. This is common on a partitioned E10000, for example. | ||
| 132 | */ | ||
| 133 | extern struct page *pfn_to_page(unsigned long pfn); | ||
| 134 | extern unsigned long page_to_pfn(struct page *); | ||
| 135 | 129 | ||
| 136 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr)>>PAGE_SHIFT) | 130 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr)>>PAGE_SHIFT) |
| 137 | 131 | ||
| 138 | #define pfn_valid(pfn) (((pfn)-(pfn_base)) < max_mapnr) | ||
| 139 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | 132 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) |
| 140 | 133 | ||
| 141 | #define virt_to_phys __pa | 134 | #define virt_to_phys __pa |
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 75a2cd2d7e..d427ce6492 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h | |||
| @@ -217,9 +217,6 @@ extern unsigned long pg_iobits; | |||
| 217 | extern unsigned long _PAGE_ALL_SZ_BITS; | 217 | extern unsigned long _PAGE_ALL_SZ_BITS; |
| 218 | extern unsigned long _PAGE_SZBITS; | 218 | extern unsigned long _PAGE_SZBITS; |
| 219 | 219 | ||
| 220 | extern unsigned long phys_base; | ||
| 221 | extern unsigned long pfn_base; | ||
| 222 | |||
| 223 | extern struct page *mem_map_zero; | 220 | extern struct page *mem_map_zero; |
| 224 | #define ZERO_PAGE(vaddr) (mem_map_zero) | 221 | #define ZERO_PAGE(vaddr) (mem_map_zero) |
| 225 | 222 | ||
diff --git a/include/asm-sparc64/sparsemem.h b/include/asm-sparc64/sparsemem.h new file mode 100644 index 0000000000..ed5c9d8541 --- /dev/null +++ b/include/asm-sparc64/sparsemem.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #ifndef _SPARC64_SPARSEMEM_H | ||
| 2 | #define _SPARC64_SPARSEMEM_H | ||
| 3 | |||
| 4 | #ifdef __KERNEL__ | ||
| 5 | |||
| 6 | #define SECTION_SIZE_BITS 26 | ||
| 7 | #define MAX_PHYSADDR_BITS 42 | ||
| 8 | #define MAX_PHYSMEM_BITS 42 | ||
| 9 | |||
| 10 | #endif /* !(__KERNEL__) */ | ||
| 11 | |||
| 12 | #endif /* !(_SPARC64_SPARSEMEM_H) */ | ||
