[ARM] 4128/1: Architecture compliant TTBR changing sequence

On newer architectures (ARMv6, ARMv7), the depth of the prefetch and
branch prediction is implementation defined and there is a small risk
of wrong ASID tagging when changing TTBR0 before setting the new
context id. The recommended solution is to set a reserved ASID during
TTBR changing. This patch reserves ASID 0.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 79e8002..9da43a0 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -19,7 +19,8 @@
 /*
  * We fork()ed a process, and we need a new context for the child
  * to run in.  We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
  */
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -38,8 +39,15 @@
 	 * If we've used up all our ASIDs, we need
 	 * to start a new version and flush the TLB.
 	 */
-	if ((asid & ~ASID_MASK) == 0)
+	if ((asid & ~ASID_MASK) == 0) {
+		asid = ++cpu_last_asid;
+		/* set the reserved ASID before flushing the TLB */
+		asm("mcr	p15, 0, %0, c13, c0, 1	@ set reserved context ID\n"
+		    :
+		    : "r" (0));
+		isb();
 		flush_tlb_all();
+	}
 
 	mm->context.id = asid;
 }