diff options
Diffstat (limited to 'arch/arm/mm/context.c')
| -rw-r--r-- | arch/arm/mm/context.c | 45 | 
1 files changed, 27 insertions, 18 deletions
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index ee9bb363d60..aaa291fc072 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -23,25 +23,37 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm);  #endif  #ifdef CONFIG_ARM_LPAE -#define cpu_set_asid(asid) {						\ -	unsigned long ttbl, ttbh;					\ -	asm volatile(							\ -	"	mrrc	p15, 0, %0, %1, c2		@ read TTBR0\n"	\ -	"	mov	%1, %2, lsl #(48 - 32)		@ set ASID\n"	\ -	"	mcrr	p15, 0, %0, %1, c2		@ set TTBR0\n"	\ -	: "=&r" (ttbl), "=&r" (ttbh)					\ -	: "r" (asid & ~ASID_MASK));					\ +static void cpu_set_reserved_ttbr0(void) +{ +	unsigned long ttbl = __pa(swapper_pg_dir); +	unsigned long ttbh = 0; + +	/* +	 * Set TTBR0 to swapper_pg_dir which contains only global entries. The +	 * ASID is set to 0. +	 */ +	asm volatile( +	"	mcrr	p15, 0, %0, %1, c2		@ set TTBR0\n" +	: +	: "r" (ttbl), "r" (ttbh)); +	isb();  }  #else -#define cpu_set_asid(asid) \ -	asm("	mcr	p15, 0, %0, c13, c0, 1\n" : : "r" (asid)) +static void cpu_set_reserved_ttbr0(void) +{ +	u32 ttb; +	/* Copy TTBR1 into TTBR0 */ +	asm volatile( +	"	mrc	p15, 0, %0, c2, c0, 1		@ read TTBR1\n" +	"	mcr	p15, 0, %0, c2, c0, 0		@ set TTBR0\n" +	: "=r" (ttb)); +	isb(); +}  #endif  /*   * We fork()ed a process, and we need a new context for the child - * to run in.  We reserve version 0 for initial tasks so we will - * always allocate an ASID. The ASID 0 is reserved for the TTBR - * register changing sequence. + * to run in.   */  void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)  { @@ -51,9 +63,7 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)  static void flush_context(void)  { -	/* set the reserved ASID before flushing the TLB */ -	cpu_set_asid(0); -	isb(); +	cpu_set_reserved_ttbr0();  	local_flush_tlb_all();  	if (icache_is_vivt_asid_tagged()) {  		__flush_icache_all(); @@ -114,8 +124,7 @@ static void reset_context(void *info)  	set_mm_context(mm, asid);  	/* set the new ASID */ -	cpu_set_asid(mm->context.id); -	isb(); +	cpu_switch_mm(mm->pgd, mm);  }  #else  |