#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cache_octeon.c,v 1.4 2020/06/06 14:30:44 simonb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <mips/locore.h>
#include <mips/cache.h>
#include <mips/cache_octeon.h>
#define SYNC __asm volatile("sync")
#ifdef OCTEON_ICACHE_DEBUG
int octeon_cache_debug = 0;
#define ICACHE_DEBUG_PRINTF(x) \
if (__predict_false(octeon_cache_debug != 0)) \
printf x;
#else
#define ICACHE_DEBUG_PRINTF(x)
#endif
static inline void
mips_synci(vaddr_t va)
{
__asm __volatile("synci 0(%0)" :: "r"(va));
}
void
octeon_icache_sync_all(void)
{
ICACHE_DEBUG_PRINTF(("%s\n", __func__));
mips_synci(MIPS_KSEG0_START);
SYNC;
}
void
octeon_icache_sync_range(register_t va, vsize_t size)
{
ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxREGISTER", size=%#"PRIxVSIZE"\n",
__func__, va, size));
mips_synci(MIPS_KSEG0_START);
SYNC;
}
void
octeon_icache_sync_range_index(vaddr_t va, vsize_t size)
{
ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxVADDR", size=%#"PRIxVSIZE"\n",
__func__, va, size));
mips_synci(MIPS_KSEG0_START);
SYNC;
}
void
octeon_pdcache_inv_all(void)
{
ICACHE_DEBUG_PRINTF(("%s\n", __func__));
cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D);
SYNC;
}
void
octeon_pdcache_inv_range(register_t va, vsize_t size)
{
ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxREGISTER", size=%#"PRIxVSIZE"\n",
__func__, va, size));
cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D);
SYNC;
}
void
octeon_pdcache_inv_range_index(vaddr_t va, vsize_t size)
{
ICACHE_DEBUG_PRINTF(("%s: va=%#"PRIxVADDR", size=%#"PRIxVSIZE"\n",
__func__, va, size));
cache_octeon_invalidate(CACHEOP_OCTEON_INV_ALL | CACHE_OCTEON_D);
SYNC;
}
#ifdef OCTEON_ICACHE_DEBUG
#define OCTEON_ICACHE_VA_WAY(_va) (((_va) & __BITS(14, 13)) >> 13)
#define OCTEON_ICACHE_VA_INDEX(_va) (((_va) & __BITS(12, 7)) >> 7)
#define OCTEON_ICACHE_VA_WORD(_va) (((_va) & __BITS( 6, 3)) >> 3)
#define OCTEON_ICACHE_TAGLO_R(_taglo) (((_taglo) & __BITS(63, 62)) >> 62)
#define OCTEON_ICACHE_TAGLO_ASID(_taglo) (((_taglo) & __BITS(59, 52)) >> 52)
#define OCTEON_ICACHE_TAGLO_TAG(_taglo) (((_taglo) & __BITS(48, 13)) >> 13)
#define OCTEON_ICACHE_TAGLO_INDEX(_taglo) (((_taglo) & __BITS(12, 7)) >> 7)
#define OCTEON_ICACHE_TAGLO_G(_taglo) (((_taglo) & __BITS( 1, 1)) >> 1)
#define OCTEON_ICACHE_TAGLO_VALID(_taglo) (((_taglo) & __BITS( 0, 0)) >> 0)
#define OCTEON_DCACHE_VA_WAY(_va) (((_va) & __BITS(12, 7)) >> 7)
#define OCTEON_DCACHE_VA_WORD(_va) (((_va) & __BITS( 6, 3)) >> 3)
#define OCTEON_DCACHE_TAGLO_R(_taglo) (((_taglo) & __BITS(63, 62)) >> 62)
#define OCTEON_DCACHE_TAGLO_ASID(_taglo) (((_taglo) & __BITS(59, 52)) >> 52)
#define OCTEON_DCACHE_TAGLO_TAG(_taglo) (((_taglo) & __BITS(48, 7)) >> 7)
#define OCTEON_DCACHE_TAGLO_G(_taglo) (((_taglo) & __BITS( 1, 1)) >> 1)
#define OCTEON_DCACHE_TAGLO_VALID(_taglo) (((_taglo) & __BITS( 0, 0)) >> 0)
#define OCTEON_DCACHE_TAGHI_PTAG(_taghi) (((_taghi) & __BITS(35, 7)) >> 7)
#define OCTEON_DCACHE_TAGHI_VALID(_taghi) (((_taghi) & __BITS( 0, 0)) >> 0)
void octeon_icache_dump_all(void);
void octeon_icache_dump_way(int);
void octeon_icache_dump_index(int, int);
void octeon_icache_dump_va(register_t);
void octeon_dcache_dump_all(void);
void octeon_dcache_dump_way(int);
void octeon_dcache_dump_index(int, int);
void octeon_dcache_dump_va(register_t);
void
octeon_icache_dump_all(void)
{
const int maxway = 2;
int way;
for (way = 0; way < maxway; way++)
octeon_icache_dump_way(way);
}
void
octeon_icache_dump_way(int way)
{
const int maxindex = 64; ;
int index;
for (index = 0; index < maxindex; index++)
octeon_icache_dump_index(way, index);
}
void
octeon_icache_dump_index(int way, int index)
{
const vaddr_t va = (way << 13) | (index << 7);
octeon_icache_dump_va(va);
}
void
octeon_icache_dump_va(register_t va)
{
uint64_t taglo, datalo, datahi;
__asm __volatile (
" .set push \n"
" .set noreorder \n"
" .set arch=octeon \n"
" cache 4, 0(%[va]) \n"
" dmfc0 %[taglo], $28, 0 \n"
" dmfc0 %[datalo], $28, 1 \n"
" dmfc0 %[datahi], $29, 1 \n"
" .set pop \n"
: [taglo] "=r" (taglo),
[datalo] "=r" (datalo),
[datahi] "=r" (datahi)
: [va] "r" (va));
printf("%s: va=%08x "
"(way=%01x, index=%02x""), "
"taglo=%016"PRIx64" "
"(R=%01"PRIx64", asid=%02"PRIx64", tag=%09"PRIx64", index=%02"PRIx64", G=%01"PRIx64", valid=%01"PRIx64"), "
"datahi=%01"PRIx64", datalo=%016"PRIx64""
"\n",
__func__,
(int)((taglo) & __BITS(48, 7)),
(int)OCTEON_ICACHE_VA_WAY(va),
(int)OCTEON_ICACHE_VA_INDEX(va),
taglo,
OCTEON_ICACHE_TAGLO_R(taglo),
OCTEON_ICACHE_TAGLO_ASID(taglo),
OCTEON_ICACHE_TAGLO_TAG(taglo),
OCTEON_ICACHE_TAGLO_INDEX(taglo),
OCTEON_ICACHE_TAGLO_G(taglo),
OCTEON_ICACHE_TAGLO_VALID(taglo),
datahi, datalo);
}
void
octeon_dcache_dump_all(void)
{
const int maxway = 64;
int way;
for (way = 0; way < maxway; way++)
octeon_dcache_dump_way(way);
}
void
octeon_dcache_dump_way(int way)
{
const int maxindex = 1;
int index;
for (index = 0; index < maxindex; index++)
octeon_dcache_dump_index(way, index);
}
void
octeon_dcache_dump_index(int way, int index)
{
const vaddr_t va = (way << 7);
octeon_dcache_dump_va(va);
}
void
octeon_dcache_dump_va(register_t va)
{
uint64_t taglo, taghi, datalo, datahi;
__asm __volatile (
" .set push \n"
" .set noreorder \n"
" .set arch=octeon \n"
" cache 5, 0(%[va]) \n"
" dmfc0 %[taglo], $28, 2 \n"
" dmfc0 %[taghi], $29, 2 \n"
" dmfc0 %[datalo], $28, 3 \n"
" dmfc0 %[datahi], $29, 3 \n"
" .set pop \n"
: [taglo] "=r" (taglo),
[taghi] "=r" (taghi),
[datalo] "=r" (datalo),
[datahi] "=r" (datahi)
: [va] "r" (va));
printf("%s: va=%08x "
"(way=%02x""), "
"taglo=%016"PRIx64" "
"(R=%01"PRIx64", asid=%02"PRIx64", tag=%09"PRIx64", G=%01"PRIx64", valid=%01"PRIx64"), "
"taghi=%016"PRIx64" "
"(ptag=%08"PRIx64", valid=%01"PRIx64"), "
"datahi=%02"PRIx64", datalo=%016"PRIx64""
"\n",
__func__,
(int)((taglo) & __BITS(48, 13)),
(int)OCTEON_DCACHE_VA_WAY(va),
taglo,
OCTEON_DCACHE_TAGLO_R(taglo),
OCTEON_DCACHE_TAGLO_ASID(taglo),
OCTEON_DCACHE_TAGLO_TAG(taglo),
OCTEON_DCACHE_TAGLO_G(taglo),
OCTEON_DCACHE_TAGLO_VALID(taglo),
taghi,
OCTEON_DCACHE_TAGHI_PTAG(taghi),
OCTEON_DCACHE_TAGHI_VALID(taghi),
datahi, datalo);
}
#endif