2005-04-17 02:20:36 +04:00
/*
2006-08-21 22:23:38 +04:00
* linux / arch / arm / mm / context . c
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 2002 - 2003 Deep Blue Solutions Ltd , all rights reserved .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/mm.h>
# include <asm/mmu_context.h>
# include <asm/tlbflush.h>
2007-05-08 23:03:09 +04:00
static DEFINE_SPINLOCK ( cpu_asid_lock ) ;
unsigned int cpu_last_asid = ASID_FIRST_VERSION ;
2005-04-17 02:20:36 +04:00
/*
* 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
2007-02-05 16:47:40 +03:00
* always allocate an ASID . The ASID 0 is reserved for the TTBR
* register changing sequence .
2005-04-17 02:20:36 +04:00
*/
void __init_new_context ( struct task_struct * tsk , struct mm_struct * mm )
{
mm - > context . id = 0 ;
}
void __new_context ( struct mm_struct * mm )
{
unsigned int asid ;
2007-05-08 23:03:09 +04:00
spin_lock ( & cpu_asid_lock ) ;
2005-04-17 02:20:36 +04:00
asid = + + cpu_last_asid ;
if ( asid = = 0 )
2007-05-08 23:03:09 +04:00
asid = cpu_last_asid = ASID_FIRST_VERSION ;
2005-04-17 02:20:36 +04:00
/*
* If we ' ve used up all our ASIDs , we need
* to start a new version and flush the TLB .
*/
2007-05-08 23:03:09 +04:00
if ( unlikely ( ( asid & ~ ASID_MASK ) = = 0 ) ) {
2007-02-05 16:47:40 +03:00
asid = + + cpu_last_asid ;
/* set the reserved ASID before flushing the TLB */
asm ( " mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID \n "
:
: " r " ( 0 ) ) ;
isb ( ) ;
2005-04-17 02:20:36 +04:00
flush_tlb_all ( ) ;
2007-05-09 12:50:23 +04:00
if ( icache_is_vivt_asid_tagged ( ) ) {
asm ( " mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache \n "
" mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB \n "
:
: " r " ( 0 ) ) ;
dsb ( ) ;
}
2007-02-05 16:47:40 +03:00
}
2007-05-08 23:03:09 +04:00
spin_unlock ( & cpu_asid_lock ) ;
2005-04-17 02:20:36 +04:00
2007-05-08 23:03:09 +04:00
mm - > cpu_vm_mask = cpumask_of_cpu ( smp_processor_id ( ) ) ;
2005-04-17 02:20:36 +04:00
mm - > context . id = asid ;
}