···4848#ifndef __ASSEMBLY__49495050typedef struct {5151- unsigned long asid; /* 8 bit MMU PID + Generation cycle */5151+ unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */5252} mm_context_t;53535454#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
+28-16
arch/arc/include/asm/mmu_context.h
···3030 * "Fast Context Switch" i.e. no TLB flush on ctxt-switch3131 *3232 * Linux assigns each task a unique ASID. A simple round-robin allocation3333- * of H/w ASID is done using software tracker @asid_cache.3333+ * of H/w ASID is done using software tracker @asid_cpu.3434 * When it reaches max 255, the allocation cycle starts afresh by flushing3535 * the entire TLB and wrapping ASID back to zero.3636 *3737 * A new allocation cycle, post rollover, could potentially reassign an ASID3838 * to a different task. Thus the rule is to refresh the ASID in a new cycle.3939- * The 32 bit @asid_cache (and mm->asid) have 8 bits MMU PID and rest 24 bits3939+ * The 32 bit @asid_cpu (and mm->asid) have 8 bits MMU PID and rest 24 bits4040 * serve as cycle/generation indicator and natural 32 bit unsigned math4141 * automagically increments the generation when lower 8 bits rollover.4242 */···4747#define MM_CTXT_FIRST_CYCLE (MM_CTXT_ASID_MASK + 1)4848#define MM_CTXT_NO_ASID 0UL49495050-#define hw_pid(mm) (mm->context.asid & MM_CTXT_ASID_MASK)5050+#define asid_mm(mm, cpu) mm->context.asid[cpu]5151+#define hw_pid(mm, cpu) (asid_mm(mm, cpu) & MM_CTXT_ASID_MASK)51525252-extern unsigned int asid_cache;5353+DECLARE_PER_CPU(unsigned int, asid_cache);5454+#define asid_cpu(cpu) per_cpu(asid_cache, cpu)53555456/*5557 * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle)···5957 */6058static inline void get_new_mmu_context(struct mm_struct *mm)6159{6060+ const unsigned int cpu = smp_processor_id();6261 unsigned long flags;63626463 local_irq_save(flags);···7471 * first need to destroy the context, setting it to invalid7572 * value.7673 */7777- if (!((mm->context.asid ^ asid_cache) & MM_CTXT_CYCLE_MASK))7474+ if (!((asid_mm(mm, cpu) ^ asid_cpu(cpu)) & MM_CTXT_CYCLE_MASK))7875 goto set_hw;79768077 /* move to new ASID and handle rollover */8181- if (unlikely(!(++asid_cache & MM_CTXT_ASID_MASK))) {7878+ if (unlikely(!(++asid_cpu(cpu) & MM_CTXT_ASID_MASK))) {82798380 flush_tlb_all();8481···8784 * If the container itself wrapped around, set it to a non zero8885 * "generation" to distinguish from no context8986 */9090- if (!asid_cache)9191- asid_cache = MM_CTXT_FIRST_CYCLE;8787+ if (!asid_cpu(cpu))8888+ asid_cpu(cpu) = MM_CTXT_FIRST_CYCLE;9289 }93909491 /* Assign new ASID to tsk */9595- mm->context.asid = asid_cache;9292+ asid_mm(mm, cpu) = asid_cpu(cpu);96939794set_hw:9898- write_aux_reg(ARC_REG_PID, hw_pid(mm) | MMU_ENABLE);9595+ write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE);999610097 local_irq_restore(flags);10198}···107104static inline int108105init_new_context(struct task_struct *tsk, struct mm_struct *mm)109106{110110- mm->context.asid = MM_CTXT_NO_ASID;107107+ int i;108108+109109+ for_each_possible_cpu(i)110110+ asid_mm(mm, i) = MM_CTXT_NO_ASID;111111+111112 return 0;113113+}114114+115115+static inline void destroy_context(struct mm_struct *mm)116116+{117117+ unsigned long flags;118118+119119+ /* Needed to elide CONFIG_DEBUG_PREEMPT warning */120120+ local_irq_save(flags);121121+ asid_mm(mm, smp_processor_id()) = MM_CTXT_NO_ASID;122122+ local_irq_restore(flags);112123}113124114125/* Prepare the MMU for task: setup PID reg with allocated ASID···147130 * only if it was unallocated148131 */149132#define activate_mm(prev, next) switch_mm(prev, next, NULL)150150-151151-static inline void destroy_context(struct mm_struct *mm)152152-{153153- mm->context.asid = MM_CTXT_NO_ASID;154154-}155133156134/* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping157135 * for retiring-mm. However destroy_context( ) still needs to do that because
+8-6
arch/arc/mm/tlb.c
···100100101101102102/* A copy of the ASID from the PID reg is kept in asid_cache */103103-unsigned int asid_cache = MM_CTXT_FIRST_CYCLE;103103+DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE;104104105105/*106106 * Utility Routine to erase a J-TLB entry···274274void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,275275 unsigned long end)276276{277277+ const unsigned int cpu = smp_processor_id();277278 unsigned long flags;278279279280 /* If range @start to @end is more than 32 TLB entries deep,···298297299298 local_irq_save(flags);300299301301- if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) {300300+ if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {302301 while (start < end) {303303- tlb_entry_erase(start | hw_pid(vma->vm_mm));302302+ tlb_entry_erase(start | hw_pid(vma->vm_mm, cpu));304303 start += PAGE_SIZE;305304 }306305 }···347346348347void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)349348{349349+ const unsigned int cpu = smp_processor_id();350350 unsigned long flags;351351352352 /* Note that it is critical that interrupts are DISABLED between···355353 */356354 local_irq_save(flags);357355358358- if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) {359359- tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm));356356+ if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {357357+ tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm, cpu));360358 utlb_invalidate();361359 }362360···402400403401 local_irq_save(flags);404402405405- tlb_paranoid_check(vma->vm_mm->context.asid, address);403403+ tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), address);406404407405 address &= PAGE_MASK;408406