aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-19 14:37:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-19 14:37:22 -0400
commit1d3c6ff44ad4b5f113602e153026a338f0f9b3ff (patch)
tree1e1f2932634fc6d0e4acfe68496c1c727b83a13e /arch/arm/mm
parent7c7cbaf5b82c418cd3b1dcf718f71d0e6057e639 (diff)
parent717e7c2672e37253a4d3aa70e4716b5b0a658761 (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (224 commits) ARM: remove 'select GENERIC_TIME' ARM: 6136/1: ARCH_REQUIRE_GPIOLIB selects GENERIC_GPIO ARM: 6074/1: oprofile: convert from sysdev to platform device ARM: 6073/1: oprofile: remove old files and update KConfig ARM: 6072/1: oprofile: use perf-events framework as backend ARM: 6071/1: perf-events: allow modules to query the number of hardware counters ARM: 6070/1: perf-events: add support for xscale PMUs ARM: 6069/1: perf-events: use numeric ID to identify PMU ARM: 6064/1: pmu: register IRQs at runtime ARM: Optionally allow ARMv6 to use 'normal, bufferable' memory for DMA ARM: 6134/1: Handle instruction cache maintenance fault properly ARM: nwfpe: allow debugging output to be configured at runtime ARM: rename mach_cpu_disable() to platform_cpu_disable() ARM: 6132/1: PL330: Add common core driver ARM: 6094/1: Extend cache-l2x0 to support the 16-way PL310 ARM: Move memory mapping into mmu.c ARM: Ensure meminfo is sorted prior to sanity_check_meminfo ARM: Remove useless linux/bootmem.h includes ARM: convert /proc/cpu/aligment to seq_file arm: use asm-generic/scatterlist.h ...
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/Kconfig26
-rw-r--r--arch/arm/mm/abort-ev7.S21
-rw-r--r--arch/arm/mm/alignment.c53
-rw-r--r--arch/arm/mm/cache-l2x0.c39
-rw-r--r--arch/arm/mm/copypage-fa.c2
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/fault.c5
-rw-r--r--arch/arm/mm/init.c34
-rw-r--r--arch/arm/mm/mm.h3
-rw-r--r--arch/arm/mm/mmu.c39
10 files changed, 149 insertions, 75 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5bd7c89a6045..346ae14824a5 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -572,6 +572,8 @@ config CPU_TLB_V6
572config CPU_TLB_V7 572config CPU_TLB_V7
573 bool 573 bool
574 574
575config VERIFY_PERMISSION_FAULT
576 bool
575endif 577endif
576 578
577config CPU_HAS_ASID 579config CPU_HAS_ASID
@@ -760,7 +762,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
760config CACHE_L2X0 762config CACHE_L2X0
761 bool "Enable the L2x0 outer cache controller" 763 bool "Enable the L2x0 outer cache controller"
762 depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ 764 depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
763 REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4 765 REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
766 ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
764 default y 767 default y
765 select OUTER_CACHE 768 select OUTER_CACHE
766 select OUTER_CACHE_SYNC 769 select OUTER_CACHE_SYNC
@@ -769,7 +772,7 @@ config CACHE_L2X0
769 772
770config CACHE_TAUROS2 773config CACHE_TAUROS2
771 bool "Enable the Tauros2 L2 cache controller" 774 bool "Enable the Tauros2 L2 cache controller"
772 depends on ARCH_DOVE 775 depends on (ARCH_DOVE || ARCH_MMP)
773 default y 776 default y
774 select OUTER_CACHE 777 select OUTER_CACHE
775 help 778 help
@@ -789,6 +792,25 @@ config ARM_L1_CACHE_SHIFT
789 default 6 if ARM_L1_CACHE_SHIFT_6 792 default 6 if ARM_L1_CACHE_SHIFT_6
790 default 5 793 default 5
791 794
795config ARM_DMA_MEM_BUFFERABLE
796 bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7
797 default y if CPU_V6 || CPU_V7
798 help
799 Historically, the kernel has used strongly ordered mappings to
800 provide DMA coherent memory. With the advent of ARMv7, mapping
801 memory with differing types results in unpredictable behaviour,
802 so on these CPUs, this option is forced on.
803
804 Multiple mappings with differing attributes is also unpredictable
805 on ARMv6 CPUs, but since they do not have aggressive speculative
806 prefetch, no harm appears to occur.
807
808 However, drivers may be missing the necessary barriers for ARMv6,
809 and therefore turning this on may result in unpredictable driver
810 behaviour. Therefore, we offer this as an option.
811
812 You are recommended say 'Y' here and debug any affected drivers.
813
792config ARCH_HAS_BARRIERS 814config ARCH_HAS_BARRIERS
793 bool 815 bool
794 help 816 help
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index 2e6dc040c654..ec88b157d3bb 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -29,5 +29,26 @@ ENTRY(v7_early_abort)
29 * V6 code adjusts the returned DFSR. 29 * V6 code adjusts the returned DFSR.
30 * New designs should not need to patch up faults. 30 * New designs should not need to patch up faults.
31 */ 31 */
32
33#if defined(CONFIG_VERIFY_PERMISSION_FAULT)
34 /*
35 * Detect erroneous permission failures and fix
36 */
37 ldr r3, =0x40d @ On permission fault
38 and r3, r1, r3
39 cmp r3, #0x0d
40 movne pc, lr
41
42 mcr p15, 0, r0, c7, c8, 0 @ Retranslate FAR
43 isb
44 mrc p15, 0, r2, c7, c4, 0 @ Read the PAR
45 and r3, r2, #0x7b @ On translation fault
46 cmp r3, #0x0b
47 movne pc, lr
48 bic r1, r1, #0xf @ Fix up FSR FS[5:0]
49 and r2, r2, #0x7e
50 orr r1, r1, r2, LSR #1
51#endif
52
32 mov pc, lr 53 mov pc, lr
33ENDPROC(v7_early_abort) 54ENDPROC(v7_early_abort)
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index a2ab51fa73e2..6f98c358989a 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -17,6 +17,7 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/seq_file.h>
20#include <linux/init.h> 21#include <linux/init.h>
21#include <linux/sched.h> 22#include <linux/sched.h>
22#include <linux/uaccess.h> 23#include <linux/uaccess.h>
@@ -94,36 +95,29 @@ static const char *usermode_action[] = {
94 "signal+warn" 95 "signal+warn"
95}; 96};
96 97
97static int 98static int alignment_proc_show(struct seq_file *m, void *v)
98proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
99 void *data)
100{ 99{
101 char *p = page; 100 seq_printf(m, "User:\t\t%lu\n", ai_user);
102 int len; 101 seq_printf(m, "System:\t\t%lu\n", ai_sys);
103 102 seq_printf(m, "Skipped:\t%lu\n", ai_skipped);
104 p += sprintf(p, "User:\t\t%lu\n", ai_user); 103 seq_printf(m, "Half:\t\t%lu\n", ai_half);
105 p += sprintf(p, "System:\t\t%lu\n", ai_sys); 104 seq_printf(m, "Word:\t\t%lu\n", ai_word);
106 p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
107 p += sprintf(p, "Half:\t\t%lu\n", ai_half);
108 p += sprintf(p, "Word:\t\t%lu\n", ai_word);
109 if (cpu_architecture() >= CPU_ARCH_ARMv5TE) 105 if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
110 p += sprintf(p, "DWord:\t\t%lu\n", ai_dword); 106 seq_printf(m, "DWord:\t\t%lu\n", ai_dword);
111 p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); 107 seq_printf(m, "Multi:\t\t%lu\n", ai_multi);
112 p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, 108 seq_printf(m, "User faults:\t%i (%s)\n", ai_usermode,
113 usermode_action[ai_usermode]); 109 usermode_action[ai_usermode]);
114 110
115 len = (p - page) - off; 111 return 0;
116 if (len < 0) 112}
117 len = 0;
118
119 *eof = (len <= count) ? 1 : 0;
120 *start = page + off;
121 113
122 return len; 114static int alignment_proc_open(struct inode *inode, struct file *file)
115{
116 return single_open(file, alignment_proc_show, NULL);
123} 117}
124 118
125static int proc_alignment_write(struct file *file, const char __user *buffer, 119static ssize_t alignment_proc_write(struct file *file, const char __user *buffer,
126 unsigned long count, void *data) 120 size_t count, loff_t *pos)
127{ 121{
128 char mode; 122 char mode;
129 123
@@ -136,6 +130,13 @@ static int proc_alignment_write(struct file *file, const char __user *buffer,
136 return count; 130 return count;
137} 131}
138 132
133static const struct file_operations alignment_proc_fops = {
134 .open = alignment_proc_open,
135 .read = seq_read,
136 .llseek = seq_lseek,
137 .release = single_release,
138 .write = alignment_proc_write,
139};
139#endif /* CONFIG_PROC_FS */ 140#endif /* CONFIG_PROC_FS */
140 141
141union offset_union { 142union offset_union {
@@ -901,12 +902,10 @@ static int __init alignment_init(void)
901#ifdef CONFIG_PROC_FS 902#ifdef CONFIG_PROC_FS
902 struct proc_dir_entry *res; 903 struct proc_dir_entry *res;
903 904
904 res = create_proc_entry("cpu/alignment", S_IWUSR | S_IRUGO, NULL); 905 res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL,
906 &alignment_proc_fops);
905 if (!res) 907 if (!res)
906 return -ENOMEM; 908 return -ENOMEM;
907
908 res->read_proc = proc_alignment_read;
909 res->write_proc = proc_alignment_write;
910#endif 909#endif
911 910
912 /* 911 /*
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 21ad68ba22ba..9819869d2bc9 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -27,6 +27,7 @@
27 27
28static void __iomem *l2x0_base; 28static void __iomem *l2x0_base;
29static DEFINE_SPINLOCK(l2x0_lock); 29static DEFINE_SPINLOCK(l2x0_lock);
30static uint32_t l2x0_way_mask; /* Bitmask of active ways */
30 31
31static inline void cache_wait(void __iomem *reg, unsigned long mask) 32static inline void cache_wait(void __iomem *reg, unsigned long mask)
32{ 33{
@@ -108,8 +109,8 @@ static inline void l2x0_inv_all(void)
108 109
109 /* invalidate all ways */ 110 /* invalidate all ways */
110 spin_lock_irqsave(&l2x0_lock, flags); 111 spin_lock_irqsave(&l2x0_lock, flags);
111 writel(0xff, l2x0_base + L2X0_INV_WAY); 112 writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
112 cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); 113 cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
113 cache_sync(); 114 cache_sync();
114 spin_unlock_irqrestore(&l2x0_lock, flags); 115 spin_unlock_irqrestore(&l2x0_lock, flags);
115} 116}
@@ -208,9 +209,37 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
208void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) 209void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
209{ 210{
210 __u32 aux; 211 __u32 aux;
212 __u32 cache_id;
213 int ways;
214 const char *type;
211 215
212 l2x0_base = base; 216 l2x0_base = base;
213 217
218 cache_id = readl(l2x0_base + L2X0_CACHE_ID);
219 aux = readl(l2x0_base + L2X0_AUX_CTRL);
220
221 /* Determine the number of ways */
222 switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
223 case L2X0_CACHE_ID_PART_L310:
224 if (aux & (1 << 16))
225 ways = 16;
226 else
227 ways = 8;
228 type = "L310";
229 break;
230 case L2X0_CACHE_ID_PART_L210:
231 ways = (aux >> 13) & 0xf;
232 type = "L210";
233 break;
234 default:
235 /* Assume unknown chips have 8 ways */
236 ways = 8;
237 type = "L2x0 series";
238 break;
239 }
240
241 l2x0_way_mask = (1 << ways) - 1;
242
214 /* 243 /*
215 * Check if l2x0 controller is already enabled. 244 * Check if l2x0 controller is already enabled.
216 * If you are booting from non-secure mode 245 * If you are booting from non-secure mode
@@ -219,8 +248,6 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
219 if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { 248 if (!(readl(l2x0_base + L2X0_CTRL) & 1)) {
220 249
221 /* l2x0 controller is disabled */ 250 /* l2x0 controller is disabled */
222
223 aux = readl(l2x0_base + L2X0_AUX_CTRL);
224 aux &= aux_mask; 251 aux &= aux_mask;
225 aux |= aux_val; 252 aux |= aux_val;
226 writel(aux, l2x0_base + L2X0_AUX_CTRL); 253 writel(aux, l2x0_base + L2X0_AUX_CTRL);
@@ -236,5 +263,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
236 outer_cache.flush_range = l2x0_flush_range; 263 outer_cache.flush_range = l2x0_flush_range;
237 outer_cache.sync = l2x0_cache_sync; 264 outer_cache.sync = l2x0_cache_sync;
238 265
239 printk(KERN_INFO "L2X0 cache controller enabled\n"); 266 printk(KERN_INFO "%s cache controller enabled\n", type);
267 printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
268 ways, cache_id, aux);
240} 269}
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c
index b2a6008b0111..d2852e1635b1 100644
--- a/arch/arm/mm/copypage-fa.c
+++ b/arch/arm/mm/copypage-fa.c
@@ -40,7 +40,7 @@ fa_copy_user_page(void *kto, const void *kfrom)
40} 40}
41 41
42void fa_copy_user_highpage(struct page *to, struct page *from, 42void fa_copy_user_highpage(struct page *to, struct page *from,
43 unsigned long vaddr) 43 unsigned long vaddr, struct vm_area_struct *vma)
44{ 44{
45 void *kto, *kfrom; 45 void *kto, *kfrom;
46 46
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 0d414c28eb2c..9b906dec1ca1 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -134,8 +134,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
134 flush_dcache_mmap_unlock(mapping); 134 flush_dcache_mmap_unlock(mapping);
135 if (aliases) 135 if (aliases)
136 do_adjust_pte(vma, addr, pfn, ptep); 136 do_adjust_pte(vma, addr, pfn, ptep);
137 else
138 flush_cache_page(vma, addr, pfn);
139} 137}
140 138
141/* 139/*
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 9d40c341e07e..92f5801f99c1 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -463,7 +463,12 @@ static struct fsr_info {
463 { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, 463 { do_bad, SIGILL, BUS_ADRALN, "alignment exception" },
464 { do_bad, SIGKILL, 0, "terminal exception" }, 464 { do_bad, SIGKILL, 0, "terminal exception" },
465 { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, 465 { do_bad, SIGILL, BUS_ADRALN, "alignment exception" },
466/* Do we need runtime check ? */
467#if __LINUX_ARM_ARCH__ < 6
466 { do_bad, SIGBUS, 0, "external abort on linefetch" }, 468 { do_bad, SIGBUS, 0, "external abort on linefetch" },
469#else
470 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "I-cache maintenance fault" },
471#endif
467 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, 472 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
468 { do_bad, SIGBUS, 0, "external abort on linefetch" }, 473 { do_bad, SIGBUS, 0, "external abort on linefetch" },
469 { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, 474 { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 0ed29bfeba1c..1ba6cf5a2c02 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -15,7 +15,6 @@
15#include <linux/mman.h> 15#include <linux/mman.h>
16#include <linux/nodemask.h> 16#include <linux/nodemask.h>
17#include <linux/initrd.h> 17#include <linux/initrd.h>
18#include <linux/sort.h>
19#include <linux/highmem.h> 18#include <linux/highmem.h>
20#include <linux/gfp.h> 19#include <linux/gfp.h>
21 20
@@ -224,20 +223,6 @@ static int __init check_initrd(struct meminfo *mi)
224 return initrd_node; 223 return initrd_node;
225} 224}
226 225
227static inline void map_memory_bank(struct membank *bank)
228{
229#ifdef CONFIG_MMU
230 struct map_desc map;
231
232 map.pfn = bank_pfn_start(bank);
233 map.virtual = __phys_to_virt(bank_phys_start(bank));
234 map.length = bank_phys_size(bank);
235 map.type = MT_MEMORY;
236
237 create_mapping(&map);
238#endif
239}
240
241static void __init bootmem_init_node(int node, struct meminfo *mi, 226static void __init bootmem_init_node(int node, struct meminfo *mi,
242 unsigned long start_pfn, unsigned long end_pfn) 227 unsigned long start_pfn, unsigned long end_pfn)
243{ 228{
@@ -247,16 +232,6 @@ static void __init bootmem_init_node(int node, struct meminfo *mi,
247 int i; 232 int i;
248 233
249 /* 234 /*
250 * Map the memory banks for this node.
251 */
252 for_each_nodebank(i, mi, node) {
253 struct membank *bank = &mi->bank[i];
254
255 if (!bank->highmem)
256 map_memory_bank(bank);
257 }
258
259 /*
260 * Allocate the bootmem bitmap page. 235 * Allocate the bootmem bitmap page.
261 */ 236 */
262 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 237 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
@@ -385,21 +360,12 @@ static void arm_memory_present(struct meminfo *mi, int node)
385} 360}
386#endif 361#endif
387 362
388static int __init meminfo_cmp(const void *_a, const void *_b)
389{
390 const struct membank *a = _a, *b = _b;
391 long cmp = bank_pfn_start(a) - bank_pfn_start(b);
392 return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
393}
394
395void __init bootmem_init(void) 363void __init bootmem_init(void)
396{ 364{
397 struct meminfo *mi = &meminfo; 365 struct meminfo *mi = &meminfo;
398 unsigned long min, max_low, max_high; 366 unsigned long min, max_low, max_high;
399 int node, initrd_node; 367 int node, initrd_node;
400 368
401 sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL);
402
403 /* 369 /*
404 * Locate which node contains the ramdisk image, if any. 370 * Locate which node contains the ramdisk image, if any.
405 */ 371 */
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index a888363398f8..815d08eecbb0 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -28,10 +28,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
28 28
29#endif 29#endif
30 30
31struct map_desc;
32struct meminfo;
33struct pglist_data; 31struct pglist_data;
34 32
35void __init create_mapping(struct map_desc *md);
36void __init bootmem_init(void); 33void __init bootmem_init(void);
37void reserve_node_zero(struct pglist_data *pgdat); 34void reserve_node_zero(struct pglist_data *pgdat);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 241c24a1c18f..e7113d0b8168 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -14,6 +14,7 @@
14#include <linux/bootmem.h> 14#include <linux/bootmem.h>
15#include <linux/mman.h> 15#include <linux/mman.h>
16#include <linux/nodemask.h> 16#include <linux/nodemask.h>
17#include <linux/sort.h>
17 18
18#include <asm/cputype.h> 19#include <asm/cputype.h>
19#include <asm/mach-types.h> 20#include <asm/mach-types.h>
@@ -603,7 +604,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
603 * offsets, and we take full advantage of sections and 604 * offsets, and we take full advantage of sections and
604 * supersections. 605 * supersections.
605 */ 606 */
606void __init create_mapping(struct map_desc *md) 607static void __init create_mapping(struct map_desc *md)
607{ 608{
608 unsigned long phys, addr, length, end; 609 unsigned long phys, addr, length, end;
609 const struct mem_type *type; 610 const struct mem_type *type;
@@ -1017,6 +1018,39 @@ static void __init kmap_init(void)
1017#endif 1018#endif
1018} 1019}
1019 1020
1021static inline void map_memory_bank(struct membank *bank)
1022{
1023 struct map_desc map;
1024
1025 map.pfn = bank_pfn_start(bank);
1026 map.virtual = __phys_to_virt(bank_phys_start(bank));
1027 map.length = bank_phys_size(bank);
1028 map.type = MT_MEMORY;
1029
1030 create_mapping(&map);
1031}
1032
1033static void __init map_lowmem(void)
1034{
1035 struct meminfo *mi = &meminfo;
1036 int i;
1037
1038 /* Map all the lowmem memory banks. */
1039 for (i = 0; i < mi->nr_banks; i++) {
1040 struct membank *bank = &mi->bank[i];
1041
1042 if (!bank->highmem)
1043 map_memory_bank(bank);
1044 }
1045}
1046
1047static int __init meminfo_cmp(const void *_a, const void *_b)
1048{
1049 const struct membank *a = _a, *b = _b;
1050 long cmp = bank_pfn_start(a) - bank_pfn_start(b);
1051 return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
1052}
1053
1020/* 1054/*
1021 * paging_init() sets up the page tables, initialises the zone memory 1055 * paging_init() sets up the page tables, initialises the zone memory
1022 * maps, and sets up the zero page, bad page and bad page tables. 1056 * maps, and sets up the zero page, bad page and bad page tables.
@@ -1025,9 +1059,12 @@ void __init paging_init(struct machine_desc *mdesc)
1025{ 1059{
1026 void *zero_page; 1060 void *zero_page;
1027 1061
1062 sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
1063
1028 build_mem_type_table(); 1064 build_mem_type_table();
1029 sanity_check_meminfo(); 1065 sanity_check_meminfo();
1030 prepare_page_table(); 1066 prepare_page_table();
1067 map_lowmem();
1031 bootmem_init(); 1068 bootmem_init();
1032 devicemaps_init(mdesc); 1069 devicemaps_init(mdesc);
1033 kmap_init(); 1070 kmap_init();