diff options
Diffstat (limited to 'arch/arm/mm')
| -rw-r--r-- | arch/arm/mm/alignment.c | 19 | ||||
| -rw-r--r-- | arch/arm/mm/mmu.c | 31 | ||||
| -rw-r--r-- | arch/arm/mm/proc-v7.S | 62 | 
3 files changed, 102 insertions, 10 deletions
| diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index d073b64ae87e..724ba3bce72c 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
| @@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
| 885 | 885 | ||
| 886 | if (ai_usermode & UM_SIGNAL) | 886 | if (ai_usermode & UM_SIGNAL) | 
| 887 | force_sig(SIGBUS, current); | 887 | force_sig(SIGBUS, current); | 
| 888 | else | 888 | else { | 
| 889 | set_cr(cr_no_alignment); | 889 | /* | 
| 890 | * We're about to disable the alignment trap and return to | ||
| 891 | * user space. But if an interrupt occurs before actually | ||
| 892 | * reaching user space, then the IRQ vector entry code will | ||
| 893 | * notice that we were still in kernel space and therefore | ||
| 894 | * the alignment trap won't be re-enabled in that case as it | ||
| 895 | * is presumed to be always on from kernel space. | ||
| 896 | * Let's prevent that race by disabling interrupts here (they | ||
| 897 | * are disabled on the way back to user space anyway in | ||
| 898 | * entry-common.S) and disable the alignment trap only if | ||
| 899 | * there is no work pending for this thread. | ||
| 900 | */ | ||
| 901 | raw_local_irq_disable(); | ||
| 902 | if (!(current_thread_info()->flags & _TIF_WORK_MASK)) | ||
| 903 | set_cr(cr_no_alignment); | ||
| 904 | } | ||
| 890 | 905 | ||
| 891 | return 0; | 906 | return 0; | 
| 892 | } | 907 | } | 
| diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6e1c4f6a2b3f..6a3a2d0cd6db 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/nodemask.h> | 15 | #include <linux/nodemask.h> | 
| 16 | #include <linux/memblock.h> | 16 | #include <linux/memblock.h> | 
| 17 | #include <linux/sort.h> | 17 | #include <linux/sort.h> | 
| 18 | #include <linux/fs.h> | ||
| 18 | 19 | ||
| 19 | #include <asm/cputype.h> | 20 | #include <asm/cputype.h> | 
| 20 | #include <asm/sections.h> | 21 | #include <asm/sections.h> | 
| @@ -246,6 +247,9 @@ static struct mem_type mem_types[] = { | |||
| 246 | .domain = DOMAIN_USER, | 247 | .domain = DOMAIN_USER, | 
| 247 | }, | 248 | }, | 
| 248 | [MT_MEMORY] = { | 249 | [MT_MEMORY] = { | 
| 250 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | ||
| 251 | L_PTE_USER | L_PTE_EXEC, | ||
| 252 | .prot_l1 = PMD_TYPE_TABLE, | ||
| 249 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 253 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 
| 250 | .domain = DOMAIN_KERNEL, | 254 | .domain = DOMAIN_KERNEL, | 
| 251 | }, | 255 | }, | 
| @@ -254,6 +258,9 @@ static struct mem_type mem_types[] = { | |||
| 254 | .domain = DOMAIN_KERNEL, | 258 | .domain = DOMAIN_KERNEL, | 
| 255 | }, | 259 | }, | 
| 256 | [MT_MEMORY_NONCACHED] = { | 260 | [MT_MEMORY_NONCACHED] = { | 
| 261 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | ||
| 262 | L_PTE_USER | L_PTE_EXEC | L_PTE_MT_BUFFERABLE, | ||
| 263 | .prot_l1 = PMD_TYPE_TABLE, | ||
| 257 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 264 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 
| 258 | .domain = DOMAIN_KERNEL, | 265 | .domain = DOMAIN_KERNEL, | 
| 259 | }, | 266 | }, | 
| @@ -411,9 +418,12 @@ static void __init build_mem_type_table(void) | |||
| 411 | * Enable CPU-specific coherency if supported. | 418 | * Enable CPU-specific coherency if supported. | 
| 412 | * (Only available on XSC3 at the moment.) | 419 | * (Only available on XSC3 at the moment.) | 
| 413 | */ | 420 | */ | 
| 414 | if (arch_is_coherent() && cpu_is_xsc3()) | 421 | if (arch_is_coherent() && cpu_is_xsc3()) { | 
| 415 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | 422 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | 
| 416 | 423 | mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; | |
| 424 | mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; | ||
| 425 | mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; | ||
| 426 | } | ||
| 417 | /* | 427 | /* | 
| 418 | * ARMv6 and above have extended page tables. | 428 | * ARMv6 and above have extended page tables. | 
| 419 | */ | 429 | */ | 
| @@ -438,7 +448,9 @@ static void __init build_mem_type_table(void) | |||
| 438 | mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; | 448 | mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; | 
| 439 | mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; | 449 | mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; | 
| 440 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | 450 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | 
| 451 | mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; | ||
| 441 | mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; | 452 | mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; | 
| 453 | mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; | ||
| 442 | #endif | 454 | #endif | 
| 443 | } | 455 | } | 
| 444 | 456 | ||
| @@ -475,6 +487,8 @@ static void __init build_mem_type_table(void) | |||
| 475 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 487 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 
| 476 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 488 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 
| 477 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; | 489 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; | 
| 490 | mem_types[MT_MEMORY].prot_pte |= kern_pgprot; | ||
| 491 | mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask; | ||
| 478 | mem_types[MT_ROM].prot_sect |= cp->pmd; | 492 | mem_types[MT_ROM].prot_sect |= cp->pmd; | 
| 479 | 493 | ||
| 480 | switch (cp->pmd) { | 494 | switch (cp->pmd) { | 
| @@ -498,6 +512,19 @@ static void __init build_mem_type_table(void) | |||
| 498 | } | 512 | } | 
| 499 | } | 513 | } | 
| 500 | 514 | ||
| 515 | #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE | ||
| 516 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
| 517 | unsigned long size, pgprot_t vma_prot) | ||
| 518 | { | ||
| 519 | if (!pfn_valid(pfn)) | ||
| 520 | return pgprot_noncached(vma_prot); | ||
| 521 | else if (file->f_flags & O_SYNC) | ||
| 522 | return pgprot_writecombine(vma_prot); | ||
| 523 | return vma_prot; | ||
| 524 | } | ||
| 525 | EXPORT_SYMBOL(phys_mem_access_prot); | ||
| 526 | #endif | ||
| 527 | |||
| 501 | #define vectors_base() (vectors_high() ? 0xffff0000 : 0) | 528 | #define vectors_base() (vectors_high() ? 0xffff0000 : 0) | 
| 502 | 529 | ||
| 503 | static void __init *early_alloc(unsigned long sz) | 530 | static void __init *early_alloc(unsigned long sz) | 
| diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 6a8506d99ee9..7563ff0141bd 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
| @@ -186,13 +186,14 @@ cpu_v7_name: | |||
| 186 | * It is assumed that: | 186 | * It is assumed that: | 
| 187 | * - cache type register is implemented | 187 | * - cache type register is implemented | 
| 188 | */ | 188 | */ | 
| 189 | __v7_setup: | 189 | __v7_ca9mp_setup: | 
| 190 | #ifdef CONFIG_SMP | 190 | #ifdef CONFIG_SMP | 
| 191 | mrc p15, 0, r0, c1, c0, 1 | 191 | mrc p15, 0, r0, c1, c0, 1 | 
| 192 | tst r0, #(1 << 6) @ SMP/nAMP mode enabled? | 192 | tst r0, #(1 << 6) @ SMP/nAMP mode enabled? | 
| 193 | orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and | 193 | orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and | 
| 194 | mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting | 194 | mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting | 
| 195 | #endif | 195 | #endif | 
| 196 | __v7_setup: | ||
| 196 | adr r12, __v7_setup_stack @ the local stack | 197 | adr r12, __v7_setup_stack @ the local stack | 
| 197 | stmia r12, {r0-r5, r7, r9, r11, lr} | 198 | stmia r12, {r0-r5, r7, r9, r11, lr} | 
| 198 | bl v7_flush_dcache_all | 199 | bl v7_flush_dcache_all | 
| @@ -201,11 +202,16 @@ __v7_setup: | |||
| 201 | mrc p15, 0, r0, c0, c0, 0 @ read main ID register | 202 | mrc p15, 0, r0, c0, c0, 0 @ read main ID register | 
| 202 | and r10, r0, #0xff000000 @ ARM? | 203 | and r10, r0, #0xff000000 @ ARM? | 
| 203 | teq r10, #0x41000000 | 204 | teq r10, #0x41000000 | 
| 204 | bne 2f | 205 | bne 3f | 
| 205 | and r5, r0, #0x00f00000 @ variant | 206 | and r5, r0, #0x00f00000 @ variant | 
| 206 | and r6, r0, #0x0000000f @ revision | 207 | and r6, r0, #0x0000000f @ revision | 
| 207 | orr r0, r6, r5, lsr #20-4 @ combine variant and revision | 208 | orr r6, r6, r5, lsr #20-4 @ combine variant and revision | 
| 209 | ubfx r0, r0, #4, #12 @ primary part number | ||
| 208 | 210 | ||
| 211 | /* Cortex-A8 Errata */ | ||
| 212 | ldr r10, =0x00000c08 @ Cortex-A8 primary part number | ||
| 213 | teq r0, r10 | ||
| 214 | bne 2f | ||
| 209 | #ifdef CONFIG_ARM_ERRATA_430973 | 215 | #ifdef CONFIG_ARM_ERRATA_430973 | 
| 210 | teq r5, #0x00100000 @ only present in r1p* | 216 | teq r5, #0x00100000 @ only present in r1p* | 
| 211 | mrceq p15, 0, r10, c1, c0, 1 @ read aux control register | 217 | mrceq p15, 0, r10, c1, c0, 1 @ read aux control register | 
| @@ -213,21 +219,42 @@ __v7_setup: | |||
| 213 | mcreq p15, 0, r10, c1, c0, 1 @ write aux control register | 219 | mcreq p15, 0, r10, c1, c0, 1 @ write aux control register | 
| 214 | #endif | 220 | #endif | 
| 215 | #ifdef CONFIG_ARM_ERRATA_458693 | 221 | #ifdef CONFIG_ARM_ERRATA_458693 | 
| 216 | teq r0, #0x20 @ only present in r2p0 | 222 | teq r6, #0x20 @ only present in r2p0 | 
| 217 | mrceq p15, 0, r10, c1, c0, 1 @ read aux control register | 223 | mrceq p15, 0, r10, c1, c0, 1 @ read aux control register | 
| 218 | orreq r10, r10, #(1 << 5) @ set L1NEON to 1 | 224 | orreq r10, r10, #(1 << 5) @ set L1NEON to 1 | 
| 219 | orreq r10, r10, #(1 << 9) @ set PLDNOP to 1 | 225 | orreq r10, r10, #(1 << 9) @ set PLDNOP to 1 | 
| 220 | mcreq p15, 0, r10, c1, c0, 1 @ write aux control register | 226 | mcreq p15, 0, r10, c1, c0, 1 @ write aux control register | 
| 221 | #endif | 227 | #endif | 
| 222 | #ifdef CONFIG_ARM_ERRATA_460075 | 228 | #ifdef CONFIG_ARM_ERRATA_460075 | 
| 223 | teq r0, #0x20 @ only present in r2p0 | 229 | teq r6, #0x20 @ only present in r2p0 | 
| 224 | mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register | 230 | mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register | 
| 225 | tsteq r10, #1 << 22 | 231 | tsteq r10, #1 << 22 | 
| 226 | orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit | 232 | orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit | 
| 227 | mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register | 233 | mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register | 
| 228 | #endif | 234 | #endif | 
| 235 | b 3f | ||
| 236 | |||
| 237 | /* Cortex-A9 Errata */ | ||
| 238 | 2: ldr r10, =0x00000c09 @ Cortex-A9 primary part number | ||
| 239 | teq r0, r10 | ||
| 240 | bne 3f | ||
| 241 | #ifdef CONFIG_ARM_ERRATA_742230 | ||
| 242 | cmp r6, #0x22 @ only present up to r2p2 | ||
| 243 | mrcle p15, 0, r10, c15, c0, 1 @ read diagnostic register | ||
| 244 | orrle r10, r10, #1 << 4 @ set bit #4 | ||
| 245 | mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register | ||
| 246 | #endif | ||
| 247 | #ifdef CONFIG_ARM_ERRATA_742231 | ||
| 248 | teq r6, #0x20 @ present in r2p0 | ||
| 249 | teqne r6, #0x21 @ present in r2p1 | ||
| 250 | teqne r6, #0x22 @ present in r2p2 | ||
| 251 | mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register | ||
| 252 | orreq r10, r10, #1 << 12 @ set bit #12 | ||
| 253 | orreq r10, r10, #1 << 22 @ set bit #22 | ||
| 254 | mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register | ||
| 255 | #endif | ||
| 229 | 256 | ||
| 230 | 2: mov r10, #0 | 257 | 3: mov r10, #0 | 
| 231 | #ifdef HARVARD_CACHE | 258 | #ifdef HARVARD_CACHE | 
| 232 | mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate | 259 | mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate | 
| 233 | #endif | 260 | #endif | 
| @@ -323,6 +350,29 @@ cpu_elf_name: | |||
| 323 | 350 | ||
| 324 | .section ".proc.info.init", #alloc, #execinstr | 351 | .section ".proc.info.init", #alloc, #execinstr | 
| 325 | 352 | ||
| 353 | .type __v7_ca9mp_proc_info, #object | ||
| 354 | __v7_ca9mp_proc_info: | ||
| 355 | .long 0x410fc090 @ Required ID value | ||
| 356 | .long 0xff0ffff0 @ Mask for ID | ||
| 357 | .long PMD_TYPE_SECT | \ | ||
| 358 | PMD_SECT_AP_WRITE | \ | ||
| 359 | PMD_SECT_AP_READ | \ | ||
| 360 | PMD_FLAGS | ||
| 361 | .long PMD_TYPE_SECT | \ | ||
| 362 | PMD_SECT_XN | \ | ||
| 363 | PMD_SECT_AP_WRITE | \ | ||
| 364 | PMD_SECT_AP_READ | ||
| 365 | b __v7_ca9mp_setup | ||
| 366 | .long cpu_arch_name | ||
| 367 | .long cpu_elf_name | ||
| 368 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP | ||
| 369 | .long cpu_v7_name | ||
| 370 | .long v7_processor_functions | ||
| 371 | .long v7wbi_tlb_fns | ||
| 372 | .long v6_user_fns | ||
| 373 | .long v7_cache_fns | ||
| 374 | .size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info | ||
| 375 | |||
| 326 | /* | 376 | /* | 
| 327 | * Match any ARMv7 processor core. | 377 | * Match any ARMv7 processor core. | 
| 328 | */ | 378 | */ | 
