Module Name: src Committed By: matt Date: Fri Apr 29 22:19:30 UTC 2011
Modified Files: src/sys/arch/mips/mips: cache_mipsNN.c Log Message: simplify. Don't limit data way size to a page. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/arch/mips/mips/cache_mipsNN.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/mips/cache_mipsNN.c diff -u src/sys/arch/mips/mips/cache_mipsNN.c:1.13 src/sys/arch/mips/mips/cache_mipsNN.c:1.14 --- src/sys/arch/mips/mips/cache_mipsNN.c:1.13 Sun Feb 20 07:45:47 2011 +++ src/sys/arch/mips/mips/cache_mipsNN.c Fri Apr 29 22:19:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cache_mipsNN.c,v 1.13 2011/02/20 07:45:47 matt Exp $ */ +/* $NetBSD: cache_mipsNN.c,v 1.14 2011/04/29 22:19:30 matt Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cache_mipsNN.c,v 1.13 2011/02/20 07:45:47 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cache_mipsNN.c,v 1.14 2011/04/29 22:19:30 matt Exp $"); #include <sys/param.h> @@ -60,7 +60,7 @@ #define SYNC __asm volatile("sync") #endif -#if defined(__mips_o32) +#ifdef __mips_o32 __asm(".set mips32"); #else __asm(".set mips64"); @@ -68,14 +68,12 @@ static int picache_stride; static int picache_loopcount; -static int pdcache_stride; -static int pdcache_loopcount; void mipsNN_cache_init(uint32_t config, uint32_t config1) { struct mips_cache_info * const mci = &mips_cache_info; - int flush_multiple_lines_per_way; + bool flush_multiple_lines_per_way; flush_multiple_lines_per_way = mci->mci_picache_way_size > PAGE_SIZE; if (config & MIPSNN_CFG_VI) { @@ -84,7 +82,7 @@ * multiples of the page size with index ops; we just * need to flush one pages' worth. */ - flush_multiple_lines_per_way = 0; + flush_multiple_lines_per_way = false; } if (flush_multiple_lines_per_way) { @@ -96,22 +94,12 @@ picache_loopcount = mci->mci_picache_ways; } - if (mci->mci_pdcache_way_size < PAGE_SIZE) { - pdcache_stride = mci->mci_pdcache_way_size; - pdcache_loopcount = mci->mci_pdcache_ways; - } else { - pdcache_stride = PAGE_SIZE; - pdcache_loopcount = (mci->mci_pdcache_way_size / PAGE_SIZE) * - mci->mci_pdcache_ways; - } #define CACHE_DEBUG #ifdef CACHE_DEBUG if (config & MIPSNN_CFG_VI) printf(" icache is virtual\n"); printf(" picache_stride = %d\n", picache_stride); printf(" picache_loopcount = %d\n", picache_loopcount); - printf(" pdcache_stride = %d\n", pdcache_stride); - printf(" pdcache_loopcount = %d\n", pdcache_loopcount); #endif } @@ -228,6 +216,15 @@ va = trunc_line16(va); /* + * If we are going to flush more than is in a way, we are flushing + * everything. + */ + if (eva - va >= mci->mci_picache_way_size) { + mipsNN_icache_sync_all_16(); + return; + } + + /* * GCC generates better code in the loops if we reference local * copies of these global variables. */ @@ -238,17 +235,19 @@ while ((eva - va) >= (8 * 16)) { tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) + for (i = 0; i < loopcount; i++, tmpva += stride) { cache_r4k_op_8lines_16(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); + } va += 8 * 16; } while (va < eva) { tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) + for (i = 0; i < loopcount; i++, tmpva += stride) { cache_op_r4k_line(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); + } va += 16; } } @@ -266,14 +265,18 @@ * bits that determine the cache index, and make a KSEG0 * address out of them. */ - if (size >= mci->mci_picache_way_size) { - va = MIPS_KSEG0_START; - eva = va + mci->mci_picache_way_size; - } else { - va = MIPS_PHYS_TO_KSEG0(va & mci->mci_picache_way_mask); + va = MIPS_PHYS_TO_KSEG0(va & mci->mci_picache_way_mask); + + eva = round_line32(va + size); + va = trunc_line32(va); - eva = round_line32(va + size); - va = trunc_line32(va); + /* + * If we are going to flush more than is in a way, we are flushing + * everything. + */ + if (eva - va >= mci->mci_picache_way_size) { + mipsNN_icache_sync_all_32(); + return; } /* @@ -287,17 +290,19 @@ while ((eva - va) >= (8 * 32)) { tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) + for (i = 0; i < loopcount; i++, tmpva += stride) { cache_r4k_op_8lines_32(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); + } va += 8 * 32; } while (va < eva) { tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) + for (i = 0; i < loopcount; i++, tmpva += stride) { cache_op_r4k_line(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); + } va += 32; } } @@ -392,87 +397,115 @@ SYNC; } -void -mipsNN_pdcache_wbinv_range_index_16(vaddr_t va, vsize_t size) +static void +mipsNN_pdcache_wbinv_range_index_16_intern(vaddr_t va, vaddr_t eva) { - struct mips_cache_info * const mci = &mips_cache_info; - vaddr_t eva, tmpva; - int i, stride, loopcount; - /* * Since we're doing Index ops, we expect to not be able * to access the address we've been given. So, get the * bits that determine the cache index, and make a KSEG0 * address out of them. */ - va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask); + va = MIPS_PHYS_TO_KSEG0(va); + eva = MIPS_PHYS_TO_KSEG0(eva); - eva = round_line16(va + size); - va = trunc_line16(va); + for (; (eva - va) >= (8 * 16); va += 8 * 16) { + cache_r4k_op_8lines_16(va, + CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); + } + + for (; va < eva; va += 16) { + cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); + } +} +static void +mipsNN_pdcache_wbinv_range_index_32_intern(vaddr_t va, vaddr_t eva) +{ /* - * GCC generates better code in the loops if we reference local - * copies of these global variables. + * Since we're doing Index ops, we expect to not be able + * to access the address we've been given. So, get the + * bits that determine the cache index, and make a KSEG0 + * address out of them. */ - stride = pdcache_stride; - loopcount = pdcache_loopcount; + va = MIPS_PHYS_TO_KSEG0(va); + eva = MIPS_PHYS_TO_KSEG0(eva); - while ((eva - va) >= (8 * 16)) { - tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) - cache_r4k_op_8lines_16(tmpva, - CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); - va += 8 * 16; + for (; (eva - va) >= (8 * 32); va += 8 * 32) { + cache_r4k_op_8lines_32(va, + CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); } - while (va < eva) { - tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) - cache_op_r4k_line(tmpva, - CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); - va += 16; + for (; va < eva; va += 32) { + cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); } } void -mipsNN_pdcache_wbinv_range_index_32(vaddr_t va, vsize_t size) +mipsNN_pdcache_wbinv_range_index_16(vaddr_t va, vsize_t size) { struct mips_cache_info * const mci = &mips_cache_info; - vaddr_t eva, tmpva; - int i, stride, loopcount; + const vaddr_t way_size = mci->mci_pdcache_way_size; + const vaddr_t way_mask = way_size - 1; + const u_int ways = mci->mci_pdcache_ways; + vaddr_t eva; + + va &= way_mask; + eva = round_line16(va + size); + va = trunc_line16(va); /* - * Since we're doing Index ops, we expect to not be able - * to access the address we've been given. So, get the - * bits that determine the cache index, and make a KSEG0 - * address out of them. + * If we are going to flush more than is in a way, we are flushing + * everything. */ - va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask); + if (eva - va >= way_size) { + mipsNN_pdcache_wbinv_all_16(); + return; + } + /* + * Invalidate each way. If the address range wraps past the end of + * the way, we will be invalidating in two ways but eventually things + * work out since the last way will wrap into the first way. + */ + for (u_int way = 0; way < ways; way++) { + mipsNN_pdcache_wbinv_range_index_16_intern(va, eva); + va += way_size; + eva += way_size; + } +} + +void +mipsNN_pdcache_wbinv_range_index_32(vaddr_t va, vsize_t size) +{ + struct mips_cache_info * const mci = &mips_cache_info; + const vaddr_t way_size = mci->mci_pdcache_way_size; + const vaddr_t way_mask = way_size - 1; + const u_int ways = mci->mci_pdcache_ways; + vaddr_t eva; + + va &= way_mask; eva = round_line32(va + size); va = trunc_line32(va); /* - * GCC generates better code in the loops if we reference local - * copies of these global variables. + * If we are going to flush more than is in a way, we are flushing + * everything. */ - stride = pdcache_stride; - loopcount = pdcache_loopcount; - - while ((eva - va) >= (8 * 32)) { - tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) - cache_r4k_op_8lines_32(tmpva, - CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); - va += 8 * 32; + if (eva - va >= way_size) { + mipsNN_pdcache_wbinv_all_32(); + return; } - while (va < eva) { - tmpva = va; - for (i = 0; i < loopcount; i++, tmpva += stride) - cache_op_r4k_line(tmpva, - CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); - va += 32; + /* + * Invalidate each way. If the address range wraps past the end of + * the way, we will be invalidating in two ways but eventually things + * work out since the last way will wrap into the first way. + */ + for (u_int way = 0; way < ways; way++) { + mipsNN_pdcache_wbinv_range_index_32_intern(va, eva); + va += way_size; + eva += way_size; } }