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