Home | History | Annotate | Line # | Download | only in mips
      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