@@ -14,6 +14,7 @@
#include <linux/percpu.h>
#include <asm/mmu_context.h>
+#include <asm/thread_notify.h>
#include <asm/tlbflush.h>
static DEFINE_SPINLOCK(cpu_asid_lock);
@@ -155,3 +156,43 @@ void __new_context(struct mm_struct *mm)
set_mm_context(mm, asid);
spin_unlock(&cpu_asid_lock);
}
+
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
+ void *t)
+{
+ unsigned long flags;
+ u32 contextid;
+ struct thread_info *thread = t;
+
+ if (cmd != THREAD_NOTIFY_SWITCH)
+ return NOTIFY_DONE;
+
+ local_irq_save(flags);
+ asm volatile("mrc p15, 0, %0, c15, c0, 1\n"
+ "bic %0, %0, #0xffffff00\n"
+ "orr %0, %0, %1, lsl #8\n"
+ "mcr p15, 0, %0, c15, c0, 1"
+ : "=&r" (contextid)
+ : "r" (task_tgid_vnr(thread->task)));
+ local_irq_restore(flags);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block contextidr_notifier_block = {
+ .notifier_call = contextidr_notifier,
+};
+
+static int __init contextidr_init(void)
+{
+ unsigned int cpu_arch = cpu_architecture();
+
+ if (cpu_arch < CPU_ARCH_ARMv6)
+ return 0;
+
+ thread_register_notifier(&contextidr_notifier_block);
+ return 0;
+}
+arch_initcall(contextidr_init);
+#endif
@@ -111,6 +111,12 @@ ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_ARM_ERRATA_754322
dsb
#endif
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+ mrc p15, 0, r2, c15, c0, 1
+ bic r2, r2, #0xff
+ bfc r1, #8, #24
+ orr r1, r1, r2
+#endif
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
isb
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0