[ARM SMP] Add support for shared memory attribute
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Mon, 7 Nov 2005 10:10:28 +0000 (10:10 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 7 Nov 2005 10:10:28 +0000 (10:10 +0000)
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>
arch/arm/mm/mm-armv.c
arch/arm/mm/proc-v6.S

index fb5b402..9e50127 100644 (file)
@@ -354,7 +354,7 @@ void __init build_mem_type_table(void)
 {
        struct cachepolicy *cp;
        unsigned int cr = get_cr();
-       unsigned int user_pgprot;
+       unsigned int user_pgprot, kern_pgprot;
        int cpu_arch = cpu_architecture();
        int i;
 
@@ -381,7 +381,7 @@ void __init build_mem_type_table(void)
        }
 
        cp = &cache_policies[cachepolicy];
-       user_pgprot = cp->pte;
+       kern_pgprot = user_pgprot = cp->pte;
 
        /*
         * ARMv6 and above have extended page tables.
@@ -393,6 +393,7 @@ void __init build_mem_type_table(void)
                 */
                mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
                mem_types[MT_ROM].prot_sect &= ~PMD_BIT4;
+
                /*
                 * Mark cache clean areas and XIP ROM read only
                 * from SVC mode and no access from userspace.
@@ -412,32 +413,47 @@ void __init build_mem_type_table(void)
                 * (iow, non-global)
                 */
                user_pgprot |= L_PTE_ASID;
+
+#ifdef CONFIG_SMP
+               /*
+                * Mark memory with the "shared" attribute for SMP systems
+                */
+               user_pgprot |= L_PTE_SHARED;
+               kern_pgprot |= L_PTE_SHARED;
+               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+#endif
        }
 
+       for (i = 0; i < 16; i++) {
+               unsigned long v = pgprot_val(protection_map[i]);
+               v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
+               protection_map[i] = __pgprot(v);
+       }
+
+       mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
+       mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
+
        if (cpu_arch >= CPU_ARCH_ARMv5) {
-               mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
-               mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
+#ifndef CONFIG_SMP
+               /*
+                * Only use write-through for non-SMP systems
+                */
+               mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+               mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+#endif
        } else {
-               mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte;
-               mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte;
                mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
        }
 
+       pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
+                                L_PTE_DIRTY | L_PTE_WRITE |
+                                L_PTE_EXEC | kern_pgprot);
+
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
        mem_types[MT_ROM].prot_sect |= cp->pmd;
 
-       for (i = 0; i < 16; i++) {
-               unsigned long v = pgprot_val(protection_map[i]);
-               v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
-               protection_map[i] = __pgprot(v);
-       }
-
-       pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-                                L_PTE_DIRTY | L_PTE_WRITE |
-                                L_PTE_EXEC | cp->pte);
-
        switch (cp->pmd) {
        case PMD_SECT_WT:
                mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
index 9bb5fff..a39d8fa 100644 (file)
@@ -112,6 +112,9 @@ ENTRY(cpu_v6_dcache_clean_area)
 ENTRY(cpu_v6_switch_mm)
        mov     r2, #0
        ldr     r1, [r1, #MM_CONTEXT_ID]        @ get mm->context.id
+#ifdef CONFIG_SMP
+       orr     r0, r0, #2                      @ set shared pgtable
+#endif
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
        mcr     p15, 0, r2, c7, c10, 4          @ drain write buffer
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
@@ -140,7 +143,7 @@ ENTRY(cpu_v6_switch_mm)
 ENTRY(cpu_v6_set_pte)
        str     r1, [r0], #-2048                @ linux version
 
-       bic     r2, r1, #0x000007f0
+       bic     r2, r1, #0x000003f0
        bic     r2, r2, #0x00000003
        orr     r2, r2, #PTE_EXT_AP0 | 2
 
@@ -198,6 +201,9 @@ __v6_setup:
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
        mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
        mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
+#ifdef CONFIG_SMP
+       orr     r4, r4, #2                      @ set shared pgtable
+#endif
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
 #ifdef CONFIG_VFP
        mrc     p15, 0, r0, c1, c0, 2