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