linux/arch/xtensa/include/asm/tlbflush.h
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2001 - 2013 Tensilica Inc.
   7 */
   8
   9#ifndef _XTENSA_TLBFLUSH_H
  10#define _XTENSA_TLBFLUSH_H
  11
  12#include <linux/stringify.h>
  13#include <asm/processor.h>
  14
  15#define DTLB_WAY_PGD    7
  16
  17#define ITLB_ARF_WAYS   4
  18#define DTLB_ARF_WAYS   4
  19
  20#define ITLB_HIT_BIT    3
  21#define DTLB_HIT_BIT    4
  22
  23#ifndef __ASSEMBLY__
  24
  25/* TLB flushing:
  26 *
  27 *  - flush_tlb_all() flushes all processes TLB entries
  28 *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
  29 *  - flush_tlb_page(mm, vmaddr) flushes a single page
  30 *  - flush_tlb_range(mm, start, end) flushes a range of pages
  31 */
  32
  33void local_flush_tlb_all(void);
  34void local_flush_tlb_mm(struct mm_struct *mm);
  35void local_flush_tlb_page(struct vm_area_struct *vma,
  36                unsigned long page);
  37void local_flush_tlb_range(struct vm_area_struct *vma,
  38                unsigned long start, unsigned long end);
  39void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
  40
  41#ifdef CONFIG_SMP
  42
  43void flush_tlb_all(void);
  44void flush_tlb_mm(struct mm_struct *);
  45void flush_tlb_page(struct vm_area_struct *, unsigned long);
  46void flush_tlb_range(struct vm_area_struct *, unsigned long,
  47                unsigned long);
  48void flush_tlb_kernel_range(unsigned long start, unsigned long end);
  49
  50#else /* !CONFIG_SMP */
  51
  52#define flush_tlb_all()                    local_flush_tlb_all()
  53#define flush_tlb_mm(mm)                   local_flush_tlb_mm(mm)
  54#define flush_tlb_page(vma, page)          local_flush_tlb_page(vma, page)
  55#define flush_tlb_range(vma, vmaddr, end)  local_flush_tlb_range(vma, vmaddr, \
  56                                                                 end)
  57#define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \
  58                                                                        end)
  59
  60#endif /* CONFIG_SMP */
  61
  62/* TLB operations. */
  63
  64static inline unsigned long itlb_probe(unsigned long addr)
  65{
  66        unsigned long tmp;
  67        __asm__ __volatile__("pitlb  %0, %1\n\t" : "=a" (tmp) : "a" (addr));
  68        return tmp;
  69}
  70
  71static inline unsigned long dtlb_probe(unsigned long addr)
  72{
  73        unsigned long tmp;
  74        __asm__ __volatile__("pdtlb  %0, %1\n\t" : "=a" (tmp) : "a" (addr));
  75        return tmp;
  76}
  77
  78static inline void invalidate_itlb_entry (unsigned long probe)
  79{
  80        __asm__ __volatile__("iitlb  %0; isync\n\t" : : "a" (probe));
  81}
  82
  83static inline void invalidate_dtlb_entry (unsigned long probe)
  84{
  85        __asm__ __volatile__("idtlb  %0; dsync\n\t" : : "a" (probe));
  86}
  87
  88/* Use the .._no_isync functions with caution.  Generally, these are
  89 * handy for bulk invalidates followed by a single 'isync'.  The
  90 * caller must follow up with an 'isync', which can be relatively
  91 * expensive on some Xtensa implementations.
  92 */
  93static inline void invalidate_itlb_entry_no_isync (unsigned entry)
  94{
  95        /* Caller must follow up with 'isync'. */
  96        __asm__ __volatile__ ("iitlb  %0\n" : : "a" (entry) );
  97}
  98
  99static inline void invalidate_dtlb_entry_no_isync (unsigned entry)
 100{
 101        /* Caller must follow up with 'isync'. */
 102        __asm__ __volatile__ ("idtlb  %0\n" : : "a" (entry) );
 103}
 104
 105static inline void set_itlbcfg_register (unsigned long val)
 106{
 107        __asm__ __volatile__("wsr  %0, itlbcfg\n\t" "isync\n\t"
 108                             : : "a" (val));
 109}
 110
 111static inline void set_dtlbcfg_register (unsigned long val)
 112{
 113        __asm__ __volatile__("wsr  %0, dtlbcfg; dsync\n\t"
 114                             : : "a" (val));
 115}
 116
 117static inline void set_ptevaddr_register (unsigned long val)
 118{
 119        __asm__ __volatile__(" wsr  %0, ptevaddr; isync\n"
 120                             : : "a" (val));
 121}
 122
 123static inline unsigned long read_ptevaddr_register (void)
 124{
 125        unsigned long tmp;
 126        __asm__ __volatile__("rsr  %0, ptevaddr\n\t" : "=a" (tmp));
 127        return tmp;
 128}
 129
 130static inline void write_dtlb_entry (pte_t entry, int way)
 131{
 132        __asm__ __volatile__("wdtlb  %1, %0; dsync\n\t"
 133                             : : "r" (way), "r" (entry) );
 134}
 135
 136static inline void write_itlb_entry (pte_t entry, int way)
 137{
 138        __asm__ __volatile__("witlb  %1, %0; isync\n\t"
 139                             : : "r" (way), "r" (entry) );
 140}
 141
 142static inline void invalidate_page_directory (void)
 143{
 144        invalidate_dtlb_entry (DTLB_WAY_PGD);
 145        invalidate_dtlb_entry (DTLB_WAY_PGD+1);
 146        invalidate_dtlb_entry (DTLB_WAY_PGD+2);
 147}
 148
 149static inline void invalidate_itlb_mapping (unsigned address)
 150{
 151        unsigned long tlb_entry;
 152        if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0)
 153                invalidate_itlb_entry(tlb_entry);
 154}
 155
 156static inline void invalidate_dtlb_mapping (unsigned address)
 157{
 158        unsigned long tlb_entry;
 159        if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0)
 160                invalidate_dtlb_entry(tlb_entry);
 161}
 162
 163#define check_pgt_cache()       do { } while (0)
 164
 165
 166/*
 167 * DO NOT USE THESE FUNCTIONS.  These instructions aren't part of the Xtensa
 168 * ISA and exist only for test purposes..
 169 * You may find it helpful for MMU debugging, however.
 170 *
 171 * 'at' is the unmodified input register
 172 * 'as' is the output register, as follows (specific to the Linux config):
 173 *
 174 *      as[31..12] contain the virtual address
 175 *      as[11..08] are meaningless
 176 *      as[07..00] contain the asid
 177 */
 178
 179static inline unsigned long read_dtlb_virtual (int way)
 180{
 181        unsigned long tmp;
 182        __asm__ __volatile__("rdtlb0  %0, %1\n\t" : "=a" (tmp), "+a" (way));
 183        return tmp;
 184}
 185
 186static inline unsigned long read_dtlb_translation (int way)
 187{
 188        unsigned long tmp;
 189        __asm__ __volatile__("rdtlb1  %0, %1\n\t" : "=a" (tmp), "+a" (way));
 190        return tmp;
 191}
 192
 193static inline unsigned long read_itlb_virtual (int way)
 194{
 195        unsigned long tmp;
 196        __asm__ __volatile__("ritlb0  %0, %1\n\t" : "=a" (tmp), "+a" (way));
 197        return tmp;
 198}
 199
 200static inline unsigned long read_itlb_translation (int way)
 201{
 202        unsigned long tmp;
 203        __asm__ __volatile__("ritlb1  %0, %1\n\t" : "=a" (tmp), "+a" (way));
 204        return tmp;
 205}
 206
 207#endif  /* __ASSEMBLY__ */
 208#endif  /* _XTENSA_TLBFLUSH_H */
 209