18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 38c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 48c2ecf20Sopenharmony_ci * for more details. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 - 2013 Tensilica Inc. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _XTENSA_TLBFLUSH_H 108c2ecf20Sopenharmony_ci#define _XTENSA_TLBFLUSH_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/stringify.h> 138c2ecf20Sopenharmony_ci#include <asm/processor.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define DTLB_WAY_PGD 7 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define ITLB_ARF_WAYS 4 188c2ecf20Sopenharmony_ci#define DTLB_ARF_WAYS 4 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define ITLB_HIT_BIT 3 218c2ecf20Sopenharmony_ci#define DTLB_HIT_BIT 4 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* TLB flushing: 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * - flush_tlb_all() flushes all processes TLB entries 288c2ecf20Sopenharmony_ci * - flush_tlb_mm(mm) flushes the specified mm context TLB entries 298c2ecf20Sopenharmony_ci * - flush_tlb_page(mm, vmaddr) flushes a single page 308c2ecf20Sopenharmony_ci * - flush_tlb_range(mm, start, end) flushes a range of pages 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid local_flush_tlb_all(void); 348c2ecf20Sopenharmony_civoid local_flush_tlb_mm(struct mm_struct *mm); 358c2ecf20Sopenharmony_civoid local_flush_tlb_page(struct vm_area_struct *vma, 368c2ecf20Sopenharmony_ci unsigned long page); 378c2ecf20Sopenharmony_civoid local_flush_tlb_range(struct vm_area_struct *vma, 388c2ecf20Sopenharmony_ci unsigned long start, unsigned long end); 398c2ecf20Sopenharmony_civoid local_flush_tlb_kernel_range(unsigned long start, unsigned long end); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_civoid flush_tlb_all(void); 448c2ecf20Sopenharmony_civoid flush_tlb_mm(struct mm_struct *); 458c2ecf20Sopenharmony_civoid flush_tlb_page(struct vm_area_struct *, unsigned long); 468c2ecf20Sopenharmony_civoid flush_tlb_range(struct vm_area_struct *, unsigned long, 478c2ecf20Sopenharmony_ci unsigned long); 488c2ecf20Sopenharmony_civoid flush_tlb_kernel_range(unsigned long start, unsigned long end); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#else /* !CONFIG_SMP */ 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define flush_tlb_all() local_flush_tlb_all() 538c2ecf20Sopenharmony_ci#define flush_tlb_mm(mm) local_flush_tlb_mm(mm) 548c2ecf20Sopenharmony_ci#define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) 558c2ecf20Sopenharmony_ci#define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ 568c2ecf20Sopenharmony_ci end) 578c2ecf20Sopenharmony_ci#define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \ 588c2ecf20Sopenharmony_ci end) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* TLB operations. */ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline unsigned long itlb_probe(unsigned long addr) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci unsigned long tmp; 678c2ecf20Sopenharmony_ci __asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); 688c2ecf20Sopenharmony_ci return tmp; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic inline unsigned long dtlb_probe(unsigned long addr) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci unsigned long tmp; 748c2ecf20Sopenharmony_ci __asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr)); 758c2ecf20Sopenharmony_ci return tmp; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic inline void invalidate_itlb_entry (unsigned long probe) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci __asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe)); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline void invalidate_dtlb_entry (unsigned long probe) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci __asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe)); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* Use the .._no_isync functions with caution. Generally, these are 898c2ecf20Sopenharmony_ci * handy for bulk invalidates followed by a single 'isync'. The 908c2ecf20Sopenharmony_ci * caller must follow up with an 'isync', which can be relatively 918c2ecf20Sopenharmony_ci * expensive on some Xtensa implementations. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_cistatic inline void invalidate_itlb_entry_no_isync (unsigned entry) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci /* Caller must follow up with 'isync'. */ 968c2ecf20Sopenharmony_ci __asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) ); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic inline void invalidate_dtlb_entry_no_isync (unsigned entry) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci /* Caller must follow up with 'isync'. */ 1028c2ecf20Sopenharmony_ci __asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) ); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic inline void set_itlbcfg_register (unsigned long val) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci __asm__ __volatile__("wsr %0, itlbcfg\n\t" "isync\n\t" 1088c2ecf20Sopenharmony_ci : : "a" (val)); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic inline void set_dtlbcfg_register (unsigned long val) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci __asm__ __volatile__("wsr %0, dtlbcfg; dsync\n\t" 1148c2ecf20Sopenharmony_ci : : "a" (val)); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic inline void set_ptevaddr_register (unsigned long val) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci __asm__ __volatile__(" wsr %0, ptevaddr; isync\n" 1208c2ecf20Sopenharmony_ci : : "a" (val)); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline unsigned long read_ptevaddr_register (void) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci unsigned long tmp; 1268c2ecf20Sopenharmony_ci __asm__ __volatile__("rsr %0, ptevaddr\n\t" : "=a" (tmp)); 1278c2ecf20Sopenharmony_ci return tmp; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic inline void write_dtlb_entry (pte_t entry, int way) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci __asm__ __volatile__("wdtlb %1, %0; dsync\n\t" 1338c2ecf20Sopenharmony_ci : : "r" (way), "r" (entry) ); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline void write_itlb_entry (pte_t entry, int way) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci __asm__ __volatile__("witlb %1, %0; isync\n\t" 1398c2ecf20Sopenharmony_ci : : "r" (way), "r" (entry) ); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic inline void invalidate_page_directory (void) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci invalidate_dtlb_entry (DTLB_WAY_PGD); 1458c2ecf20Sopenharmony_ci invalidate_dtlb_entry (DTLB_WAY_PGD+1); 1468c2ecf20Sopenharmony_ci invalidate_dtlb_entry (DTLB_WAY_PGD+2); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic inline void invalidate_itlb_mapping (unsigned address) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci unsigned long tlb_entry; 1528c2ecf20Sopenharmony_ci if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0) 1538c2ecf20Sopenharmony_ci invalidate_itlb_entry(tlb_entry); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic inline void invalidate_dtlb_mapping (unsigned address) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci unsigned long tlb_entry; 1598c2ecf20Sopenharmony_ci if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0) 1608c2ecf20Sopenharmony_ci invalidate_dtlb_entry(tlb_entry); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* 1648c2ecf20Sopenharmony_ci * DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa 1658c2ecf20Sopenharmony_ci * ISA and exist only for test purposes.. 1668c2ecf20Sopenharmony_ci * You may find it helpful for MMU debugging, however. 1678c2ecf20Sopenharmony_ci * 1688c2ecf20Sopenharmony_ci * 'at' is the unmodified input register 1698c2ecf20Sopenharmony_ci * 'as' is the output register, as follows (specific to the Linux config): 1708c2ecf20Sopenharmony_ci * 1718c2ecf20Sopenharmony_ci * as[31..12] contain the virtual address 1728c2ecf20Sopenharmony_ci * as[11..08] are meaningless 1738c2ecf20Sopenharmony_ci * as[07..00] contain the asid 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic inline unsigned long read_dtlb_virtual (int way) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci unsigned long tmp; 1798c2ecf20Sopenharmony_ci __asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 1808c2ecf20Sopenharmony_ci return tmp; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic inline unsigned long read_dtlb_translation (int way) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci unsigned long tmp; 1868c2ecf20Sopenharmony_ci __asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 1878c2ecf20Sopenharmony_ci return tmp; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic inline unsigned long read_itlb_virtual (int way) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci unsigned long tmp; 1938c2ecf20Sopenharmony_ci __asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 1948c2ecf20Sopenharmony_ci return tmp; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic inline unsigned long read_itlb_translation (int way) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci unsigned long tmp; 2008c2ecf20Sopenharmony_ci __asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way)); 2018c2ecf20Sopenharmony_ci return tmp; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 2058c2ecf20Sopenharmony_ci#endif /* _XTENSA_TLBFLUSH_H */ 206