summaryrefslogtreecommitdiff
path: root/sys/arch
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 /sys/arch
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.
Diffstat (limited to 'sys/arch')
-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
*/