linux/arch/avr32/include/asm/mmu_context.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004-2006 Atmel Corporation
   3 *
   4 * ASID handling taken from SH implementation.
   5 *   Copyright (C) 1999 Niibe Yutaka
   6 *   Copyright (C) 2003 Paul Mundt
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12#ifndef __ASM_AVR32_MMU_CONTEXT_H
  13#define __ASM_AVR32_MMU_CONTEXT_H
  14
  15#include <asm/tlbflush.h>
  16#include <asm/sysreg.h>
  17#include <asm-generic/mm_hooks.h>
  18
  19/*
  20 * The MMU "context" consists of two things:
  21 *    (a) TLB cache version
  22 *    (b) ASID (Address Space IDentifier)
  23 */
  24#define MMU_CONTEXT_ASID_MASK           0x000000ff
  25#define MMU_CONTEXT_VERSION_MASK        0xffffff00
  26#define MMU_CONTEXT_FIRST_VERSION       0x00000100
  27#define NO_CONTEXT                      0
  28
  29#define MMU_NO_ASID                     0x100
  30
  31/* Virtual Page Number mask */
  32#define MMU_VPN_MASK    0xfffff000
  33
  34/* Cache of MMU context last used */
  35extern unsigned long mmu_context_cache;
  36
  37/*
  38 * Get MMU context if needed
  39 */
  40static inline void
  41get_mmu_context(struct mm_struct *mm)
  42{
  43        unsigned long mc = mmu_context_cache;
  44
  45        if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
  46                /* It's up to date, do nothing */
  47                return;
  48
  49        /* It's old, we need to get new context with new version */
  50        mc = ++mmu_context_cache;
  51        if (!(mc & MMU_CONTEXT_ASID_MASK)) {
  52                /*
  53                 * We have exhausted all ASIDs of this version.
  54                 * Flush the TLB and start new cycle.
  55                 */
  56                flush_tlb_all();
  57                /*
  58                 * Fix version. Note that we avoid version #0
  59                 * to distinguish NO_CONTEXT.
  60                 */
  61                if (!mc)
  62                        mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
  63        }
  64        mm->context = mc;
  65}
  66
  67/*
  68 * Initialize the context related info for a new mm_struct
  69 * instance.
  70 */
  71static inline int init_new_context(struct task_struct *tsk,
  72                                       struct mm_struct *mm)
  73{
  74        mm->context = NO_CONTEXT;
  75        return 0;
  76}
  77
  78/*
  79 * Destroy context related info for an mm_struct that is about
  80 * to be put to rest.
  81 */
  82static inline void destroy_context(struct mm_struct *mm)
  83{
  84        /* Do nothing */
  85}
  86
  87static inline void set_asid(unsigned long asid)
  88{
  89        /* XXX: We're destroying TLBEHI[8:31] */
  90        sysreg_write(TLBEHI, asid & MMU_CONTEXT_ASID_MASK);
  91        cpu_sync_pipeline();
  92}
  93
  94static inline unsigned long get_asid(void)
  95{
  96        unsigned long asid;
  97
  98        asid = sysreg_read(TLBEHI);
  99        return asid & MMU_CONTEXT_ASID_MASK;
 100}
 101
 102static inline void activate_context(struct mm_struct *mm)
 103{
 104        get_mmu_context(mm);
 105        set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
 106}
 107
 108static inline void switch_mm(struct mm_struct *prev,
 109                                 struct mm_struct *next,
 110                                 struct task_struct *tsk)
 111{
 112        if (likely(prev != next)) {
 113                unsigned long __pgdir = (unsigned long)next->pgd;
 114
 115                sysreg_write(PTBR, __pgdir);
 116                activate_context(next);
 117        }
 118}
 119
 120#define deactivate_mm(tsk,mm) do { } while(0)
 121
 122#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
 123
 124static inline void
 125enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 126{
 127}
 128
 129
 130static inline void enable_mmu(void)
 131{
 132        sysreg_write(MMUCR, (SYSREG_BIT(MMUCR_S)
 133                             | SYSREG_BIT(E)
 134                             | SYSREG_BIT(MMUCR_I)));
 135        nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
 136
 137        if (mmu_context_cache == NO_CONTEXT)
 138                mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
 139
 140        set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
 141}
 142
 143static inline void disable_mmu(void)
 144{
 145        sysreg_write(MMUCR, SYSREG_BIT(MMUCR_S));
 146}
 147
 148#endif /* __ASM_AVR32_MMU_CONTEXT_H */
 149