mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 02:34:01 +08:00
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>
This commit is contained in:
parent
27a5569dc6
commit
575320d625
@ -369,4 +369,13 @@ config ARM_KPROBES_TEST
|
||||
help
|
||||
Perform tests of kprobes API and instruction set simulation.
|
||||
|
||||
config PID_IN_CONTEXTIDR
|
||||
bool "Write the current PID to the CONTEXTIDR register"
|
||||
depends on CPU_COPY_V6
|
||||
help
|
||||
Enabling this option causes the kernel to write the current PID to
|
||||
the PROCID field of the CONTEXTIDR register, at the expense of some
|
||||
additional instructions during context switch. Say Y here only if you
|
||||
are planning to use hardware trace tools with this kernel.
|
||||
|
||||
endmenu
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/percpu.h>
|
||||
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/thread_notify.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
|
||||
@ -48,6 +49,40 @@ void cpu_set_reserved_ttbr0(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PID_IN_CONTEXTIDR
|
||||
static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
|
||||
void *t)
|
||||
{
|
||||
u32 contextidr;
|
||||
pid_t pid;
|
||||
struct thread_info *thread = t;
|
||||
|
||||
if (cmd != THREAD_NOTIFY_SWITCH)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
pid = task_pid_nr(thread->task) << ASID_BITS;
|
||||
asm volatile(
|
||||
" mrc p15, 0, %0, c13, c0, 1\n"
|
||||
" bfi %1, %0, #0, %2\n"
|
||||
" mcr p15, 0, %1, c13, c0, 1\n"
|
||||
: "=r" (contextidr), "+r" (pid)
|
||||
: "I" (ASID_BITS));
|
||||
isb();
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block contextidr_notifier_block = {
|
||||
.notifier_call = contextidr_notifier,
|
||||
};
|
||||
|
||||
static int __init contextidr_notifier_init(void)
|
||||
{
|
||||
return thread_register_notifier(&contextidr_notifier_block);
|
||||
}
|
||||
arch_initcall(contextidr_notifier_init);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We fork()ed a process, and we need a new context for the child
|
||||
* to run in.
|
||||
|
@ -107,6 +107,12 @@ ENTRY(cpu_v6_switch_mm)
|
||||
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
|
||||
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
|
||||
mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
|
||||
#ifdef CONFIG_PID_IN_CONTEXTIDR
|
||||
mrc p15, 0, r2, c13, c0, 1 @ read current context ID
|
||||
bic r2, r2, #0xff @ extract the PID
|
||||
and r1, r1, #0xff
|
||||
orr r1, r1, r2 @ insert into new context ID
|
||||
#endif
|
||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
@ -46,6 +46,11 @@ ENTRY(cpu_v7_switch_mm)
|
||||
#ifdef CONFIG_ARM_ERRATA_430973
|
||||
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
|
||||
#endif
|
||||
#ifdef CONFIG_PID_IN_CONTEXTIDR
|
||||
mrc p15, 0, r2, c13, c0, 1 @ read current context ID
|
||||
lsr r2, r2, #8 @ extract the PID
|
||||
bfi r1, r2, #8, #24 @ insert into new context ID
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_ERRATA_754322
|
||||
dsb
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user