1 1.4 simonb /* $NetBSD: cache_octeon.c,v 1.4 2020/06/06 14:30:44 simonb Exp $ */ 2 1.1 hikaru 3 1.1 hikaru #include <sys/cdefs.h> 4 1.4 simonb __KERNEL_RCSID(0, "$NetBSD: cache_octeon.c,v 1.4 2020/06/06 14:30:44 simonb Exp $"); 5 1.1 hikaru 6 1.1 hikaru #include <sys/param.h> 7 1.1 hikaru #include <sys/systm.h> 8 1.1 hikaru 9 1.2 matt #include <mips/locore.h> 10 1.1 hikaru #include <mips/cache.h> 11 1.1 hikaru #include <mips/cache_octeon.h> 12 1.1 hikaru 13 1.1 hikaru #define SYNC __asm volatile("sync") 14 1.1 hikaru 15 1.1 hikaru #ifdef OCTEON_ICACHE_DEBUG 16 1.4 simonb int octeon_cache_debug = 0; 17 1.4 simonb #define ICACHE_DEBUG_PRINTF(x) \ 18 1.4 simonb if (__predict_false(octeon_cache_debug != 0)) \ 19 1.4 simonb printf x; 20 1.4 simonb #else 21 1.4 simonb #define ICACHE_DEBUG_PRINTF(x) /* nothing */ 22 1.1 hikaru #endif 23 1.1 hikaru 24 1.4 simonb 25 1.2 matt static inline void 26 1.2 matt mips_synci(vaddr_t va) 27 1.2 matt { 28 1.4 simonb 29 1.2 matt __asm __volatile("synci 0(%0)" :: "r"(va)); 30 1.2 matt } 31 1.2 matt 32 1.1 hikaru void 33 1.1 hikaru octeon_icache_sync_all(void) 34 1.1 hikaru { 35 1.4 simonb 36 1.4 simonb ICACHE_DEBUG_PRINTF(("%s\n", __func__)); 37 1.2 matt mips_synci(MIPS_KSEG0_START); 38 1.1 hikaru SYNC; 39 1.1 hikaru } 40 1.1 hikaru void 41 1.2 matt octeon_icache_sync_range(register_t va, vsize_t size) 42 1.1 hikaru { 43 1.4 simonb 44 1.4 simonb ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxREGISTER", size=%#"PRIxVSIZE"\n", 45 1.4 simonb __func__, va, size)); 46 1.2 matt mips_synci(MIPS_KSEG0_START); 47 1.1 hikaru SYNC; 48 1.1 hikaru } 49 1.2 matt 50 1.1 hikaru void 51 1.1 hikaru octeon_icache_sync_range_index(vaddr_t va, vsize_t size) 52 1.1 hikaru { 53 1.4 simonb 54 1.4 simonb ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxVADDR", size=%#"PRIxVSIZE"\n", 55 1.4 simonb __func__, va, size)); 56 1.2 matt mips_synci(MIPS_KSEG0_START); 57 1.2 matt SYNC; 58 1.1 hikaru } 59 1.2 matt 60 1.1 hikaru void 61 1.1 hikaru octeon_pdcache_inv_all(void) 62 1.1 hikaru { 63 1.4 simonb 64 1.4 simonb ICACHE_DEBUG_PRINTF(("%s\n", __func__)); 65 1.1 hikaru cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D); 66 1.1 hikaru SYNC; 67 1.1 hikaru } 68 1.2 matt 69 1.1 hikaru void 70 1.2 matt octeon_pdcache_inv_range(register_t va, vsize_t size) 71 1.1 hikaru { 72 1.4 simonb 73 1.4 simonb ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxREGISTER", size=%#"PRIxVSIZE"\n", 74 1.4 simonb __func__, va, size)); 75 1.1 hikaru cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D); 76 1.1 hikaru SYNC; 77 1.1 hikaru } 78 1.2 matt 79 1.1 hikaru void 80 1.1 hikaru octeon_pdcache_inv_range_index(vaddr_t va, vsize_t size) 81 1.1 hikaru { 82 1.4 simonb 83 1.4 simonb ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxVADDR", size=%#"PRIxVSIZE"\n", 84 1.4 simonb __func__, va, size)); 85 1.1 hikaru cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D); 86 1.2 matt SYNC; 87 1.1 hikaru } 88 1.1 hikaru 89 1.1 hikaru /* ---- debug dump */ 90 1.1 hikaru 91 1.1 hikaru #ifdef OCTEON_ICACHE_DEBUG 92 1.1 hikaru 93 1.4 simonb /* XXX does the following even make sense for Octeon II/III? */ 94 1.4 simonb 95 1.1 hikaru /* icache: 16KB, 2ways */ 96 1.1 hikaru 97 1.1 hikaru #define OCTEON_ICACHE_VA_WAY(_va) (((_va) & __BITS(14, 13)) >> 13) 98 1.1 hikaru #define OCTEON_ICACHE_VA_INDEX(_va) (((_va) & __BITS(12, 7)) >> 7) 99 1.1 hikaru #define OCTEON_ICACHE_VA_WORD(_va) (((_va) & __BITS( 6, 3)) >> 3) 100 1.1 hikaru 101 1.1 hikaru #define OCTEON_ICACHE_TAGLO_R(_taglo) (((_taglo) & __BITS(63, 62)) >> 62) 102 1.1 hikaru #define OCTEON_ICACHE_TAGLO_ASID(_taglo) (((_taglo) & __BITS(59, 52)) >> 52) 103 1.1 hikaru #define OCTEON_ICACHE_TAGLO_TAG(_taglo) (((_taglo) & __BITS(48, 13)) >> 13) 104 1.1 hikaru #define OCTEON_ICACHE_TAGLO_INDEX(_taglo) (((_taglo) & __BITS(12, 7)) >> 7) 105 1.1 hikaru #define OCTEON_ICACHE_TAGLO_G(_taglo) (((_taglo) & __BITS( 1, 1)) >> 1) 106 1.1 hikaru #define OCTEON_ICACHE_TAGLO_VALID(_taglo) (((_taglo) & __BITS( 0, 0)) >> 0) 107 1.1 hikaru 108 1.1 hikaru /* dcache: 8KB, 64ways */ 109 1.1 hikaru 110 1.1 hikaru #define OCTEON_DCACHE_VA_WAY(_va) (((_va) & __BITS(12, 7)) >> 7) 111 1.1 hikaru #define OCTEON_DCACHE_VA_WORD(_va) (((_va) & __BITS( 6, 3)) >> 3) 112 1.1 hikaru 113 1.1 hikaru #define OCTEON_DCACHE_TAGLO_R(_taglo) (((_taglo) & __BITS(63, 62)) >> 62) 114 1.1 hikaru #define OCTEON_DCACHE_TAGLO_ASID(_taglo) (((_taglo) & __BITS(59, 52)) >> 52) 115 1.1 hikaru #define OCTEON_DCACHE_TAGLO_TAG(_taglo) (((_taglo) & __BITS(48, 7)) >> 7) 116 1.1 hikaru #define OCTEON_DCACHE_TAGLO_G(_taglo) (((_taglo) & __BITS( 1, 1)) >> 1) 117 1.1 hikaru #define OCTEON_DCACHE_TAGLO_VALID(_taglo) (((_taglo) & __BITS( 0, 0)) >> 0) 118 1.1 hikaru 119 1.1 hikaru #define OCTEON_DCACHE_TAGHI_PTAG(_taghi) (((_taghi) & __BITS(35, 7)) >> 7) 120 1.1 hikaru #define OCTEON_DCACHE_TAGHI_VALID(_taghi) (((_taghi) & __BITS( 0, 0)) >> 0) 121 1.1 hikaru 122 1.1 hikaru void octeon_icache_dump_all(void); 123 1.1 hikaru void octeon_icache_dump_way(int); 124 1.1 hikaru void octeon_icache_dump_index(int, int); 125 1.2 matt void octeon_icache_dump_va(register_t); 126 1.1 hikaru void octeon_dcache_dump_all(void); 127 1.1 hikaru void octeon_dcache_dump_way(int); 128 1.1 hikaru void octeon_dcache_dump_index(int, int); 129 1.2 matt void octeon_dcache_dump_va(register_t); 130 1.1 hikaru 131 1.1 hikaru void 132 1.1 hikaru octeon_icache_dump_all(void) 133 1.1 hikaru { 134 1.1 hikaru /* way = (0 .. 3) */ 135 1.1 hikaru const int maxway = 2; /* XXX 2 << (14 - 13 + 1) == 4? */ 136 1.1 hikaru int way; 137 1.1 hikaru 138 1.1 hikaru for (way = 0; way < maxway; way++) 139 1.1 hikaru octeon_icache_dump_way(way); 140 1.1 hikaru } 141 1.1 hikaru 142 1.1 hikaru void 143 1.1 hikaru octeon_icache_dump_way(int way) 144 1.1 hikaru { 145 1.1 hikaru /* index = (0 .. 127) */ 146 1.1 hikaru const int maxindex = 64; /* XXX 2 << (12 - 7 + 1) == 128? */; 147 1.1 hikaru int index; 148 1.1 hikaru 149 1.1 hikaru for (index = 0; index < maxindex; index++) 150 1.1 hikaru octeon_icache_dump_index(way, index); 151 1.1 hikaru } 152 1.1 hikaru 153 1.1 hikaru void 154 1.1 hikaru octeon_icache_dump_index(int way, int index) 155 1.1 hikaru { 156 1.1 hikaru const vaddr_t va = (way << 13) | (index << 7); 157 1.1 hikaru 158 1.1 hikaru octeon_icache_dump_va(va); 159 1.1 hikaru } 160 1.1 hikaru 161 1.1 hikaru void 162 1.2 matt octeon_icache_dump_va(register_t va) 163 1.1 hikaru { 164 1.1 hikaru uint64_t taglo, datalo, datahi; 165 1.1 hikaru 166 1.1 hikaru /* icache */ 167 1.1 hikaru __asm __volatile ( 168 1.1 hikaru " .set push \n" 169 1.1 hikaru " .set noreorder \n" 170 1.1 hikaru " .set arch=octeon \n" 171 1.1 hikaru " cache 4, 0(%[va]) \n" 172 1.1 hikaru " dmfc0 %[taglo], $28, 0 \n" 173 1.1 hikaru " dmfc0 %[datalo], $28, 1 \n" 174 1.1 hikaru " dmfc0 %[datahi], $29, 1 \n" 175 1.1 hikaru " .set pop \n" 176 1.1 hikaru : [taglo] "=r" (taglo), 177 1.1 hikaru [datalo] "=r" (datalo), 178 1.1 hikaru [datahi] "=r" (datahi) 179 1.1 hikaru : [va] "r" (va)); 180 1.1 hikaru 181 1.1 hikaru printf("%s: va=%08x " 182 1.1 hikaru "(way=%01x, index=%02x"/* ", word=%01d" */"), " 183 1.1 hikaru "taglo=%016"PRIx64" " 184 1.1 hikaru "(R=%01"PRIx64", asid=%02"PRIx64", tag=%09"PRIx64", index=%02"PRIx64", G=%01"PRIx64", valid=%01"PRIx64"), " 185 1.1 hikaru "datahi=%01"PRIx64", datalo=%016"PRIx64"" 186 1.1 hikaru "\n", 187 1.1 hikaru __func__, 188 1.1 hikaru (int)((taglo) & __BITS(48, 7)), /* (int)va */ 189 1.1 hikaru (int)OCTEON_ICACHE_VA_WAY(va), 190 1.1 hikaru (int)OCTEON_ICACHE_VA_INDEX(va), 191 1.1 hikaru /* (int)OCTEON_ICACHE_VA_WORD(va), */ 192 1.1 hikaru taglo, 193 1.1 hikaru OCTEON_ICACHE_TAGLO_R(taglo), 194 1.1 hikaru OCTEON_ICACHE_TAGLO_ASID(taglo), 195 1.1 hikaru OCTEON_ICACHE_TAGLO_TAG(taglo), 196 1.1 hikaru OCTEON_ICACHE_TAGLO_INDEX(taglo), 197 1.1 hikaru OCTEON_ICACHE_TAGLO_G(taglo), 198 1.1 hikaru OCTEON_ICACHE_TAGLO_VALID(taglo), 199 1.1 hikaru datahi, datalo); 200 1.1 hikaru } 201 1.1 hikaru 202 1.1 hikaru void 203 1.1 hikaru octeon_dcache_dump_all(void) 204 1.1 hikaru { 205 1.1 hikaru /* way = (0 .. 63) */ 206 1.1 hikaru const int maxway = 64; 207 1.1 hikaru int way; 208 1.1 hikaru 209 1.1 hikaru for (way = 0; way < maxway; way++) 210 1.1 hikaru octeon_dcache_dump_way(way); 211 1.1 hikaru } 212 1.1 hikaru 213 1.1 hikaru void 214 1.1 hikaru octeon_dcache_dump_way(int way) 215 1.1 hikaru { 216 1.1 hikaru /* index = (0 .. 0) */ 217 1.1 hikaru const int maxindex = 1; 218 1.1 hikaru int index; 219 1.1 hikaru 220 1.1 hikaru for (index = 0; index < maxindex; index++) 221 1.1 hikaru octeon_dcache_dump_index(way, index); 222 1.1 hikaru } 223 1.1 hikaru 224 1.1 hikaru void 225 1.1 hikaru octeon_dcache_dump_index(int way, int index) 226 1.1 hikaru { 227 1.1 hikaru const vaddr_t va = (way << 7); /* no index in dcache */ 228 1.1 hikaru 229 1.1 hikaru octeon_dcache_dump_va(va); 230 1.1 hikaru } 231 1.1 hikaru 232 1.1 hikaru void 233 1.2 matt octeon_dcache_dump_va(register_t va) 234 1.1 hikaru { 235 1.1 hikaru uint64_t taglo, taghi, datalo, datahi; 236 1.1 hikaru 237 1.1 hikaru /* dcache */ 238 1.1 hikaru __asm __volatile ( 239 1.1 hikaru " .set push \n" 240 1.1 hikaru " .set noreorder \n" 241 1.1 hikaru " .set arch=octeon \n" 242 1.1 hikaru " cache 5, 0(%[va]) \n" 243 1.1 hikaru " dmfc0 %[taglo], $28, 2 \n" 244 1.1 hikaru " dmfc0 %[taghi], $29, 2 \n" 245 1.1 hikaru " dmfc0 %[datalo], $28, 3 \n" 246 1.1 hikaru " dmfc0 %[datahi], $29, 3 \n" 247 1.1 hikaru " .set pop \n" 248 1.1 hikaru : [taglo] "=r" (taglo), 249 1.1 hikaru [taghi] "=r" (taghi), 250 1.1 hikaru [datalo] "=r" (datalo), 251 1.1 hikaru [datahi] "=r" (datahi) 252 1.1 hikaru : [va] "r" (va)); 253 1.1 hikaru 254 1.1 hikaru printf("%s: va=%08x " 255 1.1 hikaru "(way=%02x"/* ", word=%01d" */"), " 256 1.1 hikaru "taglo=%016"PRIx64" " 257 1.1 hikaru "(R=%01"PRIx64", asid=%02"PRIx64", tag=%09"PRIx64", G=%01"PRIx64", valid=%01"PRIx64"), " 258 1.1 hikaru "taghi=%016"PRIx64" " 259 1.1 hikaru "(ptag=%08"PRIx64", valid=%01"PRIx64"), " 260 1.1 hikaru "datahi=%02"PRIx64", datalo=%016"PRIx64"" 261 1.1 hikaru "\n", 262 1.1 hikaru __func__, 263 1.1 hikaru (int)((taglo) & __BITS(48, 13)), /* (int)va */ 264 1.1 hikaru (int)OCTEON_DCACHE_VA_WAY(va), 265 1.1 hikaru /* (int)OCTEON_DCACHE_VA_WORD(va), */ 266 1.1 hikaru taglo, 267 1.1 hikaru OCTEON_DCACHE_TAGLO_R(taglo), 268 1.1 hikaru OCTEON_DCACHE_TAGLO_ASID(taglo), 269 1.1 hikaru OCTEON_DCACHE_TAGLO_TAG(taglo), 270 1.1 hikaru OCTEON_DCACHE_TAGLO_G(taglo), 271 1.1 hikaru OCTEON_DCACHE_TAGLO_VALID(taglo), 272 1.1 hikaru taghi, 273 1.1 hikaru OCTEON_DCACHE_TAGHI_PTAG(taghi), 274 1.1 hikaru OCTEON_DCACHE_TAGHI_VALID(taghi), 275 1.1 hikaru datahi, datalo); 276 1.1 hikaru } 277 1.1 hikaru 278 1.1 hikaru #endif /* OCTEON_ICACHE_DEBUG */ 279