]> Pileus Git - ~andy/linux/blobdiff - arch/arm/mm/context.c
ARM: 7925/1: mm: keep track of last ASID allocation to improve bitmap searching
[~andy/linux] / arch / arm / mm / context.c
index 84e6f772e204597032cc0fcd4101f36ce588728f..52e6f13ac9c78f053acc35e491751869c2895bcd 100644 (file)
@@ -78,20 +78,21 @@ void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm,
 #endif
 
 #ifdef CONFIG_ARM_LPAE
-static void cpu_set_reserved_ttbr0(void)
-{
-       /*
-        * Set TTBR0 to swapper_pg_dir which contains only global entries. The
-        * ASID is set to 0.
-        */
-       cpu_set_ttbr(0, __pa(swapper_pg_dir));
-       isb();
-}
+/*
+ * With LPAE, the ASID and page tables are updated atomicly, so there is
+ * no need for a reserved set of tables (the active ASID tracking prevents
+ * any issues across a rollover).
+ */
+#define cpu_set_reserved_ttbr0()
 #else
 static void cpu_set_reserved_ttbr0(void)
 {
        u32 ttb;
-       /* Copy TTBR1 into TTBR0 */
+       /*
+        * Copy TTBR1 into TTBR0.
+        * This points at swapper_pg_dir, which contains only global
+        * entries so any speculative walks are perfectly safe.
+        */
        asm volatile(
        "       mrc     p15, 0, %0, c2, c0, 1           @ read TTBR1\n"
        "       mcr     p15, 0, %0, c2, c0, 0           @ set TTBR0\n"
@@ -179,6 +180,7 @@ static int is_reserved_asid(u64 asid)
 
 static u64 new_context(struct mm_struct *mm, unsigned int cpu)
 {
+       static u32 cur_idx = 1;
        u64 asid = atomic64_read(&mm->context.id);
        u64 generation = atomic64_read(&asid_generation);
 
@@ -196,7 +198,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                 * as we reserve ASID #0 to switch via TTBR0 and indicate
                 * rollover events.
                 */
-               asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
+               asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx);
                if (asid == NUM_USER_ASIDS) {
                        generation = atomic64_add_return(ASID_FIRST_VERSION,
                                                         &asid_generation);
@@ -204,6 +206,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                        asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
                }
                __set_bit(asid, asid_map);
+               cur_idx = asid;
                asid |= generation;
                cpumask_clear(mm_cpumask(mm));
        }