Merge branch 'stable/bug.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / powerpc / mm / tlb_nohash.c
index 0bdad3a..d32ec64 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/preempt.h>
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
+#include <linux/of_fdt.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -102,6 +103,12 @@ unsigned long linear_map_top;      /* Top of linear mapping */
 
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+/* next_tlbcam_idx is used to round-robin tlbcam entry assignment */
+DEFINE_PER_CPU(int, next_tlbcam_idx);
+EXPORT_PER_CPU_SYMBOL(next_tlbcam_idx);
+#endif
+
 /*
  * Base TLB flushing operations:
  *
@@ -266,6 +273,17 @@ EXPORT_SYMBOL(flush_tlb_page);
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_47x
+void __init early_init_mmu_47x(void)
+{
+#ifdef CONFIG_SMP
+       unsigned long root = of_get_flat_dt_root();
+       if (of_get_flat_dt_prop(root, "cooperative-partition", NULL))
+               mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST);
+#endif /* CONFIG_SMP */
+}
+#endif /* CONFIG_PPC_47x */
+
 /*
  * Flush kernel TLB entries in the given range
  */
@@ -443,14 +461,27 @@ static void setup_page_sizes(void)
        }
 }
 
-static void setup_mmu_htw(void)
+static void __patch_exception(int exc, unsigned long addr)
 {
        extern unsigned int interrupt_base_book3e;
-       extern unsigned int exc_data_tlb_miss_htw_book3e;
-       extern unsigned int exc_instruction_tlb_miss_htw_book3e;
+       unsigned int *ibase = &interrupt_base_book3e;
+       /* Our exceptions vectors start with a NOP and -then- a branch
+        * to deal with single stepping from userspace which stops on
+        * the second instruction. Thus we need to patch the second
+        * instruction of the exception, not the first one
+        */
 
-       unsigned int *ibase = &interrupt_base_book3e;
+       patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
+
+#define patch_exception(exc, name) do { \
+       extern unsigned int name; \
+       __patch_exception((exc), (unsigned long)&name); \
+} while (0)
 
+static void setup_mmu_htw(void)
+{
        /* Check if HW tablewalk is present, and if yes, enable it by:
         *
         * - patching the TLB miss handlers to branch to the
@@ -462,19 +493,12 @@ static void setup_mmu_htw(void)
 
        if ((tlb0cfg & TLBnCFG_IND) &&
            (tlb0cfg & TLBnCFG_PT)) {
-               /* Our exceptions vectors start with a NOP and -then- a branch
-                * to deal with single stepping from userspace which stops on
-                * the second instruction. Thus we need to patch the second
-                * instruction of the exception, not the first one
-                */
-               patch_branch(ibase + (0x1c0 / 4) + 1,
-                            (unsigned long)&exc_data_tlb_miss_htw_book3e, 0);
-               patch_branch(ibase + (0x1e0 / 4) + 1,
-                            (unsigned long)&exc_instruction_tlb_miss_htw_book3e, 0);
+               patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
+               patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
                book3e_htw_enabled = 1;
        }
-       pr_info("MMU: Book3E Page Tables %s\n",
-               book3e_htw_enabled ? "Enabled" : "Disabled");
+       pr_info("MMU: Book3E HW tablewalk %s\n",
+               book3e_htw_enabled ? "enabled" : "not supported");
 }
 
 /*
@@ -549,6 +573,9 @@ static void __early_init_mmu(int boot_cpu)
                /* limit memory so we dont have linear faults */
                memblock_enforce_memory_limit(linear_map_top);
                memblock_analyze();
+
+               patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
+               patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
        }
 #endif
 
@@ -584,4 +611,11 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
        /* Finally limit subsequent allocations */
        memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
 }
+#else /* ! CONFIG_PPC64 */
+void __init early_init_mmu(void)
+{
+#ifdef CONFIG_PPC_47x
+       early_init_mmu_47x();
+#endif
+}
 #endif /* CONFIG_PPC64 */