diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-11-07 05:10:28 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-11-07 05:10:28 -0500 |
commit | cd03adb0812fe0fb06cdb935e61ec9514254e951 (patch) | |
tree | 6a79344e646b6c3815a77f0eb4ed721f50c31701 /arch/arm | |
parent | 0b154bb7d0cce80e9c0bcf11d4f9e71b59409d26 (diff) |
[ARM SMP] Add support for shared memory attribute
We need to set the shared memory attribute in the page tables
on SMP systems to allow the cache coherency to operate.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mm/mm-armv.c | 48 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 8 |
2 files changed, 39 insertions, 17 deletions
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index fb5b40289de2..9e50127be635 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
@@ -354,7 +354,7 @@ void __init build_mem_type_table(void) | |||
354 | { | 354 | { |
355 | struct cachepolicy *cp; | 355 | struct cachepolicy *cp; |
356 | unsigned int cr = get_cr(); | 356 | unsigned int cr = get_cr(); |
357 | unsigned int user_pgprot; | 357 | unsigned int user_pgprot, kern_pgprot; |
358 | int cpu_arch = cpu_architecture(); | 358 | int cpu_arch = cpu_architecture(); |
359 | int i; | 359 | int i; |
360 | 360 | ||
@@ -381,7 +381,7 @@ void __init build_mem_type_table(void) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | cp = &cache_policies[cachepolicy]; | 383 | cp = &cache_policies[cachepolicy]; |
384 | user_pgprot = cp->pte; | 384 | kern_pgprot = user_pgprot = cp->pte; |
385 | 385 | ||
386 | /* | 386 | /* |
387 | * ARMv6 and above have extended page tables. | 387 | * ARMv6 and above have extended page tables. |
@@ -393,6 +393,7 @@ void __init build_mem_type_table(void) | |||
393 | */ | 393 | */ |
394 | mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; | 394 | mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; |
395 | mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; | 395 | mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; |
396 | |||
396 | /* | 397 | /* |
397 | * Mark cache clean areas and XIP ROM read only | 398 | * Mark cache clean areas and XIP ROM read only |
398 | * from SVC mode and no access from userspace. | 399 | * from SVC mode and no access from userspace. |
@@ -412,32 +413,47 @@ void __init build_mem_type_table(void) | |||
412 | * (iow, non-global) | 413 | * (iow, non-global) |
413 | */ | 414 | */ |
414 | user_pgprot |= L_PTE_ASID; | 415 | user_pgprot |= L_PTE_ASID; |
416 | |||
417 | #ifdef CONFIG_SMP | ||
418 | /* | ||
419 | * Mark memory with the "shared" attribute for SMP systems | ||
420 | */ | ||
421 | user_pgprot |= L_PTE_SHARED; | ||
422 | kern_pgprot |= L_PTE_SHARED; | ||
423 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | ||
424 | #endif | ||
415 | } | 425 | } |
416 | 426 | ||
427 | for (i = 0; i < 16; i++) { | ||
428 | unsigned long v = pgprot_val(protection_map[i]); | ||
429 | v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot; | ||
430 | protection_map[i] = __pgprot(v); | ||
431 | } | ||
432 | |||
433 | mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot; | ||
434 | mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot; | ||
435 | |||
417 | if (cpu_arch >= CPU_ARCH_ARMv5) { | 436 | if (cpu_arch >= CPU_ARCH_ARMv5) { |
418 | mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; | 437 | #ifndef CONFIG_SMP |
419 | mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; | 438 | /* |
439 | * Only use write-through for non-SMP systems | ||
440 | */ | ||
441 | mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; | ||
442 | mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; | ||
443 | #endif | ||
420 | } else { | 444 | } else { |
421 | mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte; | ||
422 | mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte; | ||
423 | mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); | 445 | mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); |
424 | } | 446 | } |
425 | 447 | ||
448 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | ||
449 | L_PTE_DIRTY | L_PTE_WRITE | | ||
450 | L_PTE_EXEC | kern_pgprot); | ||
451 | |||
426 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 452 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; |
427 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 453 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; |
428 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; | 454 | mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; |
429 | mem_types[MT_ROM].prot_sect |= cp->pmd; | 455 | mem_types[MT_ROM].prot_sect |= cp->pmd; |
430 | 456 | ||
431 | for (i = 0; i < 16; i++) { | ||
432 | unsigned long v = pgprot_val(protection_map[i]); | ||
433 | v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; | ||
434 | protection_map[i] = __pgprot(v); | ||
435 | } | ||
436 | |||
437 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | ||
438 | L_PTE_DIRTY | L_PTE_WRITE | | ||
439 | L_PTE_EXEC | cp->pte); | ||
440 | |||
441 | switch (cp->pmd) { | 457 | switch (cp->pmd) { |
442 | case PMD_SECT_WT: | 458 | case PMD_SECT_WT: |
443 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; | 459 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 9bb5fff406fb..a39d8fa2ede5 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -112,6 +112,9 @@ ENTRY(cpu_v6_dcache_clean_area) | |||
112 | ENTRY(cpu_v6_switch_mm) | 112 | ENTRY(cpu_v6_switch_mm) |
113 | mov r2, #0 | 113 | mov r2, #0 |
114 | ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id | 114 | ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id |
115 | #ifdef CONFIG_SMP | ||
116 | orr r0, r0, #2 @ set shared pgtable | ||
117 | #endif | ||
115 | mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB | 118 | mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB |
116 | mcr p15, 0, r2, c7, c10, 4 @ drain write buffer | 119 | mcr p15, 0, r2, c7, c10, 4 @ drain write buffer |
117 | mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 | 120 | mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 |
@@ -140,7 +143,7 @@ ENTRY(cpu_v6_switch_mm) | |||
140 | ENTRY(cpu_v6_set_pte) | 143 | ENTRY(cpu_v6_set_pte) |
141 | str r1, [r0], #-2048 @ linux version | 144 | str r1, [r0], #-2048 @ linux version |
142 | 145 | ||
143 | bic r2, r1, #0x000007f0 | 146 | bic r2, r1, #0x000003f0 |
144 | bic r2, r2, #0x00000003 | 147 | bic r2, r2, #0x00000003 |
145 | orr r2, r2, #PTE_EXT_AP0 | 2 | 148 | orr r2, r2, #PTE_EXT_AP0 | 2 |
146 | 149 | ||
@@ -198,6 +201,9 @@ __v6_setup: | |||
198 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | 201 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer |
199 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs | 202 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs |
200 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register | 203 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register |
204 | #ifdef CONFIG_SMP | ||
205 | orr r4, r4, #2 @ set shared pgtable | ||
206 | #endif | ||
201 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 207 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
202 | #ifdef CONFIG_VFP | 208 | #ifdef CONFIG_VFP |
203 | mrc p15, 0, r0, c1, c0, 2 | 209 | mrc p15, 0, r0, c1, c0, 2 |