Add L2-cache writeback/flush operations. Supported 32,128-byte line-size,

else ignored. Cavium Networks also ignored as it has non-standard config
registers.

Obtained from:	NetBSD
Sponsored by:	DARPA, AFRL
This commit is contained in:
Ruslan Bukin 2014-11-20 17:06:41 +00:00
parent d455cc0410
commit 209fe5ef9a
6 changed files with 290 additions and 13 deletions

View file

@ -67,5 +67,15 @@ void mipsNN_pdcache_wbinv_range_index_128(vm_offset_t, vm_size_t);
void mipsNN_pdcache_inv_range_128(vm_offset_t, vm_size_t);
void mipsNN_pdcache_wb_range_128(vm_offset_t, vm_size_t);
#endif
void mipsNN_sdcache_wbinv_all_32(void);
void mipsNN_sdcache_wbinv_range_32(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_wbinv_range_index_32(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_inv_range_32(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_wb_range_32(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_wbinv_all_128(void);
void mipsNN_sdcache_wbinv_range_128(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_wbinv_range_index_128(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_inv_range_128(vm_paddr_t, vm_size_t);
void mipsNN_sdcache_wb_range_128(vm_paddr_t, vm_size_t);
#endif /* _MACHINE_CACHE_MIPSNN_H_ */

View file

@ -67,6 +67,12 @@ struct mips_cpuinfo {
u_int8_t dc_nways;
u_int16_t dc_nsets;
} l1;
struct {
u_int32_t dc_size;
u_int8_t dc_linesize;
u_int8_t dc_nways;
u_int16_t dc_nsets;
} l2;
};
extern struct mips_cpuinfo cpuinfo;

View file

@ -550,6 +550,13 @@
#define MIPS_CONFIG1_EP 0x00000002 /* EJTAG implemented */
#define MIPS_CONFIG1_FP 0x00000001 /* FPU implemented */
#define MIPS_CONFIG2_SA_SHIFT 0 /* Secondary cache associativity */
#define MIPS_CONFIG2_SA_MASK 0xf
#define MIPS_CONFIG2_SL_SHIFT 4 /* Secondary cache line size */
#define MIPS_CONFIG2_SL_MASK 0xf
#define MIPS_CONFIG2_SS_SHIFT 8 /* Secondary cache sets per way */
#define MIPS_CONFIG2_SS_MASK 0xf
#define MIPS_CONFIG4_MMUSIZEEXT 0x000000FF /* bits 7.. 0 MMU Size Extension */
#define MIPS_CONFIG4_MMUEXTDEF 0x0000C000 /* bits 15.14 MMU Extension Definition */
#define MIPS_CONFIG4_MMUEXTDEF_MMUSIZEEXT 0x00004000 /* This values denotes CONFIG4 bits */

View file

@ -260,19 +260,42 @@ mips_config_cache(struct mips_cpuinfo * cpuinfo)
panic("no pdcache_wb_range");
}
/* XXXMIPS: No secondary cache handlers yet */
#ifdef notyet
if (mips_sdcache_size) {
if (!mips_cache_ops.mco_sdcache_wbinv_all)
panic("no sdcache_wbinv_all");
if (!mips_cache_ops.mco_sdcache_wbinv_range)
panic("no sdcache_wbinv_range");
if (!mips_cache_ops.mco_sdcache_wbinv_range_index)
panic("no sdcache_wbinv_range_index");
if (!mips_cache_ops.mco_sdcache_inv_range)
panic("no sdcache_inv_range");
if (!mips_cache_ops.mco_sdcache_wb_range)
panic("no sdcache_wb_range");
/* L2 data cache */
if (!cpuinfo->l2.dc_size) {
/* No L2 found, ignore */
return;
}
switch (cpuinfo->l2.dc_linesize) {
case 32:
mips_cache_ops.mco_sdcache_wbinv_all =
mipsNN_sdcache_wbinv_all_32;
mips_cache_ops.mco_sdcache_wbinv_range =
mipsNN_sdcache_wbinv_range_32;
mips_cache_ops.mco_sdcache_wbinv_range_index =
mipsNN_sdcache_wbinv_range_index_32;
mips_cache_ops.mco_sdcache_inv_range =
mipsNN_sdcache_inv_range_32;
mips_cache_ops.mco_sdcache_wb_range =
mipsNN_sdcache_wb_range_32;
break;
case 128:
mips_cache_ops.mco_sdcache_wbinv_all =
mipsNN_sdcache_wbinv_all_128;
mips_cache_ops.mco_sdcache_wbinv_range =
mipsNN_sdcache_wbinv_range_128;
mips_cache_ops.mco_sdcache_wbinv_range_index =
mipsNN_sdcache_wbinv_range_index_128;
mips_cache_ops.mco_sdcache_inv_range =
mipsNN_sdcache_inv_range_128;
mips_cache_ops.mco_sdcache_wb_range =
mipsNN_sdcache_wb_range_128;
break;
default:
#ifdef CACHE_DEBUG
printf(" no sdcache ops for %d byte lines",
cpuinfo->l2.dc_linesize);
#endif
break;
}
}

View file

@ -52,6 +52,9 @@ __FBSDID("$FreeBSD$");
#define round_line32(x) (((x) + 31) & ~31)
#define trunc_line32(x) ((x) & ~31)
#define round_line128(x) (((x) + 127) & ~127)
#define trunc_line128(x) ((x) & ~127)
#if defined(CPU_NLM)
static __inline void
xlp_sync(void)
@ -100,6 +103,10 @@ static int pdcache_size;
static int pdcache_stride;
static int pdcache_loopcount;
static int pdcache_way_mask;
static int sdcache_size;
static int sdcache_stride;
static int sdcache_loopcount;
static int sdcache_way_mask;
void
mipsNN_cache_init(struct mips_cpuinfo * cpuinfo)
@ -142,6 +149,11 @@ mipsNN_cache_init(struct mips_cpuinfo * cpuinfo)
pdcache_size = cpuinfo->l1.dc_size;
pdcache_way_mask = cpuinfo->l1.dc_nways - 1;
sdcache_stride = cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize;
sdcache_loopcount = cpuinfo->l2.dc_nways;
sdcache_size = cpuinfo->l2.dc_size;
sdcache_way_mask = cpuinfo->l2.dc_nways - 1;
#define CACHE_DEBUG
#ifdef CACHE_DEBUG
printf("Cache info:\n");
@ -636,3 +648,195 @@ mipsNN_pdcache_wb_range_128(vm_offset_t va, vm_size_t size)
}
#endif
void
mipsNN_sdcache_wbinv_all_32(void)
{
vm_offset_t va = MIPS_PHYS_TO_KSEG0(0);
vm_offset_t eva = va + sdcache_size;
while (va < eva) {
cache_r4k_op_32lines_32(va,
CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += (32 * 32);
}
}
void
mipsNN_sdcache_wbinv_range_32(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line32(va + size);
va = trunc_line32(va);
while ((eva - va) >= (32 * 32)) {
cache_r4k_op_32lines_32(va,
CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += (32 * 32);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += 32;
}
}
void
mipsNN_sdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva;
/*
* Since we're doing Index ops, we expect to not be able
* to access the address we've been given. So, get the
* bits that determine the cache index, and make a KSEG0
* address out of them.
*/
va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1));
eva = round_line32(va + size);
va = trunc_line32(va);
while ((eva - va) >= (32 * 32)) {
cache_r4k_op_32lines_32(va,
CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += (32 * 32);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += 32;
}
}
void
mipsNN_sdcache_inv_range_32(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line32(va + size);
va = trunc_line32(va);
while ((eva - va) >= (32 * 32)) {
cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
va += (32 * 32);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
va += 32;
}
}
void
mipsNN_sdcache_wb_range_32(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line32(va + size);
va = trunc_line32(va);
while ((eva - va) >= (32 * 32)) {
cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
va += (32 * 32);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
va += 32;
}
}
void
mipsNN_sdcache_wbinv_all_128(void)
{
vm_offset_t va = MIPS_PHYS_TO_KSEG0(0);
vm_offset_t eva = va + sdcache_size;
while (va < eva) {
cache_r4k_op_32lines_128(va,
CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += (32 * 128);
}
}
void
mipsNN_sdcache_wbinv_range_128(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line128(va + size);
va = trunc_line128(va);
while ((eva - va) >= (32 * 128)) {
cache_r4k_op_32lines_128(va,
CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += (32 * 128);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += 128;
}
}
void
mipsNN_sdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva;
/*
* Since we're doing Index ops, we expect to not be able
* to access the address we've been given. So, get the
* bits that determine the cache index, and make a KSEG0
* address out of them.
*/
va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1));
eva = round_line128(va + size);
va = trunc_line128(va);
while ((eva - va) >= (32 * 128)) {
cache_r4k_op_32lines_128(va,
CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += (32 * 128);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += 128;
}
}
void
mipsNN_sdcache_inv_range_128(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line128(va + size);
va = trunc_line128(va);
while ((eva - va) >= (32 * 128)) {
cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
va += (32 * 128);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
va += 128;
}
}
void
mipsNN_sdcache_wb_range_128(vm_offset_t va, vm_size_t size)
{
vm_offset_t eva = round_line128(va + size);
va = trunc_line128(va);
while ((eva - va) >= (32 * 128)) {
cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
va += (32 * 128);
}
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
va += 128;
}
}

View file

@ -73,6 +73,7 @@ mips_get_identity(struct mips_cpuinfo *cpuinfo)
u_int32_t prid;
u_int32_t cfg0;
u_int32_t cfg1;
u_int32_t cfg2;
#if defined(CPU_CNMIPS)
u_int32_t cfg4;
#endif
@ -186,6 +187,31 @@ mips_get_identity(struct mips_cpuinfo *cpuinfo)
* cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_nways;
cpuinfo->l1.dc_size = cpuinfo->l1.dc_linesize
* cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_nways;
#ifndef CPU_CNMIPS
/* L2 cache */
if (!(cfg1 & MIPS_CONFIG_CM)) {
/* We don't have valid cfg2 register */
return;
}
cfg2 = mips_rd_config2();
tmp = (cfg2 >> MIPS_CONFIG2_SL_SHIFT) & MIPS_CONFIG2_SL_MASK;
if (0 < tmp && tmp <= 7)
cpuinfo->l2.dc_linesize = 2 << tmp;
tmp = (cfg2 >> MIPS_CONFIG2_SS_SHIFT) & MIPS_CONFIG2_SS_MASK;
if (0 <= tmp && tmp <= 7)
cpuinfo->l2.dc_nsets = 64 << tmp;
tmp = (cfg2 >> MIPS_CONFIG2_SA_SHIFT) & MIPS_CONFIG2_SA_MASK;
if (0 <= tmp && tmp <= 7)
cpuinfo->l2.dc_nways = tmp + 1;
cpuinfo->l2.dc_size = cpuinfo->l2.dc_linesize
* cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_nways;
#endif
}
void
@ -355,6 +381,7 @@ static driver_t cpu_driver = {
static int
cpu_probe(device_t dev)
{
return (0);
}