aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/alignment.c139
-rw-r--r--arch/arm/mm/fault.c2
-rw-r--r--arch/arm/mm/init.c118
-rw-r--r--arch/arm/mm/mmu.c16
-rw-r--r--arch/arm/mm/proc-syms.c1
5 files changed, 209 insertions, 67 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 3a398befed41..03cd27d917b9 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -62,6 +62,12 @@
62#define SHIFT_ASR 0x40 62#define SHIFT_ASR 0x40
63#define SHIFT_RORRRX 0x60 63#define SHIFT_RORRRX 0x60
64 64
65#define BAD_INSTR 0xdeadc0de
66
67/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */
68#define IS_T32(hi16) \
69 (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800))
70
65static unsigned long ai_user; 71static unsigned long ai_user;
66static unsigned long ai_sys; 72static unsigned long ai_sys;
67static unsigned long ai_skipped; 73static unsigned long ai_skipped;
@@ -332,38 +338,48 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
332 struct pt_regs *regs) 338 struct pt_regs *regs)
333{ 339{
334 unsigned int rd = RD_BITS(instr); 340 unsigned int rd = RD_BITS(instr);
335 341 unsigned int rd2;
336 if (((rd & 1) == 1) || (rd == 14)) 342 int load;
343
344 if ((instr & 0xfe000000) == 0xe8000000) {
345 /* ARMv7 Thumb-2 32-bit LDRD/STRD */
346 rd2 = (instr >> 8) & 0xf;
347 load = !!(LDST_L_BIT(instr));
348 } else if (((rd & 1) == 1) || (rd == 14))
337 goto bad; 349 goto bad;
350 else {
351 load = ((instr & 0xf0) == 0xd0);
352 rd2 = rd + 1;
353 }
338 354
339 ai_dword += 1; 355 ai_dword += 1;
340 356
341 if (user_mode(regs)) 357 if (user_mode(regs))
342 goto user; 358 goto user;
343 359
344 if ((instr & 0xf0) == 0xd0) { 360 if (load) {
345 unsigned long val; 361 unsigned long val;
346 get32_unaligned_check(val, addr); 362 get32_unaligned_check(val, addr);
347 regs->uregs[rd] = val; 363 regs->uregs[rd] = val;
348 get32_unaligned_check(val, addr + 4); 364 get32_unaligned_check(val, addr + 4);
349 regs->uregs[rd + 1] = val; 365 regs->uregs[rd2] = val;
350 } else { 366 } else {
351 put32_unaligned_check(regs->uregs[rd], addr); 367 put32_unaligned_check(regs->uregs[rd], addr);
352 put32_unaligned_check(regs->uregs[rd + 1], addr + 4); 368 put32_unaligned_check(regs->uregs[rd2], addr + 4);
353 } 369 }
354 370
355 return TYPE_LDST; 371 return TYPE_LDST;
356 372
357 user: 373 user:
358 if ((instr & 0xf0) == 0xd0) { 374 if (load) {
359 unsigned long val; 375 unsigned long val;
360 get32t_unaligned_check(val, addr); 376 get32t_unaligned_check(val, addr);
361 regs->uregs[rd] = val; 377 regs->uregs[rd] = val;
362 get32t_unaligned_check(val, addr + 4); 378 get32t_unaligned_check(val, addr + 4);
363 regs->uregs[rd + 1] = val; 379 regs->uregs[rd2] = val;
364 } else { 380 } else {
365 put32t_unaligned_check(regs->uregs[rd], addr); 381 put32t_unaligned_check(regs->uregs[rd], addr);
366 put32t_unaligned_check(regs->uregs[rd + 1], addr + 4); 382 put32t_unaligned_check(regs->uregs[rd2], addr + 4);
367 } 383 }
368 384
369 return TYPE_LDST; 385 return TYPE_LDST;
@@ -616,8 +632,72 @@ thumb2arm(u16 tinstr)
616 /* Else fall through for illegal instruction case */ 632 /* Else fall through for illegal instruction case */
617 633
618 default: 634 default:
619 return 0xdeadc0de; 635 return BAD_INSTR;
636 }
637}
638
639/*
640 * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction
641 * handlable by ARM alignment handler, also find the corresponding handler,
642 * so that we can reuse ARM userland alignment fault fixups for Thumb.
643 *
644 * @pinstr: original Thumb-2 instruction; returns new handlable instruction
645 * @regs: register context.
646 * @poffset: return offset from faulted addr for later writeback
647 *
648 * NOTES:
649 * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections.
650 * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
651 */
652static void *
653do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
654 union offset_union *poffset)
655{
656 unsigned long instr = *pinstr;
657 u16 tinst1 = (instr >> 16) & 0xffff;
658 u16 tinst2 = instr & 0xffff;
659 poffset->un = 0;
660
661 switch (tinst1 & 0xffe0) {
662 /* A6.3.5 Load/Store multiple */
663 case 0xe880: /* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */
664 case 0xe8a0: /* ...above writeback version */
665 case 0xe900: /* STMDB/STMFD, LDMDB/LDMEA */
666 case 0xe920: /* ...above writeback version */
667 /* no need offset decision since handler calculates it */
668 return do_alignment_ldmstm;
669
670 case 0xf840: /* POP/PUSH T3 (single register) */
671 if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) {
672 u32 L = !!(LDST_L_BIT(instr));
673 const u32 subset[2] = {
674 0xe92d0000, /* STMDB sp!,{registers} */
675 0xe8bd0000, /* LDMIA sp!,{registers} */
676 };
677 *pinstr = subset[L] | (1<<RD_BITS(instr));
678 return do_alignment_ldmstm;
679 }
680 /* Else fall through for illegal instruction case */
681 break;
682
683 /* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */
684 case 0xe860:
685 case 0xe960:
686 case 0xe8e0:
687 case 0xe9e0:
688 poffset->un = (tinst2 & 0xff) << 2;
689 case 0xe940:
690 case 0xe9c0:
691 return do_alignment_ldrdstrd;
692
693 /*
694 * No need to handle load/store instructions up to word size
695 * since ARMv6 and later CPUs can perform unaligned accesses.
696 */
697 default:
698 break;
620 } 699 }
700 return NULL;
621} 701}
622 702
623static int 703static int
@@ -630,6 +710,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
630 mm_segment_t fs; 710 mm_segment_t fs;
631 unsigned int fault; 711 unsigned int fault;
632 u16 tinstr = 0; 712 u16 tinstr = 0;
713 int isize = 4;
714 int thumb2_32b = 0;
633 715
634 instrptr = instruction_pointer(regs); 716 instrptr = instruction_pointer(regs);
635 717
@@ -637,8 +719,19 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
637 set_fs(KERNEL_DS); 719 set_fs(KERNEL_DS);
638 if (thumb_mode(regs)) { 720 if (thumb_mode(regs)) {
639 fault = __get_user(tinstr, (u16 *)(instrptr & ~1)); 721 fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
640 if (!(fault)) 722 if (!fault) {
641 instr = thumb2arm(tinstr); 723 if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
724 IS_T32(tinstr)) {
725 /* Thumb-2 32-bit */
726 u16 tinst2 = 0;
727 fault = __get_user(tinst2, (u16 *)(instrptr+2));
728 instr = (tinstr << 16) | tinst2;
729 thumb2_32b = 1;
730 } else {
731 isize = 2;
732 instr = thumb2arm(tinstr);
733 }
734 }
642 } else 735 } else
643 fault = __get_user(instr, (u32 *)instrptr); 736 fault = __get_user(instr, (u32 *)instrptr);
644 set_fs(fs); 737 set_fs(fs);
@@ -655,7 +748,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
655 748
656 fixup: 749 fixup:
657 750
658 regs->ARM_pc += thumb_mode(regs) ? 2 : 4; 751 regs->ARM_pc += isize;
659 752
660 switch (CODING_BITS(instr)) { 753 switch (CODING_BITS(instr)) {
661 case 0x00000000: /* 3.13.4 load/store instruction extensions */ 754 case 0x00000000: /* 3.13.4 load/store instruction extensions */
@@ -714,18 +807,25 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
714 handler = do_alignment_ldrstr; 807 handler = do_alignment_ldrstr;
715 break; 808 break;
716 809
717 case 0x08000000: /* ldm or stm */ 810 case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */
718 handler = do_alignment_ldmstm; 811 if (thumb2_32b)
812 handler = do_alignment_t32_to_handler(&instr, regs, &offset);
813 else
814 handler = do_alignment_ldmstm;
719 break; 815 break;
720 816
721 default: 817 default:
722 goto bad; 818 goto bad;
723 } 819 }
724 820
821 if (!handler)
822 goto bad;
725 type = handler(addr, instr, regs); 823 type = handler(addr, instr, regs);
726 824
727 if (type == TYPE_ERROR || type == TYPE_FAULT) 825 if (type == TYPE_ERROR || type == TYPE_FAULT) {
826 regs->ARM_pc -= isize;
728 goto bad_or_fault; 827 goto bad_or_fault;
828 }
729 829
730 if (type == TYPE_LDST) 830 if (type == TYPE_LDST)
731 do_alignment_finish_ldst(addr, instr, regs, offset); 831 do_alignment_finish_ldst(addr, instr, regs, offset);
@@ -735,7 +835,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
735 bad_or_fault: 835 bad_or_fault:
736 if (type == TYPE_ERROR) 836 if (type == TYPE_ERROR)
737 goto bad; 837 goto bad;
738 regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
739 /* 838 /*
740 * We got a fault - fix it up, or die. 839 * We got a fault - fix it up, or die.
741 */ 840 */
@@ -751,8 +850,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
751 */ 850 */
752 printk(KERN_ERR "Alignment trap: not handling instruction " 851 printk(KERN_ERR "Alignment trap: not handling instruction "
753 "%0*lx at [<%08lx>]\n", 852 "%0*lx at [<%08lx>]\n",
754 thumb_mode(regs) ? 4 : 8, 853 isize << 1,
755 thumb_mode(regs) ? tinstr : instr, instrptr); 854 isize == 2 ? tinstr : instr, instrptr);
756 ai_skipped += 1; 855 ai_skipped += 1;
757 return 1; 856 return 1;
758 857
@@ -763,8 +862,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
763 printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " 862 printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
764 "Address=0x%08lx FSR 0x%03x\n", current->comm, 863 "Address=0x%08lx FSR 0x%03x\n", current->comm,
765 task_pid_nr(current), instrptr, 864 task_pid_nr(current), instrptr,
766 thumb_mode(regs) ? 4 : 8, 865 isize << 1,
767 thumb_mode(regs) ? tinstr : instr, 866 isize == 2 ? tinstr : instr,
768 addr, fsr); 867 addr, fsr);
769 868
770 if (ai_usermode & UM_FIXUP) 869 if (ai_usermode & UM_FIXUP)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 0455557a2899..6fdcbb709827 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -208,7 +208,7 @@ good_area:
208 * than endlessly redo the fault. 208 * than endlessly redo the fault.
209 */ 209 */
210survive: 210survive:
211 fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11)); 211 fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, (fsr & (1 << 11)) ? FAULT_FLAG_WRITE : 0);
212 if (unlikely(fault & VM_FAULT_ERROR)) { 212 if (unlikely(fault & VM_FAULT_ERROR)) {
213 if (fault & VM_FAULT_OOM) 213 if (fault & VM_FAULT_OOM)
214 goto out_of_memory; 214 goto out_of_memory;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8277802ec859..3a7279c1ce5e 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -120,6 +120,32 @@ void show_mem(void)
120 printk("%d pages swap cached\n", cached); 120 printk("%d pages swap cached\n", cached);
121} 121}
122 122
123static void __init find_node_limits(int node, struct meminfo *mi,
124 unsigned long *min, unsigned long *max_low, unsigned long *max_high)
125{
126 int i;
127
128 *min = -1UL;
129 *max_low = *max_high = 0;
130
131 for_each_nodebank(i, mi, node) {
132 struct membank *bank = &mi->bank[i];
133 unsigned long start, end;
134
135 start = bank_pfn_start(bank);
136 end = bank_pfn_end(bank);
137
138 if (*min > start)
139 *min = start;
140 if (*max_high < end)
141 *max_high = end;
142 if (bank->highmem)
143 continue;
144 if (*max_low < end)
145 *max_low = end;
146 }
147}
148
123/* 149/*
124 * FIXME: We really want to avoid allocating the bootmap bitmap 150 * FIXME: We really want to avoid allocating the bootmap bitmap
125 * over the top of the initrd. Hopefully, this is located towards 151 * over the top of the initrd. Hopefully, this is located towards
@@ -210,41 +236,25 @@ static inline void map_memory_bank(struct membank *bank)
210#endif 236#endif
211} 237}
212 238
213static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) 239static void __init bootmem_init_node(int node, struct meminfo *mi,
240 unsigned long start_pfn, unsigned long end_pfn)
214{ 241{
215 unsigned long start_pfn, end_pfn, boot_pfn; 242 unsigned long boot_pfn;
216 unsigned int boot_pages; 243 unsigned int boot_pages;
217 pg_data_t *pgdat; 244 pg_data_t *pgdat;
218 int i; 245 int i;
219 246
220 start_pfn = -1UL;
221 end_pfn = 0;
222
223 /* 247 /*
224 * Calculate the pfn range, and map the memory banks for this node. 248 * Map the memory banks for this node.
225 */ 249 */
226 for_each_nodebank(i, mi, node) { 250 for_each_nodebank(i, mi, node) {
227 struct membank *bank = &mi->bank[i]; 251 struct membank *bank = &mi->bank[i];
228 unsigned long start, end;
229 252
230 start = bank_pfn_start(bank); 253 if (!bank->highmem)
231 end = bank_pfn_end(bank); 254 map_memory_bank(bank);
232
233 if (start_pfn > start)
234 start_pfn = start;
235 if (end_pfn < end)
236 end_pfn = end;
237
238 map_memory_bank(bank);
239 } 255 }
240 256
241 /* 257 /*
242 * If there is no memory in this node, ignore it.
243 */
244 if (end_pfn == 0)
245 return end_pfn;
246
247 /*
248 * Allocate the bootmem bitmap page. 258 * Allocate the bootmem bitmap page.
249 */ 259 */
250 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 260 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
@@ -260,7 +270,8 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
260 270
261 for_each_nodebank(i, mi, node) { 271 for_each_nodebank(i, mi, node) {
262 struct membank *bank = &mi->bank[i]; 272 struct membank *bank = &mi->bank[i];
263 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); 273 if (!bank->highmem)
274 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
264 memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank)); 275 memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
265 } 276 }
266 277
@@ -269,8 +280,6 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
269 */ 280 */
270 reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, 281 reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
271 boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); 282 boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
272
273 return end_pfn;
274} 283}
275 284
276static void __init bootmem_reserve_initrd(int node) 285static void __init bootmem_reserve_initrd(int node)
@@ -297,33 +306,39 @@ static void __init bootmem_reserve_initrd(int node)
297static void __init bootmem_free_node(int node, struct meminfo *mi) 306static void __init bootmem_free_node(int node, struct meminfo *mi)
298{ 307{
299 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; 308 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
300 unsigned long start_pfn, end_pfn; 309 unsigned long min, max_low, max_high;
301 pg_data_t *pgdat = NODE_DATA(node);
302 int i; 310 int i;
303 311
304 start_pfn = pgdat->bdata->node_min_pfn; 312 find_node_limits(node, mi, &min, &max_low, &max_high);
305 end_pfn = pgdat->bdata->node_low_pfn;
306 313
307 /* 314 /*
308 * initialise the zones within this node. 315 * initialise the zones within this node.
309 */ 316 */
310 memset(zone_size, 0, sizeof(zone_size)); 317 memset(zone_size, 0, sizeof(zone_size));
311 memset(zhole_size, 0, sizeof(zhole_size));
312 318
313 /* 319 /*
314 * The size of this node has already been determined. If we need 320 * The size of this node has already been determined. If we need
315 * to do anything fancy with the allocation of this memory to the 321 * to do anything fancy with the allocation of this memory to the
316 * zones, now is the time to do it. 322 * zones, now is the time to do it.
317 */ 323 */
318 zone_size[0] = end_pfn - start_pfn; 324 zone_size[0] = max_low - min;
325#ifdef CONFIG_HIGHMEM
326 zone_size[ZONE_HIGHMEM] = max_high - max_low;
327#endif
319 328
320 /* 329 /*
321 * For each bank in this node, calculate the size of the holes. 330 * For each bank in this node, calculate the size of the holes.
322 * holes = node_size - sum(bank_sizes_in_node) 331 * holes = node_size - sum(bank_sizes_in_node)
323 */ 332 */
324 zhole_size[0] = zone_size[0]; 333 memcpy(zhole_size, zone_size, sizeof(zhole_size));
325 for_each_nodebank(i, mi, node) 334 for_each_nodebank(i, mi, node) {
326 zhole_size[0] -= bank_pfn_size(&mi->bank[i]); 335 int idx = 0;
336#ifdef CONFIG_HIGHMEM
337 if (mi->bank[i].highmem)
338 idx = ZONE_HIGHMEM;
339#endif
340 zhole_size[idx] -= bank_pfn_size(&mi->bank[i]);
341 }
327 342
328 /* 343 /*
329 * Adjust the sizes according to any special requirements for 344 * Adjust the sizes according to any special requirements for
@@ -331,13 +346,13 @@ static void __init bootmem_free_node(int node, struct meminfo *mi)
331 */ 346 */
332 arch_adjust_zones(node, zone_size, zhole_size); 347 arch_adjust_zones(node, zone_size, zhole_size);
333 348
334 free_area_init_node(node, zone_size, start_pfn, zhole_size); 349 free_area_init_node(node, zone_size, min, zhole_size);
335} 350}
336 351
337void __init bootmem_init(void) 352void __init bootmem_init(void)
338{ 353{
339 struct meminfo *mi = &meminfo; 354 struct meminfo *mi = &meminfo;
340 unsigned long memend_pfn = 0; 355 unsigned long min, max_low, max_high;
341 int node, initrd_node; 356 int node, initrd_node;
342 357
343 /* 358 /*
@@ -345,11 +360,29 @@ void __init bootmem_init(void)
345 */ 360 */
346 initrd_node = check_initrd(mi); 361 initrd_node = check_initrd(mi);
347 362
363 max_low = max_high = 0;
364
348 /* 365 /*
349 * Run through each node initialising the bootmem allocator. 366 * Run through each node initialising the bootmem allocator.
350 */ 367 */
351 for_each_node(node) { 368 for_each_node(node) {
352 unsigned long end_pfn = bootmem_init_node(node, mi); 369 unsigned long node_low, node_high;
370
371 find_node_limits(node, mi, &min, &node_low, &node_high);
372
373 if (node_low > max_low)
374 max_low = node_low;
375 if (node_high > max_high)
376 max_high = node_high;
377
378 /*
379 * If there is no memory in this node, ignore it.
380 * (We can't have nodes which have no lowmem)
381 */
382 if (node_low == 0)
383 continue;
384
385 bootmem_init_node(node, mi, min, node_low);
353 386
354 /* 387 /*
355 * Reserve any special node zero regions. 388 * Reserve any special node zero regions.
@@ -362,12 +395,6 @@ void __init bootmem_init(void)
362 */ 395 */
363 if (node == initrd_node) 396 if (node == initrd_node)
364 bootmem_reserve_initrd(node); 397 bootmem_reserve_initrd(node);
365
366 /*
367 * Remember the highest memory PFN.
368 */
369 if (end_pfn > memend_pfn)
370 memend_pfn = end_pfn;
371 } 398 }
372 399
373 /* 400 /*
@@ -383,7 +410,7 @@ void __init bootmem_init(void)
383 for_each_node(node) 410 for_each_node(node)
384 bootmem_free_node(node, mi); 411 bootmem_free_node(node, mi);
385 412
386 high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1; 413 high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
387 414
388 /* 415 /*
389 * This doesn't seem to be used by the Linux memory manager any 416 * This doesn't seem to be used by the Linux memory manager any
@@ -393,7 +420,8 @@ void __init bootmem_init(void)
393 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in 420 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
394 * the system, not the maximum PFN. 421 * the system, not the maximum PFN.
395 */ 422 */
396 max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET; 423 max_low_pfn = max_low - PHYS_PFN_OFFSET;
424 max_pfn = max_high - PHYS_PFN_OFFSET;
397} 425}
398 426
399static inline int free_area(unsigned long pfn, unsigned long end, char *s) 427static inline int free_area(unsigned long pfn, unsigned long end, char *s)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index fdaa9bb87c16..4426ee67ceca 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -687,13 +687,19 @@ __early_param("vmalloc=", early_vmalloc);
687 687
688static void __init sanity_check_meminfo(void) 688static void __init sanity_check_meminfo(void)
689{ 689{
690 int i, j; 690 int i, j, highmem = 0;
691 691
692 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 692 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
693 struct membank *bank = &meminfo.bank[j]; 693 struct membank *bank = &meminfo.bank[j];
694 *bank = meminfo.bank[i]; 694 *bank = meminfo.bank[i];
695 695
696#ifdef CONFIG_HIGHMEM 696#ifdef CONFIG_HIGHMEM
697 if (__va(bank->start) > VMALLOC_MIN ||
698 __va(bank->start) < (void *)PAGE_OFFSET)
699 highmem = 1;
700
701 bank->highmem = highmem;
702
697 /* 703 /*
698 * Split those memory banks which are partially overlapping 704 * Split those memory banks which are partially overlapping
699 * the vmalloc area greatly simplifying things later. 705 * the vmalloc area greatly simplifying things later.
@@ -714,6 +720,7 @@ static void __init sanity_check_meminfo(void)
714 i++; 720 i++;
715 bank[1].size -= VMALLOC_MIN - __va(bank->start); 721 bank[1].size -= VMALLOC_MIN - __va(bank->start);
716 bank[1].start = __pa(VMALLOC_MIN - 1) + 1; 722 bank[1].start = __pa(VMALLOC_MIN - 1) + 1;
723 bank[1].highmem = highmem = 1;
717 j++; 724 j++;
718 } 725 }
719 bank->size = VMALLOC_MIN - __va(bank->start); 726 bank->size = VMALLOC_MIN - __va(bank->start);
@@ -836,6 +843,13 @@ void __init reserve_node_zero(pg_data_t *pgdat)
836 BOOTMEM_EXCLUSIVE); 843 BOOTMEM_EXCLUSIVE);
837 } 844 }
838 845
846 if (machine_is_treo680()) {
847 reserve_bootmem_node(pgdat, 0xa0000000, 0x1000,
848 BOOTMEM_EXCLUSIVE);
849 reserve_bootmem_node(pgdat, 0xa2000000, 0x1000,
850 BOOTMEM_EXCLUSIVE);
851 }
852
839 if (machine_is_palmt5()) 853 if (machine_is_palmt5())
840 reserve_bootmem_node(pgdat, 0xa0200000, 0x1000, 854 reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
841 BOOTMEM_EXCLUSIVE); 855 BOOTMEM_EXCLUSIVE);
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 195e48edd8c2..ac5c80062b70 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
27EXPORT_SYMBOL(__cpuc_flush_user_all); 27EXPORT_SYMBOL(__cpuc_flush_user_all);
28EXPORT_SYMBOL(__cpuc_flush_user_range); 28EXPORT_SYMBOL(__cpuc_flush_user_range);
29EXPORT_SYMBOL(__cpuc_coherent_kern_range); 29EXPORT_SYMBOL(__cpuc_coherent_kern_range);
30EXPORT_SYMBOL(__cpuc_flush_dcache_page);
30EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */ 31EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */
31#else 32#else
32EXPORT_SYMBOL(cpu_cache); 33EXPORT_SYMBOL(cpu_cache);