aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-09-08 05:43:49 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-08 05:43:49 -0400
commit1d6ae775d7a948c9575658eb41184fd2e506c0df (patch)
tree8128a28e89d82f13bb8e3a2160382240c66e2816 /arch/arm/mm
parent739cdbf1d8f0739b80035b80d69d871e33749b86 (diff)
parentcaf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/alignment.c70
-rw-r--r--arch/arm/mm/mm-armv.c30
-rw-r--r--arch/arm/mm/proc-arm6_7.S8
3 files changed, 72 insertions, 36 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 81f4a8a2d34b..4b39d867ac14 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -45,7 +45,7 @@
45 45
46#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) 46#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
47 47
48#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ 48#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */
49#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ 49#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
50 50
51#define RN_BITS(i) ((i >> 16) & 15) /* Rn */ 51#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
@@ -68,6 +68,7 @@ static unsigned long ai_sys;
68static unsigned long ai_skipped; 68static unsigned long ai_skipped;
69static unsigned long ai_half; 69static unsigned long ai_half;
70static unsigned long ai_word; 70static unsigned long ai_word;
71static unsigned long ai_dword;
71static unsigned long ai_multi; 72static unsigned long ai_multi;
72static int ai_usermode; 73static int ai_usermode;
73 74
@@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
93 p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); 94 p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
94 p += sprintf(p, "Half:\t\t%lu\n", ai_half); 95 p += sprintf(p, "Half:\t\t%lu\n", ai_half);
95 p += sprintf(p, "Word:\t\t%lu\n", ai_word); 96 p += sprintf(p, "Word:\t\t%lu\n", ai_word);
97 if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
98 p += sprintf(p, "DWord:\t\t%lu\n", ai_dword);
96 p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); 99 p += sprintf(p, "Multi:\t\t%lu\n", ai_multi);
97 p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, 100 p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
98 usermode_action[ai_usermode]); 101 usermode_action[ai_usermode]);
@@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
283{ 286{
284 unsigned int rd = RD_BITS(instr); 287 unsigned int rd = RD_BITS(instr);
285 288
286 if ((instr & 0x01f00ff0) == 0x01000090)
287 goto swp;
288
289 if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
290 goto bad;
291
292 ai_half += 1; 289 ai_half += 1;
293 290
294 if (user_mode(regs)) 291 if (user_mode(regs))
@@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
323 320
324 return TYPE_LDST; 321 return TYPE_LDST;
325 322
326 swp: 323 fault:
327 printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); 324 return TYPE_FAULT;
328 bad: 325}
329 return TYPE_ERROR; 326
327static int
328do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
329 struct pt_regs *regs)
330{
331 unsigned int rd = RD_BITS(instr);
332
333 ai_dword += 1;
334
335 if (user_mode(regs))
336 goto user;
337
338 if ((instr & 0xf0) == 0xd0) {
339 unsigned long val;
340 get32_unaligned_check(val, addr);
341 regs->uregs[rd] = val;
342 get32_unaligned_check(val, addr+4);
343 regs->uregs[rd+1] = val;
344 } else {
345 put32_unaligned_check(regs->uregs[rd], addr);
346 put32_unaligned_check(regs->uregs[rd+1], addr+4);
347 }
348
349 return TYPE_LDST;
350
351 user:
352 if ((instr & 0xf0) == 0xd0) {
353 unsigned long val;
354 get32t_unaligned_check(val, addr);
355 regs->uregs[rd] = val;
356 get32t_unaligned_check(val, addr+4);
357 regs->uregs[rd+1] = val;
358 } else {
359 put32t_unaligned_check(regs->uregs[rd], addr);
360 put32t_unaligned_check(regs->uregs[rd+1], addr+4);
361 }
362
363 return TYPE_LDST;
330 364
331 fault: 365 fault:
332 return TYPE_FAULT; 366 return TYPE_FAULT;
@@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
617 regs->ARM_pc += thumb_mode(regs) ? 2 : 4; 651 regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
618 652
619 switch (CODING_BITS(instr)) { 653 switch (CODING_BITS(instr)) {
620 case 0x00000000: /* ldrh or strh */ 654 case 0x00000000: /* 3.13.4 load/store instruction extensions */
621 if (LDSTH_I_BIT(instr)) 655 if (LDSTHD_I_BIT(instr))
622 offset.un = (instr & 0xf00) >> 4 | (instr & 15); 656 offset.un = (instr & 0xf00) >> 4 | (instr & 15);
623 else 657 else
624 offset.un = regs->uregs[RM_BITS(instr)]; 658 offset.un = regs->uregs[RM_BITS(instr)];
625 handler = do_alignment_ldrhstrh; 659
660 if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
661 (instr & 0x001000f0) == 0x001000f0) /* LDRSH */
662 handler = do_alignment_ldrhstrh;
663 else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
664 (instr & 0x001000f0) == 0x000000f0) /* STRD */
665 handler = do_alignment_ldrdstrd;
666 else
667 goto bad;
626 break; 668 break;
627 669
628 case 0x04000000: /* ldr or str immediate */ 670 case 0x04000000: /* ldr or str immediate */
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 3c655c54e231..d125a3dc061c 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
275 int i; 275 int i;
276 276
277 for (i = 0; i < 16; i += 1) { 277 for (i = 0; i < 16; i += 1) {
278 alloc_init_section(virt, phys & SUPERSECTION_MASK, 278 alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
279 prot | PMD_SECT_SUPER);
280 279
281 virt += (PGDIR_SIZE / 2); 280 virt += (PGDIR_SIZE / 2);
282 phys += (PGDIR_SIZE / 2);
283 } 281 }
284} 282}
285 283
@@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
297 pte_t *ptep; 295 pte_t *ptep;
298 296
299 if (pmd_none(*pmdp)) { 297 if (pmd_none(*pmdp)) {
300 unsigned long pmdval;
301 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * 298 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
302 sizeof(pte_t)); 299 sizeof(pte_t));
303 300
304 pmdval = __pa(ptep) | prot_l1; 301 __pmd_populate(pmdp, __pa(ptep) | prot_l1);
305 pmdp[0] = __pmd(pmdval);
306 pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
307 flush_pmd_entry(pmdp);
308 } 302 }
309 ptep = pte_offset_kernel(pmdp, virt); 303 ptep = pte_offset_kernel(pmdp, virt);
310 304
@@ -459,7 +453,7 @@ static void __init build_mem_type_table(void)
459 453
460 for (i = 0; i < 16; i++) { 454 for (i = 0; i < 16; i++) {
461 unsigned long v = pgprot_val(protection_map[i]); 455 unsigned long v = pgprot_val(protection_map[i]);
462 v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; 456 v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
463 protection_map[i] = __pgprot(v); 457 protection_map[i] = __pgprot(v);
464 } 458 }
465 459
@@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
583 */ 577 */
584void setup_mm_for_reboot(char mode) 578void setup_mm_for_reboot(char mode)
585{ 579{
586 unsigned long pmdval; 580 unsigned long base_pmdval;
587 pgd_t *pgd; 581 pgd_t *pgd;
588 pmd_t *pmd;
589 int i; 582 int i;
590 int cpu_arch = cpu_architecture();
591 583
592 if (current->mm && current->mm->pgd) 584 if (current->mm && current->mm->pgd)
593 pgd = current->mm->pgd; 585 pgd = current->mm->pgd;
594 else 586 else
595 pgd = init_mm.pgd; 587 pgd = init_mm.pgd;
596 588
597 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { 589 base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
598 pmdval = (i << PGDIR_SHIFT) | 590 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
599 PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | 591 base_pmdval |= PMD_BIT4;
600 PMD_TYPE_SECT; 592
601 if (cpu_arch <= CPU_ARCH_ARMv5TEJ) 593 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
602 pmdval |= PMD_BIT4; 594 unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
595 pmd_t *pmd;
596
603 pmd = pmd_off(pgd, i << PGDIR_SHIFT); 597 pmd = pmd_off(pgd, i << PGDIR_SHIFT);
604 pmd[0] = __pmd(pmdval); 598 pmd[0] = __pmd(pmdval);
605 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); 599 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 0ee214b824ff..189ef6a71ba1 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -38,8 +38,8 @@ ENTRY(cpu_arm7_data_abort)
38 mrc p15, 0, r1, c5, c0, 0 @ get FSR 38 mrc p15, 0, r1, c5, c0, 0 @ get FSR
39 mrc p15, 0, r0, c6, c0, 0 @ get FAR 39 mrc p15, 0, r0, c6, c0, 0 @ get FAR
40 ldr r8, [r0] @ read arm instruction 40 ldr r8, [r0] @ read arm instruction
41 tst r8, #1 << 20 @ L = 1 -> write? 41 tst r8, #1 << 20 @ L = 0 -> write?
42 orreq r1, r1, #1 << 8 @ yes. 42 orreq r1, r1, #1 << 11 @ yes.
43 and r7, r8, #15 << 24 43 and r7, r8, #15 << 24
44 add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine 44 add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
45 nop 45 nop
@@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
71 mrc p15, 0, r1, c5, c0, 0 @ get FSR 71 mrc p15, 0, r1, c5, c0, 0 @ get FSR
72 mrc p15, 0, r0, c6, c0, 0 @ get FAR 72 mrc p15, 0, r0, c6, c0, 0 @ get FAR
73 ldr r8, [r2] @ read arm instruction 73 ldr r8, [r2] @ read arm instruction
74 tst r8, #1 << 20 @ L = 1 -> write? 74 tst r8, #1 << 20 @ L = 0 -> write?
75 orreq r1, r1, #1 << 8 @ yes. 75 orreq r1, r1, #1 << 11 @ yes.
76 and r7, r8, #14 << 24 76 and r7, r8, #14 << 24
77 teq r7, #8 << 24 @ was it ldm/stm 77 teq r7, #8 << 24 @ was it ldm/stm
78 movne pc, lr 78 movne pc, lr