1367b8112SChris Zankel /* 2367b8112SChris Zankel * This file is subject to the terms and conditions of the GNU General Public 3367b8112SChris Zankel * License. See the file "COPYING" in the main directory of this archive 4367b8112SChris Zankel * for more details. 5367b8112SChris Zankel * 6f615136cSMax Filippov * Copyright (C) 2001 - 2013 Tensilica Inc. 7367b8112SChris Zankel */ 8367b8112SChris Zankel 9367b8112SChris Zankel #ifndef _XTENSA_TLBFLUSH_H 10367b8112SChris Zankel #define _XTENSA_TLBFLUSH_H 11367b8112SChris Zankel 12367b8112SChris Zankel #include <linux/stringify.h> 13367b8112SChris Zankel #include <asm/processor.h> 14367b8112SChris Zankel 15367b8112SChris Zankel #define DTLB_WAY_PGD 7 16367b8112SChris Zankel 17367b8112SChris Zankel #define ITLB_ARF_WAYS 4 18367b8112SChris Zankel #define DTLB_ARF_WAYS 4 19367b8112SChris Zankel 20367b8112SChris Zankel #define ITLB_HIT_BIT 3 21367b8112SChris Zankel #define DTLB_HIT_BIT 4 22367b8112SChris Zankel 23367b8112SChris Zankel #ifndef __ASSEMBLY__ 24367b8112SChris Zankel 25367b8112SChris Zankel /* TLB flushing: 26367b8112SChris Zankel * 27367b8112SChris Zankel * - flush_tlb_all() flushes all processes TLB entries 28367b8112SChris Zankel * - flush_tlb_mm(mm) flushes the specified mm context TLB entries 29367b8112SChris Zankel * - flush_tlb_page(mm, vmaddr) flushes a single page 30367b8112SChris Zankel * - flush_tlb_range(mm, start, end) flushes a range of pages 31367b8112SChris Zankel */ 32367b8112SChris Zankel 33f615136cSMax Filippov void local_flush_tlb_all(void); 34f615136cSMax Filippov void local_flush_tlb_mm(struct mm_struct *mm); 35f615136cSMax Filippov void local_flush_tlb_page(struct vm_area_struct *vma, 36f615136cSMax Filippov unsigned long page); 37f615136cSMax Filippov void local_flush_tlb_range(struct vm_area_struct *vma, 38f615136cSMax Filippov unsigned long start, unsigned long end); 39*04c6b3e2SMax Filippov void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); 40367b8112SChris Zankel 41f615136cSMax Filippov #ifdef CONFIG_SMP 42f615136cSMax Filippov 43f615136cSMax Filippov void flush_tlb_all(void); 44f615136cSMax Filippov void flush_tlb_mm(struct mm_struct *); 45f615136cSMax Filippov void flush_tlb_page(struct vm_area_struct *, unsigned long); 46f615136cSMax Filippov void flush_tlb_range(struct vm_area_struct *, unsigned long, 47f615136cSMax Filippov unsigned long); 48*04c6b3e2SMax Filippov void flush_tlb_kernel_range(unsigned long start, unsigned long end); 49f615136cSMax Filippov 50f615136cSMax Filippov #else /* !CONFIG_SMP */ 51f615136cSMax Filippov 52f615136cSMax Filippov #define flush_tlb_all() local_flush_tlb_all() 53f615136cSMax Filippov #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) 54f615136cSMax Filippov #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) 55f615136cSMax Filippov #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ 56f615136cSMax Filippov end) 57*04c6b3e2SMax Filippov #define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \ 58*04c6b3e2SMax Filippov end) 59f615136cSMax Filippov 60f615136cSMax Filippov #endif /* CONFIG_SMP */ 61367b8112SChris Zankel 62367b8112SChris Zankel /* TLB operations. */ 63367b8112SChris Zankel 64367b8112SChris Zankel static inline unsigned long itlb_probe(unsigned long addr) 65367b8112SChris Zankel { 66367b8112SChris Zankel unsigned long tmp; 67367b8112SChris Zankel __asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); 68367b8112SChris Zankel return tmp; 69367b8112SChris Zankel } 70367b8112SChris Zankel 71367b8112SChris Zankel static inline unsigned long dtlb_probe(unsigned long addr) 72367b8112SChris Zankel { 73367b8112SChris Zankel unsigned long tmp; 74367b8112SChris Zankel __asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); 75367b8112SChris Zankel return tmp; 76367b8112SChris Zankel } 77367b8112SChris Zankel 78367b8112SChris Zankel static inline void invalidate_itlb_entry (unsigned long probe) 79367b8112SChris Zankel { 80367b8112SChris Zankel __asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe)); 81367b8112SChris Zankel } 82367b8112SChris Zankel 83367b8112SChris Zankel static inline void invalidate_dtlb_entry (unsigned long probe) 84367b8112SChris Zankel { 85367b8112SChris Zankel __asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe)); 86367b8112SChris Zankel } 87367b8112SChris Zankel 88367b8112SChris Zankel /* Use the .._no_isync functions with caution. Generally, these are 89367b8112SChris Zankel * handy for bulk invalidates followed by a single 'isync'. The 90367b8112SChris Zankel * caller must follow up with an 'isync', which can be relatively 91367b8112SChris Zankel * expensive on some Xtensa implementations. 92367b8112SChris Zankel */ 93367b8112SChris Zankel static inline void invalidate_itlb_entry_no_isync (unsigned entry) 94367b8112SChris Zankel { 95367b8112SChris Zankel /* Caller must follow up with 'isync'. */ 96367b8112SChris Zankel __asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) ); 97367b8112SChris Zankel } 98367b8112SChris Zankel 99367b8112SChris Zankel static inline void invalidate_dtlb_entry_no_isync (unsigned entry) 100367b8112SChris Zankel { 101367b8112SChris Zankel /* Caller must follow up with 'isync'. */ 102367b8112SChris Zankel __asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) ); 103367b8112SChris Zankel } 104367b8112SChris Zankel 105367b8112SChris Zankel static inline void set_itlbcfg_register (unsigned long val) 106367b8112SChris Zankel { 107bc5378fcSMax Filippov __asm__ __volatile__("wsr %0, itlbcfg\n\t" "isync\n\t" 108367b8112SChris Zankel : : "a" (val)); 109367b8112SChris Zankel } 110367b8112SChris Zankel 111367b8112SChris Zankel static inline void set_dtlbcfg_register (unsigned long val) 112367b8112SChris Zankel { 113bc5378fcSMax Filippov __asm__ __volatile__("wsr %0, dtlbcfg; dsync\n\t" 114367b8112SChris Zankel : : "a" (val)); 115367b8112SChris Zankel } 116367b8112SChris Zankel 117367b8112SChris Zankel static inline void set_ptevaddr_register (unsigned long val) 118367b8112SChris Zankel { 119bc5378fcSMax Filippov __asm__ __volatile__(" wsr %0, ptevaddr; isync\n" 120367b8112SChris Zankel : : "a" (val)); 121367b8112SChris Zankel } 122367b8112SChris Zankel 123367b8112SChris Zankel static inline unsigned long read_ptevaddr_register (void) 124367b8112SChris Zankel { 125367b8112SChris Zankel unsigned long tmp; 126bc5378fcSMax Filippov __asm__ __volatile__("rsr %0, ptevaddr\n\t" : "=a" (tmp)); 127367b8112SChris Zankel return tmp; 128367b8112SChris Zankel } 129367b8112SChris Zankel 130367b8112SChris Zankel static inline void write_dtlb_entry (pte_t entry, int way) 131367b8112SChris Zankel { 132367b8112SChris Zankel __asm__ __volatile__("wdtlb %1, %0; dsync\n\t" 133367b8112SChris Zankel : : "r" (way), "r" (entry) ); 134367b8112SChris Zankel } 135367b8112SChris Zankel 136367b8112SChris Zankel static inline void write_itlb_entry (pte_t entry, int way) 137367b8112SChris Zankel { 138367b8112SChris Zankel __asm__ __volatile__("witlb %1, %0; isync\n\t" 139367b8112SChris Zankel : : "r" (way), "r" (entry) ); 140367b8112SChris Zankel } 141367b8112SChris Zankel 142367b8112SChris Zankel static inline void invalidate_page_directory (void) 143367b8112SChris Zankel { 144367b8112SChris Zankel invalidate_dtlb_entry (DTLB_WAY_PGD); 145367b8112SChris Zankel invalidate_dtlb_entry (DTLB_WAY_PGD+1); 146367b8112SChris Zankel invalidate_dtlb_entry (DTLB_WAY_PGD+2); 147367b8112SChris Zankel } 148367b8112SChris Zankel 149367b8112SChris Zankel static inline void invalidate_itlb_mapping (unsigned address) 150367b8112SChris Zankel { 151367b8112SChris Zankel unsigned long tlb_entry; 152367b8112SChris Zankel if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0) 153367b8112SChris Zankel invalidate_itlb_entry(tlb_entry); 154367b8112SChris Zankel } 155367b8112SChris Zankel 156367b8112SChris Zankel static inline void invalidate_dtlb_mapping (unsigned address) 157367b8112SChris Zankel { 158367b8112SChris Zankel unsigned long tlb_entry; 159367b8112SChris Zankel if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0) 160367b8112SChris Zankel invalidate_dtlb_entry(tlb_entry); 161367b8112SChris Zankel } 162367b8112SChris Zankel 163367b8112SChris Zankel #define check_pgt_cache() do { } while (0) 164367b8112SChris Zankel 165367b8112SChris Zankel 166367b8112SChris Zankel /* 167367b8112SChris Zankel * DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa 168367b8112SChris Zankel * ISA and exist only for test purposes.. 169367b8112SChris Zankel * You may find it helpful for MMU debugging, however. 170367b8112SChris Zankel * 171367b8112SChris Zankel * 'at' is the unmodified input register 172367b8112SChris Zankel * 'as' is the output register, as follows (specific to the Linux config): 173367b8112SChris Zankel * 174367b8112SChris Zankel * as[31..12] contain the virtual address 175367b8112SChris Zankel * as[11..08] are meaningless 176367b8112SChris Zankel * as[07..00] contain the asid 177367b8112SChris Zankel */ 178367b8112SChris Zankel 179367b8112SChris Zankel static inline unsigned long read_dtlb_virtual (int way) 180367b8112SChris Zankel { 181367b8112SChris Zankel unsigned long tmp; 182367b8112SChris Zankel __asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 183367b8112SChris Zankel return tmp; 184367b8112SChris Zankel } 185367b8112SChris Zankel 186367b8112SChris Zankel static inline unsigned long read_dtlb_translation (int way) 187367b8112SChris Zankel { 188367b8112SChris Zankel unsigned long tmp; 189367b8112SChris Zankel __asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 190367b8112SChris Zankel return tmp; 191367b8112SChris Zankel } 192367b8112SChris Zankel 193367b8112SChris Zankel static inline unsigned long read_itlb_virtual (int way) 194367b8112SChris Zankel { 195367b8112SChris Zankel unsigned long tmp; 196367b8112SChris Zankel __asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 197367b8112SChris Zankel return tmp; 198367b8112SChris Zankel } 199367b8112SChris Zankel 200367b8112SChris Zankel static inline unsigned long read_itlb_translation (int way) 201367b8112SChris Zankel { 202367b8112SChris Zankel unsigned long tmp; 203367b8112SChris Zankel __asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 204367b8112SChris Zankel return tmp; 205367b8112SChris Zankel } 206367b8112SChris Zankel 207367b8112SChris Zankel #endif /* __ASSEMBLY__ */ 208367b8112SChris Zankel #endif /* _XTENSA_TLBFLUSH_H */ 209