linux/arch/arm/mm/context.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mm/context.c
   3 *
   4 *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10#include <linux/init.h>
  11#include <linux/sched.h>
  12#include <linux/mm.h>
  13
  14#include <asm/mmu_context.h>
  15#include <asm/tlbflush.h>
  16
  17static DEFINE_SPINLOCK(cpu_asid_lock);
  18unsigned int cpu_last_asid = ASID_FIRST_VERSION;
  19
  20/*
  21 * We fork()ed a process, and we need a new context for the child
  22 * to run in.  We reserve version 0 for initial tasks so we will
  23 * always allocate an ASID. The ASID 0 is reserved for the TTBR
  24 * register changing sequence.
  25 */
  26void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
  27{
  28        mm->context.id = 0;
  29}
  30
  31void __new_context(struct mm_struct *mm)
  32{
  33        unsigned int asid;
  34
  35        spin_lock(&cpu_asid_lock);
  36        asid = ++cpu_last_asid;
  37        if (asid == 0)
  38                asid = cpu_last_asid = ASID_FIRST_VERSION;
  39
  40        /*
  41         * If we've used up all our ASIDs, we need
  42         * to start a new version and flush the TLB.
  43         */
  44        if (unlikely((asid & ~ASID_MASK) == 0)) {
  45                asid = ++cpu_last_asid;
  46                /* set the reserved ASID before flushing the TLB */
  47                asm("mcr        p15, 0, %0, c13, c0, 1  @ set reserved context ID\n"
  48                    :
  49                    : "r" (0));
  50                isb();
  51                flush_tlb_all();
  52                if (icache_is_vivt_asid_tagged()) {
  53                        __flush_icache_all();
  54                        dsb();
  55                }
  56        }
  57        spin_unlock(&cpu_asid_lock);
  58
  59        cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
  60        mm->context.id = asid;
  61}
  62