]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/arm/mm/mm-armv.c
[ARM SMP] Add support for shared memory attribute
[karo-tx-linux.git] / arch / arm / mm / mm-armv.c
index fb5b40289de287fa34ab4e986e1fcbde7d18d99c..9e50127be635c7bbb52c4dc8824524ba4397f6fc 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;