aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/context.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-07-06 10:43:03 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-09 12:41:10 -0400
commit575320d625d5b5eb115575a1f5e17af456e69577 (patch)
treedc44829a23c7eb3d6da82533853a3c9d304df6d7 /arch/arm/mm/context.c
parent27a5569dc66ecce06cb532542ddcd0b6da8783f6 (diff)
ARM: 7445/1: mm: update CONTEXTIDR register to contain PID of current process
This patch introduces a new Kconfig option which, when enabled, causes the kernel to write the PID of the current task into the PROCID field of the CONTEXTIDR on context switch. This is useful when analysing hardware trace, since writes to this register can be configured to emit an event into the trace stream. The thread notifier for writing the PID is deliberately kept separate from the ASID-writing code so that we can support newer processors using LPAE, where the ASID is stored in TTBR0. As such, the switch_mm code is updated to perform a read-modify-write sequence to ensure that we don't clobber the PID on CPUs using the classic 2-level page tables. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/context.c')
-rw-r--r--arch/arm/mm/context.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 806cc4f63516..119bc52ab93e 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -14,6 +14,7 @@
14#include <linux/percpu.h> 14#include <linux/percpu.h>
15 15
16#include <asm/mmu_context.h> 16#include <asm/mmu_context.h>
17#include <asm/thread_notify.h>
17#include <asm/tlbflush.h> 18#include <asm/tlbflush.h>
18 19
19static DEFINE_RAW_SPINLOCK(cpu_asid_lock); 20static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
@@ -48,6 +49,40 @@ void cpu_set_reserved_ttbr0(void)
48} 49}
49#endif 50#endif
50 51
52#ifdef CONFIG_PID_IN_CONTEXTIDR
53static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
54 void *t)
55{
56 u32 contextidr;
57 pid_t pid;
58 struct thread_info *thread = t;
59
60 if (cmd != THREAD_NOTIFY_SWITCH)
61 return NOTIFY_DONE;
62
63 pid = task_pid_nr(thread->task) << ASID_BITS;
64 asm volatile(
65 " mrc p15, 0, %0, c13, c0, 1\n"
66 " bfi %1, %0, #0, %2\n"
67 " mcr p15, 0, %1, c13, c0, 1\n"
68 : "=r" (contextidr), "+r" (pid)
69 : "I" (ASID_BITS));
70 isb();
71
72 return NOTIFY_OK;
73}
74
75static struct notifier_block contextidr_notifier_block = {
76 .notifier_call = contextidr_notifier,
77};
78
79static int __init contextidr_notifier_init(void)
80{
81 return thread_register_notifier(&contextidr_notifier_block);
82}
83arch_initcall(contextidr_notifier_init);
84#endif
85
51/* 86/*
52 * We fork()ed a process, and we need a new context for the child 87 * We fork()ed a process, and we need a new context for the child
53 * to run in. 88 * to run in.