aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/arm/Kconfig.debug9
-rw-r--r--arch/arm/mm/context.c35
-rw-r--r--arch/arm/mm/proc-v6.S6
-rw-r--r--arch/arm/mm/proc-v7-2level.S5
4 files changed, 55 insertions, 0 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 01a134141216..521e15bc6401 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -369,4 +369,13 @@ config ARM_KPROBES_TEST
369 help 369 help
370 Perform tests of kprobes API and instruction set simulation. 370 Perform tests of kprobes API and instruction set simulation.
371 371
372config PID_IN_CONTEXTIDR
373 bool "Write the current PID to the CONTEXTIDR register"
374 depends on CPU_COPY_V6
375 help
376 Enabling this option causes the kernel to write the current PID to
377 the PROCID field of the CONTEXTIDR register, at the expense of some
378 additional instructions during context switch. Say Y here only if you
379 are planning to use hardware trace tools with this kernel.
380
372endmenu 381endmenu
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.
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 5900cd520e84..86b8b480634f 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -107,6 +107,12 @@ ENTRY(cpu_v6_switch_mm)
107 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB 107 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
108 mcr p15, 0, r2, c7, c10, 4 @ drain write buffer 108 mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
109 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 109 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
110#ifdef CONFIG_PID_IN_CONTEXTIDR
111 mrc p15, 0, r2, c13, c0, 1 @ read current context ID
112 bic r2, r2, #0xff @ extract the PID
113 and r1, r1, #0xff
114 orr r1, r1, r2 @ insert into new context ID
115#endif
110 mcr p15, 0, r1, c13, c0, 1 @ set context ID 116 mcr p15, 0, r1, c13, c0, 1 @ set context ID
111#endif 117#endif
112 mov pc, lr 118 mov pc, lr
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 42ac069c8012..fd045e706390 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -46,6 +46,11 @@ ENTRY(cpu_v7_switch_mm)
46#ifdef CONFIG_ARM_ERRATA_430973 46#ifdef CONFIG_ARM_ERRATA_430973
47 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB 47 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
48#endif 48#endif
49#ifdef CONFIG_PID_IN_CONTEXTIDR
50 mrc p15, 0, r2, c13, c0, 1 @ read current context ID
51 lsr r2, r2, #8 @ extract the PID
52 bfi r1, r2, #8, #24 @ insert into new context ID
53#endif
49#ifdef CONFIG_ARM_ERRATA_754322 54#ifdef CONFIG_ARM_ERRATA_754322
50 dsb 55 dsb
51#endif 56#endif