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 * Inline assembly cache operations. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (C) 1996 David S. Miller (davem@davemloft.net) 98c2ecf20Sopenharmony_ci * Copyright (C) 1997 - 2002 Ralf Baechle (ralf@gnu.org) 108c2ecf20Sopenharmony_ci * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci#ifndef _ASM_R4KCACHE_H 138c2ecf20Sopenharmony_ci#define _ASM_R4KCACHE_H 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/stringify.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/asm.h> 188c2ecf20Sopenharmony_ci#include <asm/asm-eva.h> 198c2ecf20Sopenharmony_ci#include <asm/cacheops.h> 208c2ecf20Sopenharmony_ci#include <asm/compiler.h> 218c2ecf20Sopenharmony_ci#include <asm/cpu-features.h> 228c2ecf20Sopenharmony_ci#include <asm/cpu-type.h> 238c2ecf20Sopenharmony_ci#include <asm/mipsmtregs.h> 248c2ecf20Sopenharmony_ci#include <asm/mmzone.h> 258c2ecf20Sopenharmony_ci#include <asm/unroll.h> 268c2ecf20Sopenharmony_ci#include <linux/uaccess.h> /* for uaccess_kernel() */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciextern void (*r4k_blast_dcache)(void); 298c2ecf20Sopenharmony_ciextern void (*r4k_blast_icache)(void); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * This macro return a properly sign-extended address suitable as base address 338c2ecf20Sopenharmony_ci * for indexed cache operations. Two issues here: 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * - The MIPS32 and MIPS64 specs permit an implementation to directly derive 368c2ecf20Sopenharmony_ci * the index bits from the virtual address. This breaks with tradition 378c2ecf20Sopenharmony_ci * set by the R4000. To keep unpleasant surprises from happening we pick 388c2ecf20Sopenharmony_ci * an address in KSEG0 / CKSEG0. 398c2ecf20Sopenharmony_ci * - We need a properly sign extended address for 64-bit code. To get away 408c2ecf20Sopenharmony_ci * without ifdefs we let the compiler do it by a type cast. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci#define INDEX_BASE CKSEG0 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define _cache_op(insn, op, addr) \ 458c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 468c2ecf20Sopenharmony_ci " .set push \n" \ 478c2ecf20Sopenharmony_ci " .set noreorder \n" \ 488c2ecf20Sopenharmony_ci " .set "MIPS_ISA_ARCH_LEVEL" \n" \ 498c2ecf20Sopenharmony_ci " " insn("%0", "%1") " \n" \ 508c2ecf20Sopenharmony_ci " .set pop \n" \ 518c2ecf20Sopenharmony_ci : \ 528c2ecf20Sopenharmony_ci : "i" (op), "R" (*(unsigned char *)(addr))) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define cache_op(op, addr) \ 558c2ecf20Sopenharmony_ci _cache_op(kernel_cache, op, addr) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline void flush_icache_line_indexed(unsigned long addr) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci cache_op(Index_Invalidate_I, addr); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic inline void flush_dcache_line_indexed(unsigned long addr) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci cache_op(Index_Writeback_Inv_D, addr); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic inline void flush_scache_line_indexed(unsigned long addr) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci cache_op(Index_Writeback_Inv_SD, addr); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline void flush_icache_line(unsigned long addr) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci switch (boot_cpu_type()) { 758c2ecf20Sopenharmony_ci case CPU_LOONGSON2EF: 768c2ecf20Sopenharmony_ci cache_op(Hit_Invalidate_I_Loongson2, addr); 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci default: 808c2ecf20Sopenharmony_ci cache_op(Hit_Invalidate_I, addr); 818c2ecf20Sopenharmony_ci break; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic inline void flush_dcache_line(unsigned long addr) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci cache_op(Hit_Writeback_Inv_D, addr); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline void invalidate_dcache_line(unsigned long addr) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci cache_op(Hit_Invalidate_D, addr); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic inline void invalidate_scache_line(unsigned long addr) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci cache_op(Hit_Invalidate_SD, addr); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline void flush_scache_line(unsigned long addr) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci cache_op(Hit_Writeback_Inv_SD, addr); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define protected_cache_op(op,addr) \ 1068c2ecf20Sopenharmony_ci({ \ 1078c2ecf20Sopenharmony_ci int __err = 0; \ 1088c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1098c2ecf20Sopenharmony_ci " .set push \n" \ 1108c2ecf20Sopenharmony_ci " .set noreorder \n" \ 1118c2ecf20Sopenharmony_ci " .set "MIPS_ISA_ARCH_LEVEL" \n" \ 1128c2ecf20Sopenharmony_ci "1: cache %1, (%2) \n" \ 1138c2ecf20Sopenharmony_ci "2: .insn \n" \ 1148c2ecf20Sopenharmony_ci " .set pop \n" \ 1158c2ecf20Sopenharmony_ci " .section .fixup,\"ax\" \n" \ 1168c2ecf20Sopenharmony_ci "3: li %0, %3 \n" \ 1178c2ecf20Sopenharmony_ci " j 2b \n" \ 1188c2ecf20Sopenharmony_ci " .previous \n" \ 1198c2ecf20Sopenharmony_ci " .section __ex_table,\"a\" \n" \ 1208c2ecf20Sopenharmony_ci " "STR(PTR)" 1b, 3b \n" \ 1218c2ecf20Sopenharmony_ci " .previous" \ 1228c2ecf20Sopenharmony_ci : "+r" (__err) \ 1238c2ecf20Sopenharmony_ci : "i" (op), "r" (addr), "i" (-EFAULT)); \ 1248c2ecf20Sopenharmony_ci __err; \ 1258c2ecf20Sopenharmony_ci}) 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define protected_cachee_op(op,addr) \ 1298c2ecf20Sopenharmony_ci({ \ 1308c2ecf20Sopenharmony_ci int __err = 0; \ 1318c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 1328c2ecf20Sopenharmony_ci " .set push \n" \ 1338c2ecf20Sopenharmony_ci " .set noreorder \n" \ 1348c2ecf20Sopenharmony_ci " .set mips0 \n" \ 1358c2ecf20Sopenharmony_ci " .set eva \n" \ 1368c2ecf20Sopenharmony_ci "1: cachee %1, (%2) \n" \ 1378c2ecf20Sopenharmony_ci "2: .insn \n" \ 1388c2ecf20Sopenharmony_ci " .set pop \n" \ 1398c2ecf20Sopenharmony_ci " .section .fixup,\"ax\" \n" \ 1408c2ecf20Sopenharmony_ci "3: li %0, %3 \n" \ 1418c2ecf20Sopenharmony_ci " j 2b \n" \ 1428c2ecf20Sopenharmony_ci " .previous \n" \ 1438c2ecf20Sopenharmony_ci " .section __ex_table,\"a\" \n" \ 1448c2ecf20Sopenharmony_ci " "STR(PTR)" 1b, 3b \n" \ 1458c2ecf20Sopenharmony_ci " .previous" \ 1468c2ecf20Sopenharmony_ci : "+r" (__err) \ 1478c2ecf20Sopenharmony_ci : "i" (op), "r" (addr), "i" (-EFAULT)); \ 1488c2ecf20Sopenharmony_ci __err; \ 1498c2ecf20Sopenharmony_ci}) 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* 1528c2ecf20Sopenharmony_ci * The next two are for badland addresses like signal trampolines. 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_cistatic inline int protected_flush_icache_line(unsigned long addr) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci switch (boot_cpu_type()) { 1578c2ecf20Sopenharmony_ci case CPU_LOONGSON2EF: 1588c2ecf20Sopenharmony_ci return protected_cache_op(Hit_Invalidate_I_Loongson2, addr); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci default: 1618c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 1628c2ecf20Sopenharmony_ci return protected_cachee_op(Hit_Invalidate_I, addr); 1638c2ecf20Sopenharmony_ci#else 1648c2ecf20Sopenharmony_ci return protected_cache_op(Hit_Invalidate_I, addr); 1658c2ecf20Sopenharmony_ci#endif 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/* 1708c2ecf20Sopenharmony_ci * R10000 / R12000 hazard - these processors don't support the Hit_Writeback_D 1718c2ecf20Sopenharmony_ci * cacheop so we use Hit_Writeback_Inv_D which is supported by all R4000-style 1728c2ecf20Sopenharmony_ci * caches. We're talking about one cacheline unnecessarily getting invalidated 1738c2ecf20Sopenharmony_ci * here so the penalty isn't overly hard. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_cistatic inline int protected_writeback_dcache_line(unsigned long addr) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 1788c2ecf20Sopenharmony_ci return protected_cachee_op(Hit_Writeback_Inv_D, addr); 1798c2ecf20Sopenharmony_ci#else 1808c2ecf20Sopenharmony_ci return protected_cache_op(Hit_Writeback_Inv_D, addr); 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic inline int protected_writeback_scache_line(unsigned long addr) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci#ifdef CONFIG_EVA 1878c2ecf20Sopenharmony_ci return protected_cachee_op(Hit_Writeback_Inv_SD, addr); 1888c2ecf20Sopenharmony_ci#else 1898c2ecf20Sopenharmony_ci return protected_cache_op(Hit_Writeback_Inv_SD, addr); 1908c2ecf20Sopenharmony_ci#endif 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/* 1948c2ecf20Sopenharmony_ci * This one is RM7000-specific 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_cistatic inline void invalidate_tcache_page(unsigned long addr) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci cache_op(Page_Invalidate_T, addr); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci#define cache_unroll(times, insn, op, addr, lsize) do { \ 2028c2ecf20Sopenharmony_ci int i = 0; \ 2038c2ecf20Sopenharmony_ci unroll(times, _cache_op, insn, op, (addr) + (i++ * (lsize))); \ 2048c2ecf20Sopenharmony_ci} while (0) 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ 2078c2ecf20Sopenharmony_ci#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ 2088c2ecf20Sopenharmony_cistatic inline void extra##blast_##pfx##cache##lsize(void) \ 2098c2ecf20Sopenharmony_ci{ \ 2108c2ecf20Sopenharmony_ci unsigned long start = INDEX_BASE; \ 2118c2ecf20Sopenharmony_ci unsigned long end = start + current_cpu_data.desc.waysize; \ 2128c2ecf20Sopenharmony_ci unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ 2138c2ecf20Sopenharmony_ci unsigned long ws_end = current_cpu_data.desc.ways << \ 2148c2ecf20Sopenharmony_ci current_cpu_data.desc.waybit; \ 2158c2ecf20Sopenharmony_ci unsigned long ws, addr; \ 2168c2ecf20Sopenharmony_ci \ 2178c2ecf20Sopenharmony_ci for (ws = 0; ws < ws_end; ws += ws_inc) \ 2188c2ecf20Sopenharmony_ci for (addr = start; addr < end; addr += lsize * 32) \ 2198c2ecf20Sopenharmony_ci cache_unroll(32, kernel_cache, indexop, \ 2208c2ecf20Sopenharmony_ci addr | ws, lsize); \ 2218c2ecf20Sopenharmony_ci} \ 2228c2ecf20Sopenharmony_ci \ 2238c2ecf20Sopenharmony_cistatic inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \ 2248c2ecf20Sopenharmony_ci{ \ 2258c2ecf20Sopenharmony_ci unsigned long start = page; \ 2268c2ecf20Sopenharmony_ci unsigned long end = page + PAGE_SIZE; \ 2278c2ecf20Sopenharmony_ci \ 2288c2ecf20Sopenharmony_ci do { \ 2298c2ecf20Sopenharmony_ci cache_unroll(32, kernel_cache, hitop, start, lsize); \ 2308c2ecf20Sopenharmony_ci start += lsize * 32; \ 2318c2ecf20Sopenharmony_ci } while (start < end); \ 2328c2ecf20Sopenharmony_ci} \ 2338c2ecf20Sopenharmony_ci \ 2348c2ecf20Sopenharmony_cistatic inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ 2358c2ecf20Sopenharmony_ci{ \ 2368c2ecf20Sopenharmony_ci unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ 2378c2ecf20Sopenharmony_ci unsigned long start = INDEX_BASE + (page & indexmask); \ 2388c2ecf20Sopenharmony_ci unsigned long end = start + PAGE_SIZE; \ 2398c2ecf20Sopenharmony_ci unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ 2408c2ecf20Sopenharmony_ci unsigned long ws_end = current_cpu_data.desc.ways << \ 2418c2ecf20Sopenharmony_ci current_cpu_data.desc.waybit; \ 2428c2ecf20Sopenharmony_ci unsigned long ws, addr; \ 2438c2ecf20Sopenharmony_ci \ 2448c2ecf20Sopenharmony_ci for (ws = 0; ws < ws_end; ws += ws_inc) \ 2458c2ecf20Sopenharmony_ci for (addr = start; addr < end; addr += lsize * 32) \ 2468c2ecf20Sopenharmony_ci cache_unroll(32, kernel_cache, indexop, \ 2478c2ecf20Sopenharmony_ci addr | ws, lsize); \ 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) 2518c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) 2528c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) 2538c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) 2548c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) 2558c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) 2568c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) 2578c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) 2588c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) 2598c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) 2608c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, ) 2618c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, ) 2628c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) 2658c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) 2668c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) 2678c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) 2688c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) 2698c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci#define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \ 2728c2ecf20Sopenharmony_cistatic inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \ 2738c2ecf20Sopenharmony_ci{ \ 2748c2ecf20Sopenharmony_ci unsigned long start = page; \ 2758c2ecf20Sopenharmony_ci unsigned long end = page + PAGE_SIZE; \ 2768c2ecf20Sopenharmony_ci \ 2778c2ecf20Sopenharmony_ci do { \ 2788c2ecf20Sopenharmony_ci cache_unroll(32, user_cache, hitop, start, lsize); \ 2798c2ecf20Sopenharmony_ci start += lsize * 32; \ 2808c2ecf20Sopenharmony_ci } while (start < end); \ 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 2848c2ecf20Sopenharmony_ci 16) 2858c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) 2868c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 2878c2ecf20Sopenharmony_ci 32) 2888c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) 2898c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 2908c2ecf20Sopenharmony_ci 64) 2918c2ecf20Sopenharmony_ci__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* build blast_xxx_range, protected_blast_xxx_range */ 2948c2ecf20Sopenharmony_ci#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ 2958c2ecf20Sopenharmony_cistatic inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \ 2968c2ecf20Sopenharmony_ci unsigned long end) \ 2978c2ecf20Sopenharmony_ci{ \ 2988c2ecf20Sopenharmony_ci unsigned long lsize = cpu_##desc##_line_size(); \ 2998c2ecf20Sopenharmony_ci unsigned long addr = start & ~(lsize - 1); \ 3008c2ecf20Sopenharmony_ci unsigned long aend = (end - 1) & ~(lsize - 1); \ 3018c2ecf20Sopenharmony_ci \ 3028c2ecf20Sopenharmony_ci while (1) { \ 3038c2ecf20Sopenharmony_ci prot##cache_op(hitop, addr); \ 3048c2ecf20Sopenharmony_ci if (addr == aend) \ 3058c2ecf20Sopenharmony_ci break; \ 3068c2ecf20Sopenharmony_ci addr += lsize; \ 3078c2ecf20Sopenharmony_ci } \ 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci#ifndef CONFIG_EVA 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) 3138c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#else 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci#define __BUILD_PROT_BLAST_CACHE_RANGE(pfx, desc, hitop) \ 3188c2ecf20Sopenharmony_cistatic inline void protected_blast_##pfx##cache##_range(unsigned long start,\ 3198c2ecf20Sopenharmony_ci unsigned long end) \ 3208c2ecf20Sopenharmony_ci{ \ 3218c2ecf20Sopenharmony_ci unsigned long lsize = cpu_##desc##_line_size(); \ 3228c2ecf20Sopenharmony_ci unsigned long addr = start & ~(lsize - 1); \ 3238c2ecf20Sopenharmony_ci unsigned long aend = (end - 1) & ~(lsize - 1); \ 3248c2ecf20Sopenharmony_ci \ 3258c2ecf20Sopenharmony_ci if (!uaccess_kernel()) { \ 3268c2ecf20Sopenharmony_ci while (1) { \ 3278c2ecf20Sopenharmony_ci protected_cachee_op(hitop, addr); \ 3288c2ecf20Sopenharmony_ci if (addr == aend) \ 3298c2ecf20Sopenharmony_ci break; \ 3308c2ecf20Sopenharmony_ci addr += lsize; \ 3318c2ecf20Sopenharmony_ci } \ 3328c2ecf20Sopenharmony_ci } else { \ 3338c2ecf20Sopenharmony_ci while (1) { \ 3348c2ecf20Sopenharmony_ci protected_cache_op(hitop, addr); \ 3358c2ecf20Sopenharmony_ci if (addr == aend) \ 3368c2ecf20Sopenharmony_ci break; \ 3378c2ecf20Sopenharmony_ci addr += lsize; \ 3388c2ecf20Sopenharmony_ci } \ 3398c2ecf20Sopenharmony_ci \ 3408c2ecf20Sopenharmony_ci } \ 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci__BUILD_PROT_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D) 3448c2ecf20Sopenharmony_ci__BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I) 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#endif 3478c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) 3488c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ 3498c2ecf20Sopenharmony_ci protected_, loongson2_) 3508c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) 3518c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , ) 3528c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) 3538c2ecf20Sopenharmony_ci/* blast_inv_dcache_range */ 3548c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) 3558c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci/* Currently, this is very specific to Loongson-3 */ 3588c2ecf20Sopenharmony_ci#define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ 3598c2ecf20Sopenharmony_cistatic inline void blast_##pfx##cache##lsize##_node(long node) \ 3608c2ecf20Sopenharmony_ci{ \ 3618c2ecf20Sopenharmony_ci unsigned long start = CAC_BASE | nid_to_addrbase(node); \ 3628c2ecf20Sopenharmony_ci unsigned long end = start + current_cpu_data.desc.waysize; \ 3638c2ecf20Sopenharmony_ci unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ 3648c2ecf20Sopenharmony_ci unsigned long ws_end = current_cpu_data.desc.ways << \ 3658c2ecf20Sopenharmony_ci current_cpu_data.desc.waybit; \ 3668c2ecf20Sopenharmony_ci unsigned long ws, addr; \ 3678c2ecf20Sopenharmony_ci \ 3688c2ecf20Sopenharmony_ci for (ws = 0; ws < ws_end; ws += ws_inc) \ 3698c2ecf20Sopenharmony_ci for (addr = start; addr < end; addr += lsize * 32) \ 3708c2ecf20Sopenharmony_ci cache_unroll(32, kernel_cache, indexop, \ 3718c2ecf20Sopenharmony_ci addr | ws, lsize); \ 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) 3758c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) 3768c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) 3778c2ecf20Sopenharmony_ci__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci#endif /* _ASM_R4KCACHE_H */ 380