diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2007-02-05 08:47:40 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-08 09:49:24 -0500 |
commit | 9d99df4b10eef130dacb5f772cd589c625b03634 (patch) | |
tree | bf1cea618ef9380cdce9cfea8897da9fb961787b /arch | |
parent | 620879c9e33262426db0ade650be5d7a2046377b (diff) |
[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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/context.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 79e800202424..9da43a0fdcdf 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -19,7 +19,8 @@ unsigned int cpu_last_asid = { 1 << ASID_BITS }; | |||
19 | /* | 19 | /* |
20 | * We fork()ed a process, and we need a new context for the child | 20 | * We fork()ed a process, and we need a new context for the child |
21 | * to run in. We reserve version 0 for initial tasks so we will | 21 | * to run in. We reserve version 0 for initial tasks so we will |
22 | * always allocate an ASID. | 22 | * always allocate an ASID. The ASID 0 is reserved for the TTBR |
23 | * register changing sequence. | ||
23 | */ | 24 | */ |
24 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 25 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
25 | { | 26 | { |
@@ -38,8 +39,15 @@ void __new_context(struct mm_struct *mm) | |||
38 | * If we've used up all our ASIDs, we need | 39 | * If we've used up all our ASIDs, we need |
39 | * to start a new version and flush the TLB. | 40 | * to start a new version and flush the TLB. |
40 | */ | 41 | */ |
41 | if ((asid & ~ASID_MASK) == 0) | 42 | if ((asid & ~ASID_MASK) == 0) { |
43 | asid = ++cpu_last_asid; | ||
44 | /* set the reserved ASID before flushing the TLB */ | ||
45 | asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" | ||
46 | : | ||
47 | : "r" (0)); | ||
48 | isb(); | ||
42 | flush_tlb_all(); | 49 | flush_tlb_all(); |
50 | } | ||
43 | 51 | ||
44 | mm->context.id = asid; | 52 | mm->context.id = asid; |
45 | } | 53 | } |