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