|
From: <sv...@va...> - 2012-11-02 22:01:08
|
florian 2012-11-02 22:00:59 +0000 (Fri, 02 Nov 2012)
New Revision: 13100
Log:
s390: Autodetect cache info. These are the final bits to fix BZ 275800.
Modified files:
trunk/NEWS
trunk/README.s390
trunk/coregrind/m_cache.c
Modified: trunk/NEWS (+1 -0)
===================================================================
--- trunk/NEWS 2012-11-02 21:36:39 +00:00 (rev 13099)
+++ trunk/NEWS 2012-11-02 22:00:59 +00:00 (rev 13100)
@@ -33,6 +33,7 @@
252955 [390] Impossible to compile with ccache
274695 [390] s390x: Support "compare to/from logical" instructions (z196)
275800 [390] s390x: Add support for the ecag instruction (part 1)
+275800 [390] s390x: Autodetect cache info (part 2)
305948 [390] ppc64: code generation for ShlD64 / ShrD64 asserts
306054 [390] s390x: Condition code computation for convert-to-int/logical
307155 [390] filter_gdb should filter out syscall-template.S T_PSEUDO
Modified: trunk/coregrind/m_cache.c (+104 -2)
===================================================================
--- trunk/coregrind/m_cache.c 2012-11-02 21:36:39 +00:00 (rev 13099)
+++ trunk/coregrind/m_cache.c 2012-11-02 22:00:59 +00:00 (rev 13100)
@@ -551,12 +551,114 @@
#elif defined(VGA_s390x)
+static ULong
+ecag(UInt ai, UInt li, UInt ti)
+{
+ register ULong result asm("2") = 0;
+ register ULong input asm("3") = (ai << 4) | (li << 1) | ti;
+
+ asm volatile(".short 0xeb20\n\t"
+ ".long 0x3000004c\n\t"
+ : "=d" (result) : "d" (input));
+
+ return result;
+}
+
+static UInt
+get_cache_info_for_level(ULong topology, UInt level)
+{
+ return (topology >> (56 - level * 8)) & 0xff;
+}
+
+static ULong
+get_line_size(UInt level, Bool is_insn_cache)
+{
+ return ecag(1, level, is_insn_cache);
+}
+
+static ULong
+get_total_size(UInt level, Bool is_insn_cache)
+{
+ return ecag(2, level, is_insn_cache);
+}
+
+static ULong
+get_associativity(UInt level, Bool is_insn_cache)
+{
+ return ecag(3, level, is_insn_cache);
+}
+
+static VexCache
+get_cache(UInt level, VexCacheKind kind)
+{
+ Bool is_insn_cache = kind == INSN_CACHE;
+ UInt size = get_total_size(level, is_insn_cache);
+ UInt line_size = get_line_size(level, is_insn_cache);
+ UInt assoc = get_associativity(level, is_insn_cache);
+
+ return VEX_CACHE_INIT(kind, level + 1, size, line_size, assoc);
+}
+
static Bool
get_cache_info(VexArchInfo *vai)
{
- vai->hwcache_info.icaches_maintain_coherence = True;
+ VexCacheInfo *ci = &vai->hwcache_info;
- return False; // not yet
+ ci->icaches_maintain_coherence = True;
+
+ if (! vai->hwcaps & VEX_HWCAPS_S390X_GIE) {
+ // ECAG is not available
+ return False;
+ }
+
+ UInt level, cache_kind, info, i;
+ ULong topology = ecag(0, 0, 0); // get summary
+
+ /* ECAG supports at most 8 levels of cache. Find out how many levels
+ of cache and how many caches there are. */
+ ci->num_levels = 0;
+ ci->num_caches = 0;
+ for (level = 0; level < 8; level++) {
+ info = get_cache_info_for_level(topology, level);
+
+ if ((info & 0xc) == 0) break; // cache does not exist at this level
+ ++ci->num_levels;
+
+ cache_kind = info & 0x3;
+ switch (cache_kind) {
+ case 0: ci->num_caches += 2; break; /* separate data and insn cache */
+ case 1: ci->num_caches += 1; break; /* only insn cache */
+ case 2: ci->num_caches += 1; break; /* only data cache */
+ case 3: ci->num_caches += 1; break; /* unified data and insn cache */
+ }
+ }
+
+ ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof *ci->caches);
+
+ i = 0;
+ for (level = 0; level < ci->num_levels; level++) {
+ info = get_cache_info_for_level(topology, level);
+ cache_kind = info & 0x3;
+ switch (cache_kind) {
+ case 0: /* separate data and insn cache */
+ ci->caches[i++] = get_cache(level, INSN_CACHE);
+ ci->caches[i++] = get_cache(level, DATA_CACHE);
+ break;
+
+ case 1: /* only insn cache */
+ ci->caches[i++] = get_cache(level, INSN_CACHE);
+ break;
+
+ case 2: /* only data cache */
+ ci->caches[i++] = get_cache(level, DATA_CACHE);
+ break;
+
+ case 3: /* unified data and insn cache */
+ ci->caches[i++] = get_cache(level, UNIFIED_CACHE);
+ break;
+ }
+ }
+ return True;
}
#else
Modified: trunk/README.s390 (+4 -2)
===================================================================
--- trunk/README.s390 2012-11-02 21:36:39 +00:00 (rev 13099)
+++ trunk/README.s390 2012-11-02 22:00:59 +00:00 (rev 13100)
@@ -11,10 +11,12 @@
- 31-bit client programs are not supported.
- Hexadecimal floating point is not supported.
- Decimal floating point is not supported yet.
-- Currently, only memcheck, massif, lackey, and none are supported
+- memcheck, massif, lackey, and none are supported.
+- cachegrind is supported on z10 and newer models. On older models,
+ a z10 cache architecture will be assumed.
+- callgrind and all experimental tools are currently not supported.
- helgrind and drd seem to work on SLES10,11 and RHEL5,6 on z9,z10 and z196
but might fail on other hardware/software combinations.
-- exp-sgcheck, cachegrind, and callgrind are currently not supported.
- Some gcc versions use mvc to copy 4/8 byte values. This will affect some
debug messages. Valgrind will complain about 4 or 8 one-byte reads/writes
instead of just 1 read/write.
|