Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: cache_ls2.c,v 1.5 2016/07/11 16:15:36 matt Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas <matt (at) 3am-software.com>.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: cache_ls2.c,v 1.5 2016/07/11 16:15:36 matt Exp $");
     34 
     35 #include <sys/param.h>
     36 
     37 #include <mips/cache.h>
     38 #include <mips/cache_ls2.h>
     39 #include <mips/locore.h>
     40 
     41 /*
     42  * Cache operations for Loongson2-style caches:
     43  *
     44  *	- 4-way set-associative 32b/l
     45  *	- Write-back
     46  *	- Primary is virtually indexed, physically tagged
     47  *	- Seconadry is physically indexed, physically tagged
     48  */
     49 
     50 #define	round_line(x)		(((x) + 31) & ~31)
     51 #define	trunc_line(x)		((x) & ~31)
     52 
     53 __asm(".set mips3");
     54 
     55 void
     56 ls2_icache_sync_range(register_t va, vsize_t size)
     57 {
     58 	struct mips_cache_info * const mci = &mips_cache_info;
     59 	const vaddr_t eva = round_line(va + size);
     60 
     61 	va = trunc_line(va);
     62 
     63 	if (va + mci->mci_picache_size <= eva) {
     64 		ls2_icache_sync_all();
     65 		return;
     66 	}
     67 
     68 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
     69 		cache_op_ls2_8line(va, CACHEOP_LS2_D_HIT_WB_INV);
     70 		cache_op_ls2_8line(va, CACHEOP_LS2_I_INDEX_INV);
     71 	}
     72 
     73 	for (; va < eva; va += 32) {
     74 		cache_op_ls2_line(va, CACHEOP_LS2_D_HIT_WB_INV);
     75 		cache_op_ls2_line(va, CACHEOP_LS2_I_INDEX_INV);
     76 	}
     77 
     78 	__asm volatile("sync");
     79 }
     80 
     81 void
     82 ls2_icache_sync_range_index(vaddr_t va, vsize_t size)
     83 {
     84 	vaddr_t eva;
     85 	struct mips_cache_info * const mci = &mips_cache_info;
     86 
     87 	/*
     88 	 * Since we're doing Index ops, we expect to not be able
     89 	 * to access the address we've been given.  So, get the
     90 	 * bits that determine the cache index, and make a KSEG0
     91 	 * address out of them.
     92 	 */
     93 
     94 	va = MIPS_PHYS_TO_KSEG0(va & mci->mci_picache_way_mask);
     95 	eva = round_line(va + size);
     96 	va = trunc_line(va);
     97 
     98 	if (va + mci->mci_picache_way_size < eva) {
     99 		va = MIPS_PHYS_TO_KSEG0(0);
    100 		eva = mci->mci_picache_way_size;
    101 	}
    102 
    103 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    104 		cache_op_ls2_8line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    105 		cache_op_ls2_8line(va, CACHEOP_LS2_I_INDEX_INV);
    106 	}
    107 
    108 	for (; va < eva; va += 32) {
    109 		cache_op_ls2_line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    110 		cache_op_ls2_line(va, CACHEOP_LS2_I_INDEX_INV);
    111 	}
    112 
    113 	__asm volatile("sync");
    114 }
    115 
    116 void
    117 ls2_icache_sync_all(void)
    118 {
    119 	struct mips_cache_info * const mci = &mips_cache_info;
    120 	ls2_icache_sync_range_index(0, mci->mci_picache_way_size);
    121 }
    122 
    123 void
    124 ls2_pdcache_inv_range(register_t va, vsize_t size)
    125 {
    126 	const vaddr_t eva = round_line(va + size);
    127 
    128 	va = trunc_line(va);
    129 
    130 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    131 		cache_op_ls2_8line(va, CACHEOP_LS2_D_HIT_INV);
    132 	}
    133 
    134 	for (; va < eva; va += 32) {
    135 		cache_op_ls2_line(va, CACHEOP_LS2_D_HIT_INV);
    136 	}
    137 
    138 	__asm volatile("sync");
    139 }
    140 
    141 void
    142 ls2_pdcache_wbinv_range(register_t va, vsize_t size)
    143 {
    144 	const vaddr_t eva = round_line(va + size);
    145 
    146 	va = trunc_line(va);
    147 
    148 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    149 		cache_op_ls2_8line(va, CACHEOP_LS2_D_HIT_WB_INV);
    150 	}
    151 
    152 	for (; va < eva; va += 32) {
    153 		cache_op_ls2_line(va, CACHEOP_LS2_D_HIT_WB_INV);
    154 	}
    155 
    156 	__asm volatile("sync");
    157 }
    158 
    159 void
    160 ls2_pdcache_wb_range(register_t va, vsize_t size)
    161 {
    162 	/*
    163 	 * Alas, can't writeback without invalidating...
    164 	 */
    165 	ls2_pdcache_wbinv_range(va, size);
    166 }
    167 
    168 void
    169 ls2_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
    170 {
    171 	vaddr_t eva;
    172 	struct mips_cache_info * const mci = &mips_cache_info;
    173 
    174 	/*
    175 	 * Since we're doing Index ops, we expect to not be able
    176 	 * to access the address we've been given.  So, get the
    177 	 * bits that determine the cache index, and make a KSEG0
    178 	 * address out of them.
    179 	 */
    180 	va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask);
    181 
    182 	eva = round_line(va + size);
    183 	va = trunc_line(va);
    184 
    185 	if (va + mci->mci_pdcache_way_size > eva) {
    186 		va = MIPS_PHYS_TO_KSEG0(0);
    187 		eva = mci->mci_pdcache_way_size;
    188 	}
    189 
    190 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    191 		cache_op_ls2_8line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    192 	}
    193 
    194 	for (; va < eva; va += 32) {
    195 		cache_op_ls2_line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    196 	}
    197 
    198 	__asm volatile("sync");
    199 }
    200 
    201 void
    202 ls2_pdcache_wbinv_all(void)
    203 {
    204 	struct mips_cache_info * const mci = &mips_cache_info;
    205 	ls2_pdcache_wbinv_range_index(0, mci->mci_pdcache_way_size);
    206 }
    207 
    208 /*
    209  * Cache operations for secondary caches:
    210  *
    211  *	- Direct-mapped
    212  *	- Write-back
    213  *	- Physically indexed, physically tagged
    214  *
    215  */
    216 
    217 void
    218 ls2_sdcache_inv_range(register_t va, vsize_t size)
    219 {
    220 	const vaddr_t eva = round_line(va + size);
    221 
    222 	va = trunc_line(va);
    223 
    224 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    225 		cache_op_ls2_8line(va, CACHEOP_LS2_D_HIT_INV);
    226 		cache_op_ls2_8line(va, CACHEOP_LS2_S_HIT_INV);
    227 	}
    228 
    229 	for (; va < eva; va += 32) {
    230 		cache_op_ls2_line(va, CACHEOP_LS2_D_HIT_INV);
    231 		cache_op_ls2_line(va, CACHEOP_LS2_S_HIT_INV);
    232 	}
    233 
    234 	__asm volatile("sync");
    235 }
    236 
    237 void
    238 ls2_sdcache_wbinv_range(register_t va, vsize_t size)
    239 {
    240 	const vaddr_t eva = round_line(va + size);
    241 
    242 	va = trunc_line(va);
    243 
    244 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    245 		cache_op_ls2_8line(va, CACHEOP_LS2_D_HIT_WB_INV);
    246 		cache_op_ls2_8line(va, CACHEOP_LS2_S_HIT_WB_INV);
    247 	}
    248 
    249 	for (; va < eva; va += 32) {
    250 		cache_op_ls2_line(va, CACHEOP_LS2_D_HIT_WB_INV);
    251 		cache_op_ls2_line(va, CACHEOP_LS2_S_HIT_WB_INV);
    252 	}
    253 
    254 	__asm volatile("sync");
    255 }
    256 
    257 void
    258 ls2_sdcache_wb_range(register_t va, vsize_t size)
    259 {
    260 	/*
    261 	 * Alas, can't writeback without invalidating...
    262 	 */
    263 	ls2_sdcache_wbinv_range(va, size);
    264 }
    265 
    266 void
    267 ls2_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
    268 {
    269 	vaddr_t eva;
    270 	struct mips_cache_info * const mci = &mips_cache_info;
    271 
    272 	/*
    273 	 * Since we're doing Index ops, we expect to not be able
    274 	 * to access the address we've been given.  So, get the
    275 	 * bits that determine the cache index, and make a KSEG0
    276 	 * address out of them.
    277 	 */
    278 	va = MIPS_PHYS_TO_KSEG0(va & mci->mci_sdcache_way_mask);
    279 
    280 	eva = round_line(va + size);
    281 	va = trunc_line(va);
    282 
    283 	if (va + mci->mci_sdcache_way_size > eva) {
    284 		va = MIPS_PHYS_TO_KSEG0(0);
    285 		eva = va + mci->mci_sdcache_way_size;
    286 	}
    287 
    288 	for (; va + 8 * 32 <= eva; va += 8 * 32) {
    289 		cache_op_ls2_8line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    290 		cache_op_ls2_8line_4way(va, CACHEOP_LS2_S_INDEX_WB_INV);
    291 	}
    292 
    293 	for (; va < eva; va += 32) {
    294 		cache_op_ls2_line_4way(va, CACHEOP_LS2_D_INDEX_WB_INV);
    295 		cache_op_ls2_line_4way(va, CACHEOP_LS2_S_INDEX_WB_INV);
    296 	}
    297 
    298 	__asm volatile("sync");
    299 }
    300 
    301 void
    302 ls2_sdcache_wbinv_all(void)
    303 {
    304 	struct mips_cache_info * const mci = &mips_cache_info;
    305 	ls2_sdcache_wbinv_range_index(0, mci->mci_sdcache_way_size);
    306 }
    307