linux/arch/score/include/asm/mmu_context.h
<<
>>
Prefs
   1#ifndef _ASM_SCORE_MMU_CONTEXT_H
   2#define _ASM_SCORE_MMU_CONTEXT_H
   3
   4#include <linux/errno.h>
   5#include <linux/sched.h>
   6#include <linux/slab.h>
   7#include <asm-generic/mm_hooks.h>
   8
   9#include <asm/cacheflush.h>
  10#include <asm/tlbflush.h>
  11#include <asm/scoreregs.h>
  12
  13/*
  14 * For the fast tlb miss handlers, we keep a per cpu array of pointers
  15 * to the current pgd for each processor. Also, the proc. id is stuffed
  16 * into the context register.
  17 */
  18extern unsigned long asid_cache;
  19extern unsigned long pgd_current;
  20
  21#define TLBMISS_HANDLER_SETUP_PGD(pgd) (pgd_current = (unsigned long)(pgd))
  22
  23#define TLBMISS_HANDLER_SETUP()                         \
  24do {                                                    \
  25        write_c0_context(0);                            \
  26        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)       \
  27} while (0)
  28
  29/*
  30 * All unused by hardware upper bits will be considered
  31 * as a software asid extension.
  32 */
  33#define ASID_VERSION_MASK       0xfffff000
  34#define ASID_FIRST_VERSION      0x1000
  35
  36/* PEVN    --------- VPN ---------- --ASID--- -NA- */
  37/* binary: 0000 0000 0000 0000 0000 0000 0001 0000 */
  38/* binary: 0000 0000 0000 0000 0000 1111 1111 0000 */
  39#define ASID_INC        0x10
  40#define ASID_MASK       0xff0
  41
  42static inline void enter_lazy_tlb(struct mm_struct *mm,
  43                                struct task_struct *tsk)
  44{}
  45
  46static inline void
  47get_new_mmu_context(struct mm_struct *mm)
  48{
  49        unsigned long asid = asid_cache + ASID_INC;
  50
  51        if (!(asid & ASID_MASK)) {
  52                local_flush_tlb_all();          /* start new asid cycle */
  53                if (!asid)                      /* fix version if needed */
  54                        asid = ASID_FIRST_VERSION;
  55        }
  56
  57        mm->context = asid;
  58        asid_cache = asid;
  59}
  60
  61/*
  62 * Initialize the context related info for a new mm_struct
  63 * instance.
  64 */
  65static inline int
  66init_new_context(struct task_struct *tsk, struct mm_struct *mm)
  67{
  68        mm->context = 0;
  69        return 0;
  70}
  71
  72static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
  73                        struct task_struct *tsk)
  74{
  75        unsigned long flags;
  76
  77        local_irq_save(flags);
  78        if ((next->context ^ asid_cache) & ASID_VERSION_MASK)
  79                get_new_mmu_context(next);
  80
  81        pevn_set(next->context);
  82        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
  83        local_irq_restore(flags);
  84}
  85
  86/*
  87 * Destroy context related info for an mm_struct that is about
  88 * to be put to rest.
  89 */
  90static inline void destroy_context(struct mm_struct *mm)
  91{}
  92
  93static inline void
  94deactivate_mm(struct task_struct *task, struct mm_struct *mm)
  95{}
  96
  97/*
  98 * After we have set current->mm to a new value, this activates
  99 * the context for the new mm so we see the new mappings.
 100 */
 101static inline void
 102activate_mm(struct mm_struct *prev, struct mm_struct *next)
 103{
 104        unsigned long flags;
 105
 106        local_irq_save(flags);
 107        get_new_mmu_context(next);
 108        pevn_set(next->context);
 109        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 110        local_irq_restore(flags);
 111}
 112
 113#endif /* _ASM_SCORE_MMU_CONTEXT_H */
 114