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