summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2013-09-03 16:48:27 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2013-09-03 16:48:27 +0000
commit1da7a986e0c6178248f485b8416c0e7db0e4d72d (patch)
treea11d28124ee8a5ac8f33f8a9d016c0abdddb752e
parenta0c2e69a5c9a0e4bef456d85d1f8c1bb0fbd87c4 (diff)
Rewrite the ARMv7 cache discovery, as some assumptions in the previous one
were utterly wrong. Fix Log2(), correct one taken from the scheduler code. Tested by rapha@ and Artturi Alm.
-rw-r--r--sys/arch/arm/arm/cpufunc.c206
-rw-r--r--sys/arch/arm/arm/pmap7.c10
2 files changed, 82 insertions, 134 deletions
diff --git a/sys/arch/arm/arm/cpufunc.c b/sys/arch/arm/arm/cpufunc.c
index 9e463016619..557519098e5 100644
--- a/sys/arch/arm/arm/cpufunc.c
+++ b/sys/arch/arm/arm/cpufunc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc.c,v 1.23 2013/05/18 17:48:48 patrick Exp $ */
+/* $OpenBSD: cpufunc.c,v 1.24 2013/09/03 16:48:26 patrick Exp $ */
/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */
/*
@@ -763,108 +763,94 @@ int arm_dcache_l2_nsets;
int arm_dcache_l2_assoc;
int arm_dcache_l2_linesize;
+/*
+ * Base 2 logarithm of an int. returns 0 for 0 (yeye, I know).
+ */
static int
-log2(int size)
+log2(unsigned int i)
{
- int i = 0;
- while (size != 0)
- for (i = 0; size != 0; i++)
- size >>= 1;
- return i;
+ int ret = 0;
+
+ while (i >>= 1)
+ ret++;
+
+ return (ret);
}
void
arm_get_cachetype_cp15v7(void)
{
- extern int pmap_cachevivt;
uint32_t cachereg;
uint32_t cache_level_id;
- uint32_t line_size, ways, sets, size;
- uint32_t sel;
- uint32_t ctr;
-
- __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
- : "=r" (ctr) :);
-
- switch ((ctr >> 14) & 3) {
- case 2:
- pmap_cachevivt = 0;
- #if 0
- pmap_alias_dist = 0x4000;
- pmap_alias_bits = 0x3000;
- #endif
- break;
- case 3:
- pmap_cachevivt = 0;
- break;
- default:
- break;
- }
+ uint32_t sets;
+ uint32_t sel, level;
+ /* CLIDR - Cache Level ID Register */
__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
: "=r" (cache_level_id) :);
-
- /* dcache L1 */
- sel = 0;
- __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
- :: "r" (sel));
cpu_drain_writebuf();
- __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
- : "=r" (cachereg) :);
- line_size = 1 << ((cachereg & 7)+4);
- ways = ((0x00000ff8 & cachereg) >> 3) + 1;
- sets = ((0x0ffff000 & cachereg) >> 13) + 1;
- arm_pcache_unified = (cache_level_id & 0x7) == 2;
- arm_pdcache_line_size = line_size;
- arm_pdcache_ways = ways;
- size = line_size * ways * sets;
- arm_pdcache_size = size;
-
- switch (cachereg & 0xc0000000) {
- case 0x00000000:
- arm_pcache_type = 0;
- break;
- case 0x40000000:
- case 0xc0000000:
- arm_pcache_type = CPU_CT_CTYPE_WB1;
- break;
- case 0x80000000:
- arm_pcache_type = CPU_CT_CTYPE_WT;
- break;
- }
- /* icache L1 */
- sel = 1;
- __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
- :: "r" (sel));
- cpu_drain_writebuf();
- __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
- : "=r" (cachereg) :);
- line_size = 1 << ((cachereg & 7)+4);
- ways = ((0x00000ff8 & cachereg) >> 3) + 1;
- sets = ((0x0ffff000 & cachereg) >> 13) + 1;
- arm_picache_line_size = line_size;
- size = line_size * ways * sets;
- arm_picache_size = size;
- arm_picache_ways = ways;
+ /* L1 Cache available. */
+ level = 0;
+ if (cache_level_id & (0x7 << level)) {
+ /* Unified cache. */
+ if (cache_level_id & (0x4 << level))
+ arm_pcache_unified = 1;
+
+ /* Unified or data cache separate. */
+ if (cache_level_id & (0x4 << level) ||
+ cache_level_id & (0x2 << level)) {
+ sel = level << 1 | 0 << 0; /* L1 | unified/data cache */
+ /* CSSELR - Cache Size Selection Register */
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ :: "r" (sel));
+ cpu_drain_writebuf();
+ /* CCSIDR - Cache Size Identification Register */
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (cachereg) :);
+ cpu_drain_writebuf();
+ sets = ((cachereg >> 13) & 0x7fff) + 1;
+ arm_pdcache_line_size = 1 << ((cachereg & 0x7) + 4);
+ arm_pdcache_ways = ((cachereg >> 3) & 0x3ff) + 1;
+ arm_pdcache_size = arm_pdcache_line_size * arm_pdcache_ways * sets;
+ switch (cachereg & 0xc0000000) {
+ case 0x00000000:
+ arm_pcache_type = 0;
+ break;
+ case 0x40000000:
+ case 0xc0000000:
+ arm_pcache_type = CPU_CT_CTYPE_WB1;
+ break;
+ case 0x80000000:
+ arm_pcache_type = CPU_CT_CTYPE_WT;
+ break;
+ }
+ }
- arm_dcache_align = arm_pdcache_line_size;
+ /* Instruction cache separate. */
+ if (cache_level_id & (0x1 << level)) {
+ sel = level << 1 | 1 << 0; /* L1 | instruction cache */
+ /* CSSELR - Cache Size Selection Register */
+ __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
+ :: "r" (sel));
+ cpu_drain_writebuf();
+ /* CCSIDR - Cache Size Identification Register */
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
+ : "=r" (cachereg) :);
+ cpu_drain_writebuf();
+ sets = ((cachereg >> 13) & 0x7fff) + 1;
+ arm_picache_line_size = 1 << ((cachereg & 0x7) + 4);
+ arm_picache_ways = ((cachereg >> 3) & 0x3ff) + 1;
+ arm_picache_size = arm_picache_line_size * arm_picache_ways * sets;
+ }
+ }
+ arm_dcache_align = arm_pdcache_line_size;
arm_dcache_align_mask = arm_dcache_align - 1;
- /* ucache L2 */
- sel = 1;
- __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
- :: "r" (sel));
- cpu_drain_writebuf();
- __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
- : "=r" (cachereg) :);
- line_size = 1 << ((cachereg & 7)+4);
- ways = ((0x00000ff8 & cachereg) >> 3) + 1;
- sets = ((0x0ffff000 & cachereg) >> 13) + 1;
- arm_dcache_l2_nsets = log2(sets);
- arm_dcache_l2_assoc = log2(ways);
- arm_dcache_l2_linesize = log2(line_size);
+ arm_dcache_l2_nsets = arm_pdcache_size/arm_pdcache_ways/arm_pdcache_line_size;
+ arm_dcache_l2_assoc = log2(arm_pdcache_ways);
+ arm_dcache_l2_linesize = log2(arm_pdcache_line_size);
}
/*
@@ -882,54 +868,23 @@ void
armv7_dcache_wbinv_all()
{
int sets, ways, lvl;
- int nincr, nsets, nways;
+ int nsets, nways;
uint32_t wayincr, setincr;
uint32_t wayval, setval;
uint32_t word;
- nsets = arm_picache_size/arm_picache_ways/arm_picache_line_size;
- nways = arm_picache_ways;
- nincr = arm_picache_line_size;
+ nsets = arm_dcache_l2_nsets;
+ nways = arm_pdcache_ways;
- wayincr = 1 << (32 - arm_picache_ways);
- setincr = arm_picache_line_size;
+ setincr = armv7_dcache_sets_inc;
+ wayincr = armv7_dcache_index_inc;
#if 0
- printf("l1 nsets %d nways %d nincr %d wayincr %x setincr %x\n",
- nsets, nways, nincr, wayincr, setincr);
+ printf("l1 nsets %d nways %d wayincr %x setincr %x\n",
+ nsets, nways, wayincr, setincr);
#endif
-
- lvl = 0; /* L1 */
- setval = 0;
- for (sets = 0; sets < nsets; sets++) {
- wayval = 0;
- for (ways = 0; ways < nways; ways++) {
- word = wayval | setval | lvl;
-
- /* Clean D cache SE with Set/Index */
- __asm __volatile("mcr p15, 0, %0, c7, c10, 2"
- : : "r" (word));
- wayval += nincr;
- }
- setval += setincr;
- }
- /* drain the write buffer */
- cpu_drain_writebuf();
-
- /* L2 */
- nsets = 1 << arm_dcache_l2_nsets;
- nways = 1 << arm_dcache_l2_assoc;
- nincr = 1 << arm_dcache_l2_linesize;
- wayincr = 1 << (32 - arm_picache_ways);
- setincr = arm_picache_line_size;
-
-#if 0
- printf("l2 nsets %d nways %d nincr %d wayincr %x setincr %x\n",
- nsets, nways, nincr, wayincr, setincr);
-#endif
-
- lvl = 1 << 1; /* L2 */
+ lvl = 0; /* L1 */
setval = 0;
for (sets = 0; sets < nsets; sets++) {
wayval = 0;
@@ -939,13 +894,14 @@ armv7_dcache_wbinv_all()
/* Clean D cache SE with Set/Index */
__asm __volatile("mcr p15, 0, %0, c7, c10, 2"
: : "r" (word));
- wayval += nincr;
+ wayval += wayincr;
}
setval += setincr;
}
/* drain the write buffer */
cpu_drain_writebuf();
+ /* L2 cache flushing removed. Our current L2 caches are separate. */
}
#endif /* CPU_ARMv7 */
diff --git a/sys/arch/arm/arm/pmap7.c b/sys/arch/arm/arm/pmap7.c
index 1cc89fd7c14..b7d23178f6c 100644
--- a/sys/arch/arm/arm/pmap7.c
+++ b/sys/arch/arm/arm/pmap7.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap7.c,v 1.8 2013/06/09 12:53:42 miod Exp $ */
+/* $OpenBSD: pmap7.c,v 1.9 2013/09/03 16:48:26 patrick Exp $ */
/* $NetBSD: pmap.c,v 1.147 2004/01/18 13:03:50 scw Exp $ */
/*
@@ -280,14 +280,6 @@ extern caddr_t msgbufaddr;
boolean_t pmap_initialized;
/*
- * Flag to indicate whether the data cache is virtually indexed and
- * virtually tagged. A value of zero implies physically indexed and
- * physically tagged data cache; there is no support for VIPT data
- * cache yet.
- */
-boolean_t pmap_cachevivt = FALSE;
-
-/*
* Misc. locking data structures
*/