/* $Id: mmu_context.h,v 1.26 1998/07/31 10:42:38 jj Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H /* Derived heavily from Linus's Alpha/AXP ASN code... */ #include #include #include #define NO_CONTEXT 0 #ifndef __ASSEMBLY__ extern unsigned long tlb_context_cache; extern spinlock_t scheduler_lock; extern unsigned long mmu_context_bmap[]; #define CTX_VERSION_SHIFT (PAGE_SHIFT - 3) #define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) #define CTX_FIRST_VERSION ((1UL << CTX_VERSION_SHIFT) + 1UL) extern void get_new_mmu_context(struct mm_struct *mm); /* Initialize/destroy the context related info for a new mm_struct * instance. */ #define init_new_context(mm) ((mm)->context = NO_CONTEXT) #define destroy_context(mm) do { \ if ((mm)->context != NO_CONTEXT) { \ spin_lock(&scheduler_lock); \ if (!(((mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK)) \ clear_bit((mm)->context & ~(CTX_VERSION_MASK), \ mmu_context_bmap); \ spin_unlock(&scheduler_lock); \ (mm)->context = NO_CONTEXT; \ } \ } while (0) extern __inline__ void get_mmu_context(struct task_struct *tsk) { register unsigned long paddr asm("o5"); register unsigned long pgd_cache asm("o4"); struct mm_struct *mm = tsk->mm; flushw_user(); if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD) && !(tsk->flags & PF_EXITING)) { unsigned long ctx = tlb_context_cache; if((mm->context ^ ctx) & CTX_VERSION_MASK) get_new_mmu_context(mm); if(!(mm->cpu_vm_mask & (1UL<context & 0x3ff); __asm__ __volatile__("flush %g6"); spitfire_flush_dtlb_secondary_context(); spitfire_flush_itlb_secondary_context(); __asm__ __volatile__("flush %g6"); } /* Don't worry, set_fs() will restore it... */ /* Sigh, damned include loops... just poke seg directly. */ tsk->tss.ctx = (tsk->tss.current_ds.seg ? (mm->context & 0x3ff) : 0); } else tsk->tss.ctx = 0; spitfire_set_secondary_context(tsk->tss.ctx); __asm__ __volatile__("flush %g6"); paddr = __pa(mm->pgd); if(tsk->tss.flags & SPARC_FLAG_32BIT) pgd_cache = (unsigned long) mm->pgd[0]; else pgd_cache = 0; __asm__ __volatile__(" rdpr %%pstate, %%o3 wrpr %%o3, %2, %%pstate mov %4, %%g4 mov %0, %%g7 stxa %1, [%%g4] %3 wrpr %%o3, 0x0, %%pstate " : /* no outputs */ : "r" (paddr), "r" (pgd_cache), "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_DMMU), "i" (TSB_REG) : "o3"); } /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. */ #define activate_context(tsk) get_mmu_context(tsk) #endif /* !(__ASSEMBLY__) */ #endif /* !(__SPARC64_MMU_CONTEXT_H) */